Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: tools/lexer_generator/code_generator.py

Issue 59823004: Exoerimental parser: jinja codegen templates (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright 2013 the V8 project authors. All rights reserved. 1 # Copyright 2013 the V8 project authors. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without 2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are 3 # modification, are permitted provided that the following conditions are
4 # met: 4 # met:
5 # 5 #
6 # * Redistributions of source code must retain the above copyright 6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer. 7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above 8 # * Redistributions in binary form must reproduce the above
9 # copyright notice, this list of conditions and the following 9 # copyright notice, this list of conditions and the following
10 # disclaimer in the documentation and/or other materials provided 10 # disclaimer in the documentation and/or other materials provided
11 # with the distribution. 11 # with the distribution.
12 # * Neither the name of Google Inc. nor the names of its 12 # * Neither the name of Google Inc. nor the names of its
13 # contributors may be used to endorse or promote products derived 13 # contributors may be used to endorse or promote products derived
14 # from this software without specific prior written permission. 14 # from this software without specific prior written permission.
15 # 15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 from dfa import Dfa 28 from dfa import Dfa
29 import jinja2
29 30
30 class CodeGenerator: 31 class CodeGenerator:
31 debug = False
32 32
33 @staticmethod 33 def __init__(self, rule_processor, use_mdfa, debug_print = False):
34 def key_to_code(key):
35 code = 'if ('
36 first = True
37 for (kind, r) in key.range_iter():
38 if kind == 'CLASS': # FIXME: add class checks
39 continue
40 assert kind == 'LATIN_1'
41 if not first:
42 code += ' || '
43 if r[0] == r[1]:
44 code += 'yych == %s' % r[0]
45 elif r[0] == 0:
46 code += 'yych <= %s' % r[1]
47 elif r[1] == 255: # FIXME: this should depend on the char type maybe??
48 code += 'yych >= %s' % r[0]
49 else:
50 code += '(yych >= %s && yych <= %s)' % (r[0], r[1])
51 first = False
52 code += ')'
53 return code
54
55 @staticmethod
56 def __terminate_code(value):
57 assert value == None
58 return 'PUSH_TOKEN(Token::EOS); return 0;'
59
60 @staticmethod
61 def __terminate_illegal_code(value):
62 assert value == None
63 return 'PUSH_TOKEN(Token::ILLEGAL); return 1;'
64
65 @staticmethod
66 def __skip_code(value):
67 assert value == None
68 return 'SKIP();'
69
70 @staticmethod
71 def __push_line_terminator_code(value):
72 assert value == None
73 return 'PUSH_LINE_TERMINATOR();'
74
75 @staticmethod
76 def __push_token_code(value):
77 assert value != None
78 return 'PUSH_TOKEN(Token::%s);' % value
79
80 @staticmethod
81 def __code_code(value):
82 assert value != None
83 return '%s\n' % value
84
85 @staticmethod
86 def __skip_and_terminate_code(value):
87 return 'SKIP(); --start_; ' + CodeGenerator.__terminate_code(value)
88
89 def __init__(self, dfa, default_action):
90 self.__dfa = dfa
91 self.__start_node_number = dfa.start_state().node_number()
92 self.__default_action = default_action
93 # make this better
94 self.__action_code_map = {
95 "terminate" : self.__terminate_code,
96 "terminate_illegal" : self.__terminate_illegal_code,
97 "push_token" : self.__push_token_code,
98 "push_line_terminator" : self.__push_line_terminator_code,
99 "skip" : self.__skip_code,
100 "code" : self.__code_code,
101 "skip_and_terminate" : self.__skip_and_terminate_code,
102 }
103
104 def __dfa_state_to_code(self, state):
105 # FIXME: add different check types (if, switch, lookup table)
106 # FIXME: add action + break / continue
107 # FIXME: add default action
108 code = ''
109 if self.__start_node_number == state.node_number():
110 code += '''
111 code_start:
112 '''
113
114 code += '''
115 code_%s:
116 ''' % state.node_number()
117
118 if CodeGenerator.debug:
119 code += '''
120 fprintf(stderr, "state %s\\n");
121 ''' % state.node_number()
122
123 entry_action = state.action().entry_action() if state.action() else None
124 match_action = state.action().match_action() if state.action() else None
125
126 if entry_action:
127 code += self.__action_code_map[entry_action[0]](entry_action[1])
128
129 if CodeGenerator.debug:
130 code += '''
131 fprintf(stderr, "char at hand is %c (%d)\\n", yych, yych);
132 '''
133
134 for key, s in state.transitions().items():
135 code += CodeGenerator.key_to_code(key)
136 code += ''' {
137 FORWARD();
138 goto code_%s;
139 }
140 ''' % s.node_number()
141
142 if match_action:
143 code += self.__action_code_map[match_action[0]](match_action[1])
144 code += 'goto code_%s;\n' % self.__start_node_number
145 else:
146 code += 'goto default_action;\n'
147 return code
148
149 def __process(self):
150 dfa = self.__dfa
151 default_action = self.__default_action
152 code = '''
153 #include "lexer/even-more-experimental-scanner.h"
154
155 namespace v8 {
156 namespace internal {
157 uint32_t EvenMoreExperimentalScanner::DoLex() {
158 YYCTYPE yych = *cursor_;
159 goto code_%s;
160 ''' % self.__start_node_number
161 def f(state, code):
162 code += self.__dfa_state_to_code(state)
163 return code
164 code = dfa.visit_all_states(f, code)
165
166 default_action_code = ''
167 assert(default_action and default_action.match_action())
168 action = default_action.match_action()
169 default_action_code = self.__action_code_map[action[0]](action[1])
170 code += '''
171 CHECK(false); goto code_start;
172 default_action:'''
173 if CodeGenerator.debug:
174 code += '''
175 fprintf(stderr, "default action\\n");
176 '''
177 code += '''
178 %s
179 FORWARD();
180 goto code_%s;
181 return 0;
182 }
183 }
184 }
185 ''' % (default_action_code, self.__start_node_number)
186 return code
187
188 @staticmethod
189 def rule_processor_to_code(rule_processor, use_mdfa):
190 if use_mdfa: 34 if use_mdfa:
191 dfa = rule_processor.default_automata().minimal_dfa() 35 dfa = rule_processor.default_automata().minimal_dfa()
192 else: 36 else:
193 dfa = rule_processor.default_automata().dfa() 37 dfa = rule_processor.default_automata().dfa()
194 return CodeGenerator(dfa, rule_processor.default_action).__process() 38 self.__dfa = dfa
39 self.__default_action = rule_processor.default_action
40 self.__debug_print = debug_print
41
42 def process(self):
43
44 start_node_number = self.__dfa.start_state().node_number()
45
46 dfa_states = []
47 self.__dfa.visit_all_states(lambda state, acc: dfa_states.append(state))
48
49 default_action = self.__default_action
50 assert(default_action and default_action.match_action())
51 default_action = default_action.match_action()
52
53 template_env = jinja2.Environment(
54 loader = jinja2.PackageLoader('lexer_generator', '.'),
55 undefined = jinja2.StrictUndefined)
56 template = template_env.get_template('code_generator.jinja')
57
58 return template.render(
59 start_node_number = start_node_number,
60 debug_print = self.__debug_print,
61 default_action = default_action,
62 dfa_states = dfa_states)
OLDNEW
« no previous file with comments | « tools/lexer_generator/code_generator.jinja ('k') | tools/lexer_generator/code_generator_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698