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

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

Issue 134153014: Experimental parser: introduce jump abstractions (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 11 months 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
« no previous file with comments | « tools/lexer_generator/code_generator.jinja ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 dfa = rule_processor.default_automata().minimal_dfa() 44 dfa = rule_processor.default_automata().minimal_dfa()
45 else: 45 else:
46 dfa = rule_processor.default_automata().dfa() 46 dfa = rule_processor.default_automata().dfa()
47 self.__dfa = dfa 47 self.__dfa = dfa
48 self.__default_action = rule_processor.default_action 48 self.__default_action = rule_processor.default_action
49 self.__debug_print = debug_print 49 self.__debug_print = debug_print
50 self.__start_node_number = self.__dfa.start_state().node_number() 50 self.__start_node_number = self.__dfa.start_state().node_number()
51 self.__log = log 51 self.__log = log
52 self.__inline = inline 52 self.__inline = inline
53 self.__switching = switching 53 self.__switching = switching
54 self.__jump_table = []
55
56 __jump_labels = ['state_entry', 'after_entry_code']
54 57
55 @staticmethod 58 @staticmethod
56 def __transform_state(encoding, state): 59 def __transform_state(encoding, state):
57 # action data 60 # action data
58 action = state.action() 61 action = state.action()
59 entry_action = None if not action else action.entry_action() 62 entry_action = None if not action else action.entry_action()
60 match_action = None if not action else action.match_action() 63 match_action = None if not action else action.match_action()
61 # generate ordered transitions 64 # generate ordered transitions
62 transitions = map(lambda (k, v) : (k, v.node_number()), 65 transitions = map(lambda (k, v) : (k, v.node_number()),
63 state.transitions().items()) 66 state.transitions().items())
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 'long_char_transitions' : [], 107 'long_char_transitions' : [],
105 'unique_transitions' : unique_transitions, 108 'unique_transitions' : unique_transitions,
106 # state actions 109 # state actions
107 'entry_action' : entry_action, 110 'entry_action' : entry_action,
108 'match_action' : match_action, 111 'match_action' : match_action,
109 # statistics for states 112 # statistics for states
110 'class_keys' : class_keys, 113 'class_keys' : class_keys,
111 'distinct_keys' : distinct_keys, 114 'distinct_keys' : distinct_keys,
112 'ranges' : ranges, 115 'ranges' : ranges,
113 # record of which entry points will be needed 116 # record of which entry points will be needed
114 'entry_points' : { 117 'entry_points' : {k : False for k in CodeGenerator.__jump_labels}
115 'state_entry' : True,
116 'after_entry_code' : False,
117 # 'before_match' : False,
118 # 'before_deferred' : False,
119 }
120 } 118 }
121 119
120 def __register_jump(self, node_id, label):
121 assert label in CodeGenerator.__jump_labels
122 state = self.__dfa_states[node_id]['entry_points'][label] = True
123 self.__jump_table.append((node_id, label))
124 return len(self.__jump_table) - 1
125
122 def __set_inline(self, count, state): 126 def __set_inline(self, count, state):
123 assert state['inline'] == None 127 assert state['inline'] == None
124 inline = False 128 inline = False
125 # inline terminal states 129 # inline terminal states
126 if not state['transitions']: 130 if not state['transitions']:
127 inline = True 131 inline = True
128 # inline next to terminal states with 1 or 2 transitions 132 # inline next to terminal states with 1 or 2 transitions
129 elif state['distinct_keys'] < 3 and state['class_keys'] == 0: 133 elif state['distinct_keys'] < 3 and state['class_keys'] == 0:
130 inline = True 134 inline = True
131 # ensure state terminates in 1 step 135 # ensure state terminates in 1 step
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 state['match_action'][0] == 'do_stored_token'): 279 state['match_action'][0] == 'do_stored_token'):
276 assert not state['match_action'][1] in goto_map 280 assert not state['match_action'][1] in goto_map
277 goto_map[state['match_action'][1]] = state['node_number'] 281 goto_map[state['match_action'][1]] = state['node_number']
278 mapped_actions = set([ 282 mapped_actions = set([
279 'store_harmony_token_and_goto', 283 'store_harmony_token_and_goto',
280 'store_token_and_goto', 284 'store_token_and_goto',
281 'goto_start']) 285 'goto_start'])
282 for state in states: 286 for state in states:
283 if not state['match_action']: 287 if not state['match_action']:
284 continue 288 continue
285 if state['match_action'][0] in mapped_actions: 289 action = state['match_action'][0]
290 if action in mapped_actions:
286 value = state['match_action'][1] 291 value = state['match_action'][1]
287 value = tuple(list(value[:-1]) + [goto_map[value[-1]]]) 292 target_id = goto_map[value[-1]]
288 state['match_action'] = (state['match_action'][0], value) 293 if action != 'goto_start':
289 if state['match_action'][0] != 'goto_start':
290 states[value[-1]]['entry_points']['after_entry_code'] = True
291 state['can_elide_read'] = False 294 state['can_elide_read'] = False
295 label = 'after_entry_code'
292 else: 296 else:
293 states[value[-1]]['can_elide_read'] = False 297 states[target_id]['can_elide_read'] = False
298 label = 'state_entry'
299 jump_label = self.__register_jump(target_id, label)
300 state['match_action'] = (action, tuple(list(value[:-1]) + [jump_label]))
294 301
295 @staticmethod 302 def __rewrite_transitions_to_jumps(self):
296 def __mark_entry_points(dfa_states): 303 transition_names = [
304 'if_transitions',
305 'switch_transitions',
306 'deferred_transitions',
307 'long_char_transitions']
308 def f((key, target_id)):
309 return (key, self.__register_jump(target_id, 'state_entry'))
310 for state in self.__dfa_states:
311 for name in transition_names:
312 state[name] = map(f, state[name])
313
314 def __mark_entry_points(self):
315 # mark the entry point in case there are implicit jumps to it
316 self.__dfa_states[0]['entry_points']['state_entry'] = True
297 # inlined states can write no labels 317 # inlined states can write no labels
298 for state in dfa_states: 318 for state in self.__dfa_states:
299 entry_points = state['entry_points'] 319 entry_points = state['entry_points']
300 if state['inline']: 320 if state['inline']:
301 for k in entry_points.keys(): 321 for k in entry_points.keys():
302 entry_points[k] = False 322 entry_points[k] = False
303 323
304 def process(self): 324 def process(self):
305 325
306 self.__build_dfa_states() 326 self.__build_dfa_states()
307 self.__rewrite_gotos()
308
309 dfa_states = self.__dfa_states 327 dfa_states = self.__dfa_states
310 # set nodes to inline
311 if self.__inline:
312 inlined = reduce(self.__set_inline, dfa_states, 0)
313 if self.__log:
314 print "%s states inlined" % inlined
315 elif self.__log:
316 print "no inlining"
317 # split transitions 328 # split transitions
318 switched = reduce(self.__split_transitions, dfa_states, 0) 329 switched = reduce(self.__split_transitions, dfa_states, 0)
319 if self.__log: 330 if self.__log:
320 print "%s states use switch (instead of if)" % switched 331 print "%s states use switch (instead of if)" % switched
321 # rewrite deferred transitions 332 # rewrite deferred transitions
322 for state in dfa_states: 333 for state in dfa_states:
323 self.__rewrite_deferred_transitions(state) 334 self.__rewrite_deferred_transitions(state)
335 # rewrite gotos
336 self.__rewrite_gotos()
337 # rewrite transitions to use jumps
338 self.__rewrite_transitions_to_jumps()
339 # set nodes to inline
340 if self.__inline:
341 inlined = reduce(self.__set_inline, dfa_states, 0)
342 if self.__log:
343 print "%s states inlined" % inlined
344 elif self.__log:
345 print "no inlining"
324 # mark all the entry points that will be used 346 # mark all the entry points that will be used
325 self.__mark_entry_points(dfa_states) 347 self.__mark_entry_points()
326 348
327 default_action = self.__default_action 349 default_action = self.__default_action
328 assert(default_action and default_action.match_action()) 350 assert(default_action and default_action.match_action())
329 default_action = default_action.match_action() 351 default_action = default_action.match_action()
330 352
331 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 353 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
332 template_env = jinja2.Environment( 354 template_env = jinja2.Environment(
333 loader = jinja2.PackageLoader('lexer_generator', '.'), 355 loader = jinja2.PackageLoader('lexer_generator', '.'),
334 undefined = jinja2.StrictUndefined) 356 undefined = jinja2.StrictUndefined)
335 template = template_env.get_template('code_generator.jinja') 357 template = template_env.get_template('code_generator.jinja')
336 358
337 encoding = self.__dfa.encoding() 359 encoding = self.__dfa.encoding()
338 char_types = {'latin1': 'uint8_t', 'utf16': 'uint16_t', 'utf8': 'int8_t'} 360 char_types = {'latin1': 'uint8_t', 'utf16': 'uint16_t', 'utf8': 'int8_t'}
339 char_type = char_types[encoding.name()] 361 char_type = char_types[encoding.name()]
340 362
341 return template.render( 363 return template.render(
342 start_node_number = 0, 364 start_node_number = 0,
343 debug_print = self.__debug_print, 365 debug_print = self.__debug_print,
344 default_action = default_action, 366 default_action = default_action,
345 dfa_states = dfa_states, 367 dfa_states = dfa_states,
368 jump_table = self.__jump_table,
346 encoding = encoding.name(), 369 encoding = encoding.name(),
347 char_type = char_type, 370 char_type = char_type,
348 upper_bound = encoding.primary_range()[1]) 371 upper_bound = encoding.primary_range()[1])
OLDNEW
« no previous file with comments | « tools/lexer_generator/code_generator.jinja ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698