| OLD | NEW |
| 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 17 matching lines...) Expand all Loading... |
| 28 import os | 28 import os |
| 29 import sys | 29 import sys |
| 30 import jinja2 | 30 import jinja2 |
| 31 from dfa import Dfa | 31 from dfa import Dfa |
| 32 from transition_keys import TransitionKey | 32 from transition_keys import TransitionKey |
| 33 | 33 |
| 34 class CodeGenerator: | 34 class CodeGenerator: |
| 35 | 35 |
| 36 def __init__(self, | 36 def __init__(self, |
| 37 rule_processor, | 37 rule_processor, |
| 38 encoding = 'latin1', | |
| 39 minimize_default = True, | 38 minimize_default = True, |
| 40 inline = True, | 39 inline = True, |
| 41 switching = True, | 40 switching = True, |
| 42 debug_print = False, | 41 debug_print = False, |
| 43 log = False): | 42 log = False): |
| 44 if minimize_default: | 43 if minimize_default: |
| 45 dfa = rule_processor.default_automata().minimal_dfa() | 44 dfa = rule_processor.default_automata().minimal_dfa() |
| 46 else: | 45 else: |
| 47 dfa = rule_processor.default_automata().dfa() | 46 dfa = rule_processor.default_automata().dfa() |
| 48 self.__dfa = dfa | 47 self.__dfa = dfa |
| 49 self.__default_action = rule_processor.default_action | 48 self.__default_action = rule_processor.default_action |
| 50 self.__debug_print = debug_print | 49 self.__debug_print = debug_print |
| 51 self.__start_node_number = self.__dfa.start_state().node_number() | 50 self.__start_node_number = self.__dfa.start_state().node_number() |
| 52 self.__log = log | 51 self.__log = log |
| 53 self.__inline = inline | 52 self.__inline = inline |
| 54 self.__switching = switching | 53 self.__switching = switching |
| 55 self.__encoding = encoding | |
| 56 | 54 |
| 57 def __state_cmp(self, left, right): | 55 def __state_cmp(self, left, right): |
| 58 if left['original_node_number'] == self.__start_node_number: | 56 if left['original_node_number'] == self.__start_node_number: |
| 59 return -1 | 57 return -1 |
| 60 if right['original_node_number'] == self.__start_node_number: | 58 if right['original_node_number'] == self.__start_node_number: |
| 61 return 1 | 59 return 1 |
| 62 c = cmp(len(left['disjoint_keys']), len(right['disjoint_keys'])) | 60 c = cmp(len(left['disjoint_keys']), len(right['disjoint_keys'])) |
| 63 if c: | 61 if c: |
| 64 return c | 62 return c |
| 65 c = cmp(left['disjoint_keys'], right['disjoint_keys']) | 63 c = cmp(left['disjoint_keys'], right['disjoint_keys']) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 89 return cmp(left[1], right[1]) | 87 return cmp(left[1], right[1]) |
| 90 assert right[0] == 'CLASS' | 88 assert right[0] == 'CLASS' |
| 91 return -1 | 89 return -1 |
| 92 assert left[0] == 'CLASS' | 90 assert left[0] == 'CLASS' |
| 93 if right[0] == 'LATIN_1': | 91 if right[0] == 'LATIN_1': |
| 94 return 1 | 92 return 1 |
| 95 # TODO store numeric values and cmp | 93 # TODO store numeric values and cmp |
| 96 return cmp(left[1], right[1]) | 94 return cmp(left[1], right[1]) |
| 97 | 95 |
| 98 @staticmethod | 96 @staticmethod |
| 99 def __transform_state(state): | 97 def __transform_state(encoding, state): |
| 100 # action data | 98 # action data |
| 101 action = state.action() | 99 action = state.action() |
| 102 entry_action = None if not action else action.entry_action() | 100 entry_action = None if not action else action.entry_action() |
| 103 match_action = None if not action else action.match_action() | 101 match_action = None if not action else action.match_action() |
| 104 # generate ordered transitions | 102 # generate ordered transitions |
| 105 transitions = map(lambda (k, v) : (k, v.node_number()), | 103 transitions = map(lambda (k, v) : (k, v.node_number()), |
| 106 state.transitions().items()) | 104 state.transitions().items()) |
| 107 def cmp(left, right): | 105 def cmp(left, right): |
| 108 return TransitionKey.canonical_compare(left[0], right[0]) | 106 return TransitionKey.canonical_compare(left[0], right[0]) |
| 109 transitions = sorted(transitions, cmp) | 107 transitions = sorted(transitions, cmp) |
| 110 # map transition keys to disjoint ranges | 108 # map transition keys to disjoint ranges |
| 111 disjoint_keys = {'value' : []} | 109 disjoint_keys = {'value' : []} |
| 112 def f((key, state)): | 110 def f((key, state)): |
| 113 ranges = list(key.range_iter()) | 111 ranges = list(key.range_iter(encoding)) |
| 114 disjoint_keys['value'] += ranges | 112 disjoint_keys['value'] += ranges |
| 115 return (ranges, state) | 113 return (ranges, state) |
| 116 transitions = map(f, transitions) | 114 transitions = map(f, transitions) |
| 117 disjoint_keys = sorted(disjoint_keys['value'], CodeGenerator.__range_cmp) | 115 disjoint_keys = sorted(disjoint_keys['value'], CodeGenerator.__range_cmp) |
| 118 # dictionary object representing state | 116 # dictionary object representing state |
| 119 (class_keys, distinct_keys, ranges) = (0, 0, 0) | 117 (class_keys, distinct_keys, ranges) = (0, 0, 0) |
| 120 for (t, r) in disjoint_keys: | 118 for (t, r) in disjoint_keys: |
| 121 if t == 'CLASS': | 119 if t == 'CLASS': |
| 122 class_keys += 1 | 120 class_keys += 1 |
| 123 elif t == 'LATIN_1': | 121 elif t == 'LATIN_1': |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if d: | 194 if d: |
| 197 deferred_transitions.append((d, node_id)) | 195 deferred_transitions.append((d, node_id)) |
| 198 state['transitions'] = if_transitions | 196 state['transitions'] = if_transitions |
| 199 state['switch_transitions'] = switch_transitions | 197 state['switch_transitions'] = switch_transitions |
| 200 state['deferred_transitions'] = deferred_transitions | 198 state['deferred_transitions'] = deferred_transitions |
| 201 return split_count + (0 if no_switch else 1) | 199 return split_count + (0 if no_switch else 1) |
| 202 | 200 |
| 203 def __canonicalize_traversal(self): | 201 def __canonicalize_traversal(self): |
| 204 dfa_states = [] | 202 dfa_states = [] |
| 205 self.__dfa.visit_all_states(lambda state, acc: dfa_states.append(state)) | 203 self.__dfa.visit_all_states(lambda state, acc: dfa_states.append(state)) |
| 206 dfa_states = map(CodeGenerator.__transform_state, dfa_states) | 204 encoding = self.__dfa.encoding() |
| 205 f = lambda state : CodeGenerator.__transform_state(encoding, state) |
| 206 dfa_states = map(f, dfa_states) |
| 207 id_map = {x['original_node_number'] : x for x in dfa_states} | 207 id_map = {x['original_node_number'] : x for x in dfa_states} |
| 208 CodeGenerator.__compute_depths(self.__start_node_number, 1, id_map) | 208 CodeGenerator.__compute_depths(self.__start_node_number, 1, id_map) |
| 209 dfa_states = sorted(dfa_states, cmp=self.__state_cmp) | 209 dfa_states = sorted(dfa_states, cmp=self.__state_cmp) |
| 210 # remap all node numbers | 210 # remap all node numbers |
| 211 for i, state in enumerate(dfa_states): | 211 for i, state in enumerate(dfa_states): |
| 212 state['node_number'] = i | 212 state['node_number'] = i |
| 213 def f((key, original_node_number)): | 213 def f((key, original_node_number)): |
| 214 return (key, id_map[original_node_number]['node_number']) | 214 return (key, id_map[original_node_number]['node_number']) |
| 215 for state in dfa_states: | 215 for state in dfa_states: |
| 216 state['transitions'] = map(f, state['transitions']) | 216 state['transitions'] = map(f, state['transitions']) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 239 default_action = self.__default_action | 239 default_action = self.__default_action |
| 240 assert(default_action and default_action.match_action()) | 240 assert(default_action and default_action.match_action()) |
| 241 default_action = default_action.match_action() | 241 default_action = default_action.match_action() |
| 242 | 242 |
| 243 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | 243 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 244 template_env = jinja2.Environment( | 244 template_env = jinja2.Environment( |
| 245 loader = jinja2.PackageLoader('lexer_generator', '.'), | 245 loader = jinja2.PackageLoader('lexer_generator', '.'), |
| 246 undefined = jinja2.StrictUndefined) | 246 undefined = jinja2.StrictUndefined) |
| 247 template = template_env.get_template('code_generator.jinja') | 247 template = template_env.get_template('code_generator.jinja') |
| 248 | 248 |
| 249 if self.__encoding == 'latin1': | 249 encoding = self.__dfa.encoding().name() |
| 250 if encoding == 'latin1': |
| 250 char_type = 'uint8_t' | 251 char_type = 'uint8_t' |
| 251 elif self.__encoding == 'utf16': | 252 elif encoding == 'utf16': |
| 252 char_type = 'uint16_t' | 253 char_type = 'uint16_t' |
| 253 else: | 254 else: |
| 254 raise Exception('Unsupported encoding %s' % encoding) | 255 raise Exception('Unsupported encoding %s' % encoding) |
| 255 return template.render( | 256 return template.render( |
| 256 start_node_number = 0, | 257 start_node_number = 0, |
| 257 debug_print = self.__debug_print, | 258 debug_print = self.__debug_print, |
| 258 default_action = default_action, | 259 default_action = default_action, |
| 259 dfa_states = dfa_states, | 260 dfa_states = dfa_states, |
| 260 encoding = self.__encoding, | 261 encoding = encoding, |
| 261 char_type = char_type) | 262 char_type = char_type) |
| OLD | NEW |