| 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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 (start, ends) = self.__process(subtree) | 149 (start, ends) = self.__process(subtree) |
| 150 state = self.__peek_state() | 150 state = self.__peek_state() |
| 151 if not state['start_node']: | 151 if not state['start_node']: |
| 152 state['start_node'] = self.__new_state() | 152 state['start_node'] = self.__new_state() |
| 153 self.__patch_ends(ends, state['start_node']) | 153 self.__patch_ends(ends, state['start_node']) |
| 154 return (start, []) | 154 return (start, []) |
| 155 | 155 |
| 156 def __unique_key(self, name): | 156 def __unique_key(self, name): |
| 157 return self.__key_state(TransitionKey.unique(name)) | 157 return self.__key_state(TransitionKey.unique(name)) |
| 158 | 158 |
| 159 def __join(self, graph, name, subgraph): | 159 def __join(self, tree, subtree): |
| 160 subgraphs = self.__peek_state()['subgraphs'] | 160 (subtree_start, subtree_end, nodes_in_subtree) = self.__nfa(subtree) |
| 161 if not name in subgraphs: | 161 (start, ends) = self.__process(tree) |
| 162 subgraphs[name] = self.__nfa(subgraph) | 162 self.__patch_ends(ends, subtree_start) |
| 163 (subgraph_start, subgraph_end, nodes_in_subgraph) = subgraphs[name] | 163 if subtree_end: |
| 164 (start, ends) = self.__process(graph) | 164 return (start, [subtree_end]) |
| 165 self.__patch_ends(ends, subgraph_start) | |
| 166 if subgraph_end: | |
| 167 end = self.__new_state() | |
| 168 subgraph_end.add_epsilon_transition(end) | |
| 169 return (start, [end]) | |
| 170 else: | 165 else: |
| 171 return (start, []) | 166 return (start, []) |
| 172 | 167 |
| 173 def __process(self, term): | 168 def __process(self, term): |
| 174 assert isinstance(term, Term) | 169 assert isinstance(term, Term) |
| 175 method = "_NfaBuilder__" + term.name().lower() | 170 method = "_NfaBuilder__" + term.name().lower() |
| 176 if not method in self.__operation_map: | 171 if not method in self.__operation_map: |
| 177 matches = filter(lambda (name, func): name == method, self.__members) | 172 matches = filter(lambda (name, func): name == method, self.__members) |
| 178 assert len(matches) == 1 | 173 assert len(matches) == 1 |
| 179 self.__operation_map[method] = matches[0][1] | 174 self.__operation_map[method] = matches[0][1] |
| 180 return self.__operation_map[method](*term.args()) | 175 return self.__operation_map[method](*term.args()) |
| 181 | 176 |
| 182 def __patch_ends(self, ends, new_end): | 177 def __patch_ends(self, ends, new_end): |
| 183 for end in ends: | 178 for end in ends: |
| 184 end.close(new_end) | 179 end.close(new_end) |
| 185 | 180 |
| 186 def __push_state(self): | 181 def __push_state(self): |
| 187 self.__states.append({ | 182 self.__states.append({ |
| 188 'start_node' : None, | 183 'start_node' : None, |
| 189 'subgraphs' : {}, | |
| 190 'unpatched_ends' : [], | |
| 191 }) | 184 }) |
| 192 | 185 |
| 193 def __pop_state(self): | 186 def __pop_state(self): |
| 194 return self.__states.pop() | 187 return self.__states.pop() |
| 195 | 188 |
| 196 def __peek_state(self): | 189 def __peek_state(self): |
| 197 return self.__states[-1] | 190 return self.__states[-1] |
| 198 | 191 |
| 199 def __nfa(self, term): | 192 def __nfa(self, term): |
| 200 start_node_number = self.__node_number | 193 start_node_number = self.__node_number |
| 201 self.__push_state() | 194 self.__push_state() |
| 202 (start, ends) = self.__process(term) | 195 (start, ends) = self.__process(term) |
| 203 state = self.__pop_state() | 196 state = self.__pop_state() |
| 204 if state['start_node']: | 197 if state['start_node']: |
| 205 state['start_node'].close(start) | 198 state['start_node'].close(start) |
| 206 start = state['start_node'] | 199 start = state['start_node'] |
| 207 for k, subgraph in state['subgraphs'].items(): | |
| 208 if subgraph[1]: | |
| 209 subgraph[1].close(None) | |
| 210 | |
| 211 # Don't create an end node for the subgraph if it would be unused (ends can | 200 # Don't create an end node for the subgraph if it would be unused (ends can |
| 212 # be an empty list e.g., in the case when everything inside the subgraph is | 201 # be an empty list e.g., in the case when everything inside the subgraph is |
| 213 # "continue"). | 202 # "continue"). |
| 214 end = None | 203 end = None |
| 215 if ends: | 204 if ends: |
| 216 end = self.__new_state() | 205 end = self.__new_state() |
| 217 self.__patch_ends(ends, end) | 206 self.__patch_ends(ends, end) |
| 218 | |
| 219 return (start, end, self.__node_number - start_node_number) | 207 return (start, end, self.__node_number - start_node_number) |
| 220 | 208 |
| 221 @staticmethod | 209 @staticmethod |
| 222 def __compute_epsilon_closures(start_state): | 210 def __compute_epsilon_closures(start_state): |
| 223 def outer(node, state): | 211 def outer(node, state): |
| 224 def inner(node, closure): | 212 def inner(node, closure): |
| 225 closure.add(node) | 213 closure.add(node) |
| 226 return closure | 214 return closure |
| 227 is_epsilon = lambda k: k == TransitionKey.epsilon() | 215 is_epsilon = lambda k: k == TransitionKey.epsilon() |
| 228 state_iter = lambda node : node.state_iter(key_filter = is_epsilon) | 216 state_iter = lambda node : node.state_iter(key_filter = is_epsilon) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 | 263 |
| 276 @staticmethod | 264 @staticmethod |
| 277 def add_continue(term): | 265 def add_continue(term): |
| 278 return Term('CONTINUE', term) | 266 return Term('CONTINUE', term) |
| 279 | 267 |
| 280 @staticmethod | 268 @staticmethod |
| 281 def unique_key(name): | 269 def unique_key(name): |
| 282 return Term('UNIQUE_KEY', name) | 270 return Term('UNIQUE_KEY', name) |
| 283 | 271 |
| 284 @staticmethod | 272 @staticmethod |
| 285 def join_subgraph(term, name, subgraph_term): | 273 def join_subgraph(tree, subtree): |
| 286 return Term('JOIN', term, name, subgraph_term) | 274 return Term('JOIN', tree, subtree) |
| 287 | 275 |
| 288 @staticmethod | 276 @staticmethod |
| 289 def or_terms(terms): | 277 def or_terms(terms): |
| 290 return reduce(lambda acc, g: Term('OR', acc, g), terms) | 278 return reduce(lambda acc, g: Term('OR', acc, g), terms) |
| 291 | 279 |
| 292 @staticmethod | 280 @staticmethod |
| 293 def cat_terms(terms): | 281 def cat_terms(terms): |
| 294 return reduce(lambda acc, g: Term('CAT', acc, g), terms) | 282 return reduce(lambda acc, g: Term('CAT', acc, g), terms) |
| 295 | 283 |
| 296 __modifer_map = { | 284 __modifer_map = { |
| 297 '+': 'ONE_OR_MORE', | 285 '+': 'ONE_OR_MORE', |
| 298 '?': 'ZERO_OR_ONE', | 286 '?': 'ZERO_OR_ONE', |
| 299 '*': 'ZERO_OR_MORE', | 287 '*': 'ZERO_OR_MORE', |
| 300 } | 288 } |
| 301 | 289 |
| 302 @staticmethod | 290 @staticmethod |
| 303 def apply_modifier(modifier, term): | 291 def apply_modifier(modifier, term): |
| 304 return Term(NfaBuilder.__modifer_map[modifier], term) | 292 return Term(NfaBuilder.__modifer_map[modifier], term) |
| OLD | NEW |