| 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 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 (start, ends) = self.__process(graph[1]) | 214 (start, ends) = self.__process(graph[1]) |
| 215 state = self.__peek_state() | 215 state = self.__peek_state() |
| 216 if not state['start_node']: | 216 if not state['start_node']: |
| 217 state['start_node'] = self.__new_state() | 217 state['start_node'] = self.__new_state() |
| 218 end = self.__new_state() | 218 end = self.__new_state() |
| 219 self.__patch_ends(ends, end) | 219 self.__patch_ends(ends, end) |
| 220 ends = [end] | 220 ends = [end] |
| 221 end.add_epsilon_transition(state['start_node']) | 221 end.add_epsilon_transition(state['start_node']) |
| 222 return (start, ends) | 222 return (start, ends) |
| 223 | 223 |
| 224 def __break(self, graph): |
| 225 (start, ends) = self.__process(graph[1]) |
| 226 self.__peek_state()['unpatched_ends'] += ends |
| 227 new_end = self.__new_state() |
| 228 for end in ends: |
| 229 end.add_epsilon_transition(new_end) |
| 230 return (start, [new_end]) |
| 231 |
| 224 def __join(self, graph): | 232 def __join(self, graph): |
| 225 (graph, name, subgraph, modifier) = graph[1:] | 233 (graph, name, subgraph, modifier) = graph[1:] |
| 226 subgraphs = self.__peek_state()['subgraphs'] | 234 subgraphs = self.__peek_state()['subgraphs'] |
| 227 if not name in subgraphs: | 235 if not name in subgraphs: |
| 228 subgraphs[name] = self.__nfa(subgraph) | 236 subgraphs[name] = self.__nfa(subgraph) |
| 229 (subgraph_start, subgraph_end, nodes_in_subgraph) = subgraphs[name] | 237 (subgraph_start, subgraph_end, nodes_in_subgraph) = subgraphs[name] |
| 230 (start, ends) = self.__process(graph) | 238 (start, ends) = self.__process(graph) |
| 231 if modifier: | 239 if modifier: |
| 232 assert modifier == 'ZERO_OR_MORE' | 240 assert modifier == 'ZERO_OR_MORE' |
| 233 for end in ends: | 241 for end in ends: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 247 return self.__operation_map[method](graph) | 255 return self.__operation_map[method](graph) |
| 248 | 256 |
| 249 def __patch_ends(self, ends, new_end): | 257 def __patch_ends(self, ends, new_end): |
| 250 for end in ends: | 258 for end in ends: |
| 251 end.close(new_end) | 259 end.close(new_end) |
| 252 | 260 |
| 253 def __push_state(self): | 261 def __push_state(self): |
| 254 self.__states.append({ | 262 self.__states.append({ |
| 255 'start_node' : None, | 263 'start_node' : None, |
| 256 'subgraphs' : {}, | 264 'subgraphs' : {}, |
| 265 'unpatched_ends' : [], |
| 257 }) | 266 }) |
| 258 | 267 |
| 259 def __pop_state(self): | 268 def __pop_state(self): |
| 260 return self.__states.pop() | 269 return self.__states.pop() |
| 261 | 270 |
| 262 def __peek_state(self): | 271 def __peek_state(self): |
| 263 return self.__states[len(self.__states) - 1] | 272 return self.__states[len(self.__states) - 1] |
| 264 | 273 |
| 265 def __nfa(self, graph): | 274 def __nfa(self, graph): |
| 266 start_node_number = self.__node_number | 275 start_node_number = self.__node_number |
| 267 self.__push_state() | 276 self.__push_state() |
| 268 (start, ends) = self.__process(graph) | 277 (start, ends) = self.__process(graph) |
| 269 state = self.__pop_state() | 278 state = self.__pop_state() |
| 270 if state['start_node']: | 279 if state['start_node']: |
| 271 state['start_node'].close(start) | 280 state['start_node'].close(start) |
| 272 start = state['start_node'] | 281 start = state['start_node'] |
| 273 for k, subgraph in state['subgraphs'].items(): | 282 for k, subgraph in state['subgraphs'].items(): |
| 274 subgraph[1].close(None) | 283 subgraph[1].close(None) |
| 275 end = self.__new_state() | 284 end = self.__new_state() |
| 285 if self.__states: |
| 286 self.__peek_state()['unpatched_ends'] += state['unpatched_ends'] |
| 287 else: |
| 288 self.__patch_ends(state['unpatched_ends'], end) |
| 276 self.__patch_ends(ends, end) | 289 self.__patch_ends(ends, end) |
| 277 return (start, end, self.__node_number - start_node_number) | 290 return (start, end, self.__node_number - start_node_number) |
| 278 | 291 |
| 279 def nfa(self, graph): | 292 def nfa(self, graph): |
| 280 (start, end, nodes_created) = self.__nfa(graph) | 293 (start, end, nodes_created) = self.__nfa(graph) |
| 281 end.close(None) | 294 end.close(None) |
| 282 return Nfa(start, end, nodes_created) | 295 return Nfa(start, end, nodes_created) |
| 283 | 296 |
| 284 @staticmethod | 297 @staticmethod |
| 285 def add_action(graph, action): | 298 def add_action(graph, action): |
| 286 return ('ACTION', graph, action) | 299 return ('ACTION', graph, action) |
| 287 | 300 |
| 288 @staticmethod | 301 @staticmethod |
| 289 def add_continue(graph): | 302 def add_continue(graph): |
| 290 return ('CONTINUE', graph) | 303 return ('CONTINUE', graph) |
| 291 | 304 |
| 292 @staticmethod | 305 @staticmethod |
| 306 def add_break(graph): |
| 307 return ('BREAK', graph) |
| 308 |
| 309 @staticmethod |
| 293 def join_subgraph(graph, name, subgraph, modifier): | 310 def join_subgraph(graph, name, subgraph, modifier): |
| 294 if modifier: | 311 if modifier: |
| 295 modifier = NfaBuilder.__modifer_map[modifier] | 312 modifier = NfaBuilder.__modifer_map[modifier] |
| 296 return ('JOIN', graph, name, subgraph, modifier) | 313 return ('JOIN', graph, name, subgraph, modifier) |
| 297 | 314 |
| 298 @staticmethod | 315 @staticmethod |
| 299 def or_graphs(graphs): | 316 def or_graphs(graphs): |
| 300 return reduce(lambda acc, g: ('OR', acc, g), graphs) | 317 return reduce(lambda acc, g: ('OR', acc, g), graphs) |
| 301 | 318 |
| 302 @staticmethod | 319 @staticmethod |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 def compute_dfa(self): | 414 def compute_dfa(self): |
| 398 self.__compute_epsilon_closures() | 415 self.__compute_epsilon_closures() |
| 399 dfa_nodes = {} | 416 dfa_nodes = {} |
| 400 start_name = self.__to_dfa(set([self.__start]), dfa_nodes, self.__end) | 417 start_name = self.__to_dfa(set([self.__start]), dfa_nodes, self.__end) |
| 401 return (start_name, dfa_nodes) | 418 return (start_name, dfa_nodes) |
| 402 | 419 |
| 403 def to_dot(self): | 420 def to_dot(self): |
| 404 iterator = lambda visitor, state: self.__visit_all_edges(visitor, state) | 421 iterator = lambda visitor, state: self.__visit_all_edges(visitor, state) |
| 405 state_iterator = lambda x : x | 422 state_iterator = lambda x : x |
| 406 return self.generate_dot(self.__start, set([self.__end]), iterator, state_it
erator) | 423 return self.generate_dot(self.__start, set([self.__end]), iterator, state_it
erator) |
| OLD | NEW |