| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 self.__add_transition(TransitionKey.epsilon(), None, state) | 81 self.__add_transition(TransitionKey.epsilon(), None, state) |
| 82 | 82 |
| 83 def is_closed(self): | 83 def is_closed(self): |
| 84 return self.__unclosed == None | 84 return self.__unclosed == None |
| 85 | 85 |
| 86 def close(self, end): | 86 def close(self, end): |
| 87 assert not self.is_closed() | 87 assert not self.is_closed() |
| 88 unclosed, self.__unclosed = self.__unclosed, None | 88 unclosed, self.__unclosed = self.__unclosed, None |
| 89 action, self.__transition_action = self.__transition_action, None | 89 action, self.__transition_action = self.__transition_action, None |
| 90 if end == None: | 90 if end == None: |
| 91 assert not unclosed | 91 assert not unclosed and not action |
| 92 assert not action | |
| 93 return | 92 return |
| 94 for key in unclosed: | 93 for key in unclosed: |
| 95 self.__add_transition(key, action, end) | 94 self.__add_transition(key, action, end) |
| 96 if not unclosed: | 95 if not unclosed: |
| 97 self.__add_transition(TransitionKey.epsilon(), action, end) | 96 self.__add_transition(TransitionKey.epsilon(), action, end) |
| 98 | 97 |
| 99 def __matches(self, match_func, value): | 98 def __matches(self, match_func, value): |
| 100 f = lambda acc, (k, vs): acc | vs if match_func(k, value) else acc | 99 f = lambda acc, (k, vs): acc | vs if match_func(k, value) else acc |
| 101 return reduce(f, self.__transitions.items(), set()) | 100 return reduce(f, self.__transitions.items(), set()) |
| 102 | 101 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 114 f = lambda acc, state: acc | set(state.__transitions.keys()) | 113 f = lambda acc, state: acc | set(state.__transitions.keys()) |
| 115 return TransitionKey.disjoint_keys(reduce(f, state_set, set())) | 114 return TransitionKey.disjoint_keys(reduce(f, state_set, set())) |
| 116 | 115 |
| 117 class NfaBuilder: | 116 class NfaBuilder: |
| 118 | 117 |
| 119 def __init__(self): | 118 def __init__(self): |
| 120 self.__node_number = 0 | 119 self.__node_number = 0 |
| 121 self.__operation_map = {} | 120 self.__operation_map = {} |
| 122 self.__members = getmembers(self) | 121 self.__members = getmembers(self) |
| 123 self.__character_classes = {} | 122 self.__character_classes = {} |
| 123 self.__states = [] |
| 124 | 124 |
| 125 def set_character_classes(self, classes): | 125 def set_character_classes(self, classes): |
| 126 self.__character_classes = classes | 126 self.__character_classes = classes |
| 127 | 127 |
| 128 def __new_state(self): | 128 def __new_state(self): |
| 129 self.__node_number += 1 | 129 self.__node_number += 1 |
| 130 return NfaState(self.__node_number - 1) | 130 return NfaState(self.__node_number - 1) |
| 131 | 131 |
| 132 def __or(self, graph): | 132 def __or(self, graph): |
| 133 start = self.__new_state() | 133 start = self.__new_state() |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 TransitionKey.character_class(graph, self.__character_classes)) | 198 TransitionKey.character_class(graph, self.__character_classes)) |
| 199 | 199 |
| 200 def __not_class(self, graph): | 200 def __not_class(self, graph): |
| 201 return self.__key_state( | 201 return self.__key_state( |
| 202 TransitionKey.character_class(graph, self.__character_classes)) | 202 TransitionKey.character_class(graph, self.__character_classes)) |
| 203 | 203 |
| 204 def __any(self, graph): | 204 def __any(self, graph): |
| 205 return self.__key_state(TransitionKey.any()) | 205 return self.__key_state(TransitionKey.any()) |
| 206 | 206 |
| 207 def __action(self, graph): | 207 def __action(self, graph): |
| 208 result = self.__process(graph[1]) | 208 incoming = graph[3] |
| 209 for end in result[1]: | 209 (start, ends) = self.__process(graph[1]) |
| 210 end.set_transition_action(graph[2]) | 210 action = graph[2] |
| 211 return result | 211 if incoming: |
| 212 new_start = self.__new_state() |
| 213 new_start.set_transition_action(action) |
| 214 new_start.close(start) |
| 215 start = new_start |
| 216 else: |
| 217 for end in ends: |
| 218 end.set_transition_action(action) |
| 219 return (start, ends) |
| 212 | 220 |
| 213 def __continue(self, graph): | 221 def __continue(self, graph): |
| 214 (start, ends) = self.__process(graph[1]) | 222 (start, ends) = self.__process(graph[1]) |
| 215 if not self.__start_node: | 223 state = self.__peek_state() |
| 216 self.__start_node = self.__new_state() | 224 if not state['start_node']: |
| 225 state['start_node'] = self.__new_state() |
| 217 end = self.__new_state() | 226 end = self.__new_state() |
| 218 self.__patch_ends(ends, end) | 227 self.__patch_ends(ends, end) |
| 219 ends = [end] | 228 ends = [end] |
| 220 end.add_epsilon_transition(self.__start_node) | 229 end.add_epsilon_transition(state['start_node']) |
| 221 return (start, ends) | 230 return (start, ends) |
| 222 | 231 |
| 232 def __join(self, graph): |
| 233 (graph, name, subgraph) = graph[1:] |
| 234 subgraphs = self.__peek_state()['subgraphs'] |
| 235 if not name in subgraphs: |
| 236 subgraphs[name] = self.__nfa(subgraph) |
| 237 (subgraph_start, subgraph_end, nodes_in_subgraph) = subgraphs[name] |
| 238 (start, ends) = self.__process(graph) |
| 239 self.__patch_ends(ends, subgraph_start) |
| 240 end = self.__new_state() |
| 241 subgraph_end.add_epsilon_transition(end) |
| 242 return (start, [end]) |
| 243 |
| 223 def __process(self, graph): | 244 def __process(self, graph): |
| 224 assert type(graph) == TupleType | 245 assert type(graph) == TupleType |
| 225 method = "_NfaBuilder__" + graph[0].lower() | 246 method = "_NfaBuilder__" + graph[0].lower() |
| 226 if not method in self.__operation_map: | 247 if not method in self.__operation_map: |
| 227 matches = filter(lambda (name, func): name == method, self.__members) | 248 matches = filter(lambda (name, func): name == method, self.__members) |
| 228 assert len(matches) == 1 | 249 assert len(matches) == 1 |
| 229 self.__operation_map[method] = matches[0][1] | 250 self.__operation_map[method] = matches[0][1] |
| 230 return self.__operation_map[method](graph) | 251 return self.__operation_map[method](graph) |
| 231 | 252 |
| 232 def __patch_ends(self, ends, new_end): | 253 def __patch_ends(self, ends, new_end): |
| 233 for end in ends: | 254 for end in ends: |
| 234 end.close(new_end) | 255 end.close(new_end) |
| 235 | 256 |
| 236 def nfa(self, graph): | 257 def __push_state(self): |
| 237 self.__start_node = None | 258 self.__states.append({ |
| 259 'start_node' : None, |
| 260 'subgraphs' : {}, |
| 261 }) |
| 262 |
| 263 def __pop_state(self): |
| 264 return self.__states.pop() |
| 265 |
| 266 def __peek_state(self): |
| 267 return self.__states[len(self.__states) - 1] |
| 268 |
| 269 def __nfa(self, graph): |
| 238 start_node_number = self.__node_number | 270 start_node_number = self.__node_number |
| 271 self.__push_state() |
| 239 (start, ends) = self.__process(graph) | 272 (start, ends) = self.__process(graph) |
| 240 if self.__start_node: | 273 state = self.__pop_state() |
| 241 self.__start_node.close(start) | 274 if state['start_node']: |
| 242 start = self.__start_node | 275 state['start_node'].close(start) |
| 276 start = state['start_node'] |
| 277 for k, subgraph in state['subgraphs'].items(): |
| 278 subgraph[1].close(None) |
| 243 end = self.__new_state() | 279 end = self.__new_state() |
| 244 self.__patch_ends(ends, end) | 280 self.__patch_ends(ends, end) |
| 281 return (start, end, self.__node_number - start_node_number) |
| 282 |
| 283 def nfa(self, graph): |
| 284 (start, end, nodes_created) = self.__nfa(graph) |
| 245 end.close(None) | 285 end.close(None) |
| 246 return Nfa(start, end, self.__node_number - start_node_number) | 286 return Nfa(start, end, nodes_created) |
| 247 | 287 |
| 248 @staticmethod | 288 @staticmethod |
| 249 def add_action(graph, action): | 289 def add_action(graph, action): |
| 250 return ('ACTION', graph, action) | 290 return ('ACTION', graph, action, False) |
| 291 |
| 292 @staticmethod |
| 293 def add_incoming_action(graph, action): |
| 294 return ('ACTION', graph, action, True) |
| 251 | 295 |
| 252 @staticmethod | 296 @staticmethod |
| 253 def add_continue(graph): | 297 def add_continue(graph): |
| 254 return ('CONTINUE', graph) | 298 return ('CONTINUE', graph) |
| 255 | 299 |
| 256 @staticmethod | 300 @staticmethod |
| 301 def join_subgraph(graph, name, subgraph): |
| 302 return ('JOIN', graph, name, subgraph) |
| 303 |
| 304 @staticmethod |
| 257 def or_graphs(graphs): | 305 def or_graphs(graphs): |
| 258 return reduce(lambda acc, g: ('OR', acc, g), graphs) | 306 return reduce(lambda acc, g: ('OR', acc, g), graphs) |
| 259 | 307 |
| 260 @staticmethod | 308 @staticmethod |
| 261 def cat_graphs(graphs): | 309 def cat_graphs(graphs): |
| 262 return reduce(lambda acc, g: ('CAT', acc, g), graphs) | 310 return reduce(lambda acc, g: ('CAT', acc, g), graphs) |
| 263 | 311 |
| 264 __modifer_map = { | 312 __modifer_map = { |
| 265 '+': 'ONE_OR_MORE', | 313 '+': 'ONE_OR_MORE', |
| 266 '?': 'ZERO_OR_ONE', | 314 '?': 'ZERO_OR_ONE', |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 410 |
| 363 def compute_dfa(self): | 411 def compute_dfa(self): |
| 364 self.__compute_epsilon_closures() | 412 self.__compute_epsilon_closures() |
| 365 dfa_nodes = {} | 413 dfa_nodes = {} |
| 366 start_name = self.__to_dfa(set([self.__start]), dfa_nodes, self.__end) | 414 start_name = self.__to_dfa(set([self.__start]), dfa_nodes, self.__end) |
| 367 return (start_name, dfa_nodes) | 415 return (start_name, dfa_nodes) |
| 368 | 416 |
| 369 def to_dot(self): | 417 def to_dot(self): |
| 370 iterator = lambda visitor, state: self.__visit_all_edges(visitor, state) | 418 iterator = lambda visitor, state: self.__visit_all_edges(visitor, state) |
| 371 return self.generate_dot(self.__start, set([self.__end]), iterator) | 419 return self.generate_dot(self.__start, set([self.__end]), iterator) |
| OLD | NEW |