| 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 15 matching lines...) Expand all Loading... |
| 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 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, rule_processor, use_mdfa, debug_print = False): | 36 def __init__(self, |
| 37 if use_mdfa: | 37 rule_processor, |
| 38 minimize_default = True, |
| 39 inline = True, |
| 40 debug_print = False, |
| 41 log = False): |
| 42 if minimize_default: |
| 38 dfa = rule_processor.default_automata().minimal_dfa() | 43 dfa = rule_processor.default_automata().minimal_dfa() |
| 39 else: | 44 else: |
| 40 dfa = rule_processor.default_automata().dfa() | 45 dfa = rule_processor.default_automata().dfa() |
| 41 self.__dfa = dfa | 46 self.__dfa = dfa |
| 42 self.__default_action = rule_processor.default_action | 47 self.__default_action = rule_processor.default_action |
| 43 self.__debug_print = debug_print | 48 self.__debug_print = debug_print |
| 44 self.__start_node_number = self.__dfa.start_state().node_number() | 49 self.__start_node_number = self.__dfa.start_state().node_number() |
| 50 self.__log = log |
| 51 self.__inline = inline |
| 45 | 52 |
| 46 def __state_cmp(self, left, right): | 53 def __state_cmp(self, left, right): |
| 47 if left['original_node_number'] == self.__start_node_number: | 54 if left['original_node_number'] == self.__start_node_number: |
| 48 return -1 | 55 return -1 |
| 49 if right['original_node_number'] == self.__start_node_number: | 56 if right['original_node_number'] == self.__start_node_number: |
| 50 return 1 | 57 return 1 |
| 51 c = cmp(len(left['disjoint_keys']), len(right['disjoint_keys'])) | 58 c = cmp(len(left['disjoint_keys']), len(right['disjoint_keys'])) |
| 52 if c: | 59 if c: |
| 53 return c | 60 return c |
| 54 c = cmp(left['disjoint_keys'], right['disjoint_keys']) | 61 c = cmp(left['disjoint_keys'], right['disjoint_keys']) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 state.transitions().items()) | 109 state.transitions().items()) |
| 103 def cmp(left, right): | 110 def cmp(left, right): |
| 104 return TransitionKey.canonical_compare(left[0], right[0]) | 111 return TransitionKey.canonical_compare(left[0], right[0]) |
| 105 transitions = sorted(transitions, cmp) | 112 transitions = sorted(transitions, cmp) |
| 106 # dictionary object representing state | 113 # dictionary object representing state |
| 107 return { | 114 return { |
| 108 'node_number' : state.node_number(), | 115 'node_number' : state.node_number(), |
| 109 'original_node_number' : state.node_number(), | 116 'original_node_number' : state.node_number(), |
| 110 'transitions' : transitions, | 117 'transitions' : transitions, |
| 111 'disjoint_keys' : keys, | 118 'disjoint_keys' : keys, |
| 112 'inline' : False, | 119 'inline' : None, |
| 113 'depth' : None, | 120 'depth' : None, |
| 114 'action' : action, | 121 'action' : action, |
| 115 'entry_action' : entry_action, | 122 'entry_action' : entry_action, |
| 116 'match_action' : match_action, | 123 'match_action' : match_action, |
| 117 } | 124 } |
| 118 | 125 |
| 119 @staticmethod | 126 @staticmethod |
| 120 def __compute_depths(node_number, depth, id_map): | 127 def __compute_depths(node_number, depth, id_map): |
| 121 state = id_map[node_number] | 128 state = id_map[node_number] |
| 122 if state['depth'] != None: | 129 if state['depth'] != None: |
| 123 return | 130 return |
| 124 state['depth'] = depth | 131 state['depth'] = depth |
| 125 for (k, transition_node) in state['transitions']: | 132 for (k, transition_node) in state['transitions']: |
| 126 CodeGenerator.__compute_depths(transition_node, depth + 1, id_map) | 133 CodeGenerator.__compute_depths(transition_node, depth + 1, id_map) |
| 127 | 134 |
| 135 @staticmethod |
| 136 def __set_inline(count, state): |
| 137 assert state['inline'] == None |
| 138 inline = False |
| 139 if not state['transitions']: |
| 140 inline = True |
| 141 state['inline'] = inline |
| 142 return count + 1 if inline else count |
| 143 |
| 128 def __canonicalize_traversal(self): | 144 def __canonicalize_traversal(self): |
| 129 dfa_states = [] | 145 dfa_states = [] |
| 130 self.__dfa.visit_all_states(lambda state, acc: dfa_states.append(state)) | 146 self.__dfa.visit_all_states(lambda state, acc: dfa_states.append(state)) |
| 131 dfa_states = map(CodeGenerator.__transform_state, dfa_states) | 147 dfa_states = map(CodeGenerator.__transform_state, dfa_states) |
| 132 id_map = {x['original_node_number'] : x for x in dfa_states} | 148 id_map = {x['original_node_number'] : x for x in dfa_states} |
| 133 CodeGenerator.__compute_depths(self.__start_node_number, 1, id_map) | 149 CodeGenerator.__compute_depths(self.__start_node_number, 1, id_map) |
| 134 dfa_states = sorted(dfa_states, cmp=self.__state_cmp) | 150 dfa_states = sorted(dfa_states, cmp=self.__state_cmp) |
| 135 # remap all node numbers | 151 # remap all node numbers |
| 136 for i, state in enumerate(dfa_states): | 152 for i, state in enumerate(dfa_states): |
| 137 state['node_number'] = i | 153 state['node_number'] = i |
| 138 def f((key, original_node_number)): | 154 def f((key, original_node_number)): |
| 139 return (key, id_map[original_node_number]['node_number']) | 155 return (key, id_map[original_node_number]['node_number']) |
| 140 for state in dfa_states: | 156 for state in dfa_states: |
| 141 state['transitions'] = map(f, state['transitions']) | 157 state['transitions'] = map(f, state['transitions']) |
| 142 assert id_map[self.__start_node_number]['node_number'] == 0 | 158 assert id_map[self.__start_node_number]['node_number'] == 0 |
| 159 assert len(dfa_states) == self.__dfa.node_count() |
| 160 # set nodes to inline |
| 161 if self.__inline: |
| 162 inlined = reduce(CodeGenerator.__set_inline, dfa_states, 0) |
| 163 if self.__log: |
| 164 print "inlined %s" % inlined |
| 165 elif self.__log: |
| 166 print "no inlining" |
| 143 self.__dfa_states = dfa_states | 167 self.__dfa_states = dfa_states |
| 144 | 168 |
| 145 def process(self): | 169 def process(self): |
| 146 | 170 |
| 147 self.__canonicalize_traversal() | 171 self.__canonicalize_traversal() |
| 148 | 172 |
| 149 start_node_number = self.__start_node_number | |
| 150 dfa_states = self.__dfa_states | 173 dfa_states = self.__dfa_states |
| 151 assert len(dfa_states) == self.__dfa.node_count() | |
| 152 assert dfa_states[0]['node_number'] == 0 | |
| 153 | 174 |
| 154 default_action = self.__default_action | 175 default_action = self.__default_action |
| 155 assert(default_action and default_action.match_action()) | 176 assert(default_action and default_action.match_action()) |
| 156 default_action = default_action.match_action() | 177 default_action = default_action.match_action() |
| 157 | 178 |
| 158 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | 179 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 159 template_env = jinja2.Environment( | 180 template_env = jinja2.Environment( |
| 160 loader = jinja2.PackageLoader('lexer_generator', '.'), | 181 loader = jinja2.PackageLoader('lexer_generator', '.'), |
| 161 undefined = jinja2.StrictUndefined) | 182 undefined = jinja2.StrictUndefined) |
| 162 template = template_env.get_template('code_generator.jinja') | 183 template = template_env.get_template('code_generator.jinja') |
| 163 | 184 |
| 164 return template.render( | 185 return template.render( |
| 165 start_node_number = 0, | 186 start_node_number = 0, |
| 166 debug_print = self.__debug_print, | 187 debug_print = self.__debug_print, |
| 167 default_action = default_action, | 188 default_action = default_action, |
| 168 dfa_states = dfa_states) | 189 dfa_states = dfa_states) |
| OLD | NEW |