| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 assert self.is_closed() | 47 assert self.is_closed() |
| 48 assert self.__epsilon_closure == None | 48 assert self.__epsilon_closure == None |
| 49 self.__epsilon_closure = frozenset(closure) | 49 self.__epsilon_closure = frozenset(closure) |
| 50 | 50 |
| 51 def transitions(self): | 51 def transitions(self): |
| 52 assert self.is_closed() | 52 assert self.is_closed() |
| 53 return self.__transitions | 53 return self.__transitions |
| 54 | 54 |
| 55 def get_epsilon_transitions(self): | 55 def get_epsilon_transitions(self): |
| 56 key = TransitionKey.epsilon(); | 56 key = TransitionKey.epsilon(); |
| 57 if not self.__transitions.has_key(key): return frozenset() | 57 if not key in self.__transitions: return frozenset() |
| 58 return frozenset(self.__transitions[key]) | 58 return frozenset(self.__transitions[key]) |
| 59 | 59 |
| 60 def __add_transition(self, key, value): | 60 def __add_transition(self, key, value): |
| 61 if value == None: | 61 if value == None: |
| 62 assert not self.is_closed(), "already closed" | 62 assert not self.is_closed(), "already closed" |
| 63 self.__unclosed.add(key) | 63 self.__unclosed.add(key) |
| 64 return | 64 return |
| 65 if not self.__transitions.has_key(key): | 65 if not key in self.__transitions: |
| 66 self.__transitions[key] = set() | 66 self.__transitions[key] = set() |
| 67 self.__transitions[key].add(value) | 67 self.__transitions[key].add(value) |
| 68 | 68 |
| 69 def add_unclosed_transition(self, key): | 69 def add_unclosed_transition(self, key): |
| 70 assert key != TransitionKey.epsilon() | 70 assert key != TransitionKey.epsilon() |
| 71 self.__add_transition(key, None) | 71 self.__add_transition(key, None) |
| 72 | 72 |
| 73 def add_epsilon_transition(self, state): | 73 def add_epsilon_transition(self, state): |
| 74 assert state != None | 74 assert state != None |
| 75 self.__add_transition(TransitionKey.epsilon(), state) | 75 self.__add_transition(TransitionKey.epsilon(), state) |
| 76 | 76 |
| 77 def is_closed(self): | 77 def is_closed(self): |
| 78 return self.__unclosed == None | 78 return self.__unclosed == None |
| 79 | 79 |
| 80 def close(self, end): | 80 def close(self, end): |
| 81 assert not self.is_closed() | 81 assert not self.is_closed() |
| 82 if end == None: | 82 if end == None: |
| 83 assert not self.__unclosed | 83 assert not self.__unclosed |
| 84 else: | 84 else: |
| 85 for key in self.__unclosed: | 85 for key in self.__unclosed: |
| 86 self.__add_transition(key, end) | 86 self.__add_transition(key, end) |
| 87 if not self.__unclosed: | 87 if not self.__unclosed: |
| 88 self.add_epsilon_transition(end) | 88 self.add_epsilon_transition(end) |
| 89 self.__unclosed = None | 89 self.__unclosed = None |
| 90 | 90 |
| 91 def __matches(self, match_func, value): | 91 def __matches(self, match_func, value): |
| 92 matches = set() | 92 f = lambda acc, (k, vs): acc | vs if match_func(k, value) else acc |
| 93 for key, values in self.__transitions.items(): | 93 return reduce(f, self.__transitions.items(), set()) |
| 94 if match_func(key, value): | |
| 95 matches |= values | |
| 96 return matches | |
| 97 | 94 |
| 98 def char_matches(self, value): | 95 def char_matches(self, value): |
| 99 return self.__matches((lambda k, v : k.matches_char(v)), value) | 96 return self.__matches((lambda k, v : k.matches_char(v)), value) |
| 100 | 97 |
| 101 def key_matches(self, value): | 98 def key_matches(self, value): |
| 102 return self.__matches((lambda k, v : k.matches_key(v)), value) | 99 return self.__matches((lambda k, v : k.matches_key(v)), value) |
| 103 | 100 |
| 104 @staticmethod | 101 @staticmethod |
| 105 def gather_transition_keys(state_set): | 102 def gather_transition_keys(state_set): |
| 106 keys = set() | 103 f = lambda acc, state: acc | set(state.__transitions.keys()) |
| 107 for state in state_set: | 104 return TransitionKey.merge_key_set(reduce(f, state_set, set())) |
| 108 keys |= set(state.__transitions.keys()) | |
| 109 return TransitionKey.merge_key_set(keys) | |
| 110 | 105 |
| 111 class NfaBuilder: | 106 class NfaBuilder: |
| 112 | 107 |
| 113 def __init__(self): | 108 def __init__(self): |
| 114 self.__operation_map = {} | 109 self.__operation_map = {} |
| 115 self.__members = getmembers(self) | 110 self.__members = getmembers(self) |
| 116 | 111 |
| 117 def __new_state(self): | 112 def __new_state(self): |
| 118 node_number = self.node_number | 113 node_number = self.node_number |
| 119 self.node_number = self.node_number + 1 | 114 self.node_number = self.node_number + 1 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 161 |
| 167 def __not_class(self, graph): | 162 def __not_class(self, graph): |
| 168 return self.__key_state(TransitionKey.character_class(True, graph[1])) | 163 return self.__key_state(TransitionKey.character_class(True, graph[1])) |
| 169 | 164 |
| 170 def __any(self, graph): | 165 def __any(self, graph): |
| 171 return self.__key_state(TransitionKey.any()) | 166 return self.__key_state(TransitionKey.any()) |
| 172 | 167 |
| 173 def __process(self, graph): | 168 def __process(self, graph): |
| 174 assert type(graph) == TupleType | 169 assert type(graph) == TupleType |
| 175 method = "_NfaBuilder__" + graph[0].lower() | 170 method = "_NfaBuilder__" + graph[0].lower() |
| 176 if (not self.__operation_map.has_key(method)): | 171 if not method in self.__operation_map: |
| 177 matches = [func for (name, func) in self.__members if name == method] | 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] | 174 self.__operation_map[method] = matches[0][1] |
| 180 return self.__operation_map[method](graph) | 175 return self.__operation_map[method](graph) |
| 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 nfa(self, graph): | 181 def nfa(self, graph): |
| 187 self.node_number = 0 | 182 self.node_number = 0 |
| 188 (start, ends) = self.__process(graph) | 183 (start, ends) = self.__process(graph) |
| 189 end = self.__new_state() | 184 end = self.__new_state() |
| 190 self.__patch_ends(ends, end) | 185 self.__patch_ends(ends, end) |
| 191 end.close(None) | 186 end.close(None) |
| 192 return Nfa(start, end, self.node_number) | 187 return Nfa(start, end, self.node_number) |
| 193 | 188 |
| 194 class Nfa: | 189 class Nfa: |
| 195 | 190 |
| 196 def __init__(self, start, end, nodes_created): | 191 def __init__(self, start, end, nodes_created): |
| 197 self.__start = start | 192 self.__start = start |
| 198 self.__end = end | 193 self.__end = end |
| 199 self.__epsilon_closure_computed = False | 194 self.__epsilon_closure_computed = False |
| 200 self.__verify(nodes_created) | 195 self.__verify(nodes_created) |
| 201 | 196 |
| 202 @staticmethod | 197 @staticmethod |
| 203 def __visit_edges(edge, compute_next_edge, visitor, state): | 198 def __visit_edges(edge, compute_next_edge, visitor, state): |
| 204 visited = set() | 199 visited = set() |
| 205 while edge: | 200 while edge: |
| 206 next_edge = set() | 201 f = lambda (next_edge, state), node: ( |
| 207 for node in edge: | 202 next_edge | compute_next_edge(node), |
| 208 next_edge |= compute_next_edge(node) | 203 visitor(node, state)) |
| 209 state = visitor(node, state) | 204 (next_edge, state) = reduce(f, edge, (set(), state)) |
| 210 visited |= edge | 205 visited |= edge |
| 211 edge = next_edge - visited | 206 edge = next_edge - visited |
| 212 return state | 207 return state |
| 213 | 208 |
| 214 def __visit_all_edges(self, function, state): | 209 def __visit_all_edges(self, visitor, state): |
| 215 edge = set([self.__start]) | 210 edge = set([self.__start]) |
| 216 def next_edge(node): | 211 def next_edge(node): |
| 217 next = set() | 212 f = lambda acc, values: acc | values |
| 218 for values in node.transitions().values(): | 213 return reduce(f, node.transitions().values(), set()) |
| 219 next |= values | 214 return Nfa.__visit_edges(edge, next_edge, visitor, state) |
| 220 return next | |
| 221 return Nfa.__visit_edges(edge, next_edge, function, state) | |
| 222 | 215 |
| 223 def __verify(self, nodes_created): | 216 def __verify(self, nodes_created): |
| 224 def f(node, node_list): | 217 def f(node, node_list): |
| 225 assert node.is_closed() | 218 assert node.is_closed() |
| 226 node_list.append(node) | 219 node_list.append(node) |
| 227 return node_list | 220 return node_list |
| 228 node_list = self.__visit_all_edges(f, []) | 221 node_list = self.__visit_all_edges(f, []) |
| 229 assert len(node_list) == nodes_created | 222 assert len(node_list) == nodes_created |
| 230 | 223 |
| 231 def __compute_epsilon_closures(self): | 224 def __compute_epsilon_closures(self): |
| 232 if self.__epsilon_closure_computed: | 225 if self.__epsilon_closure_computed: |
| 233 return | 226 return |
| 234 self.__epsilon_closure_computed = True | 227 self.__epsilon_closure_computed = True |
| 235 def outer(node, state): | 228 def outer(node, state): |
| 236 def inner(node, closure): | 229 def inner(node, closure): |
| 237 closure.add(node) | 230 closure.add(node) |
| 238 return closure | 231 return closure |
| 239 next_edge = lambda node : node.get_epsilon_transitions() | 232 next_edge = lambda node : node.get_epsilon_transitions() |
| 240 edge = next_edge(node) | 233 edge = next_edge(node) |
| 241 closure = Nfa.__visit_edges(edge, next_edge, inner, set()) | 234 closure = Nfa.__visit_edges(edge, next_edge, inner, set()) |
| 242 node.set_epsilon_closure(closure) | 235 node.set_epsilon_closure(closure) |
| 243 self.__visit_all_edges(outer, None) | 236 self.__visit_all_edges(outer, None) |
| 244 | 237 |
| 245 @staticmethod | 238 @staticmethod |
| 246 def __close(states): | 239 def __close(states): |
| 247 closure = set(states) | 240 f = lambda acc, node: acc | node.epsilon_closure() |
| 248 for node in states: | 241 return reduce(f, states, set(states)) |
| 249 closure |= node.epsilon_closure() | |
| 250 return closure | |
| 251 | 242 |
| 252 def matches(self, string): | 243 def matches(self, string): |
| 253 self.__compute_epsilon_closures() | 244 self.__compute_epsilon_closures() |
| 254 valid_states = Nfa.__close(set([self.__start])) | 245 valid_states = Nfa.__close(set([self.__start])) |
| 255 for c in string: | 246 for c in string: |
| 256 next_valid_states = set() | 247 f = lambda acc, state: acc | state.char_matches(c) |
| 257 for valid_state in valid_states: | 248 valid_states = Nfa.__close(reduce(valid_states, f, set())) |
| 258 next_valid_states |= valid_state.char_matches(c) | |
| 259 valid_states = Nfa.__close(next_valid_states) | |
| 260 if not valid_states: | 249 if not valid_states: |
| 261 return False | 250 return False |
| 262 return self.__end in valid_states | 251 return self.__end in valid_states |
| 263 | 252 |
| 264 @staticmethod | 253 @staticmethod |
| 265 def __to_dfa(nfa_state_set, dfa_builder): | 254 def __to_dfa(nfa_state_set, builder): |
| 266 nfa_state_set = Nfa.__close(nfa_state_set) | 255 nfa_state_set = Nfa.__close(nfa_state_set) |
| 267 name = str([x.node_number() for x in nfa_state_set]) | 256 name = str([x.node_number() for x in nfa_state_set]) |
| 268 (dfa_nodes, end_nodes, end_node) = dfa_builder | 257 (dfa_nodes, end_nodes, end_node) = builder |
| 269 if dfa_nodes.has_key(name): | 258 if name in dfa_nodes: |
| 270 return name | 259 return name |
| 271 dfa_node = {} | 260 dfa_node = {} |
| 272 dfa_nodes[name] = dfa_node | 261 dfa_nodes[name] = dfa_node |
| 273 for key in NfaState.gather_transition_keys(nfa_state_set): | 262 for key in NfaState.gather_transition_keys(nfa_state_set): |
| 274 reachable_set = set() | 263 f = lambda acc, state: acc | state.key_matches(key) |
| 275 for nfa_state in nfa_state_set: | 264 dfa_node[key] = Nfa.__to_dfa(reduce(f, nfa_state_set, set()), builder) |
| 276 reachable_set |= nfa_state.key_matches(key) | |
| 277 dfa_node[key] = Nfa.__to_dfa(reachable_set, dfa_builder) | |
| 278 if end_node in nfa_state_set: | 265 if end_node in nfa_state_set: |
| 279 end_nodes.add(name) | 266 end_nodes.add(name) |
| 280 return name | 267 return name |
| 281 | 268 |
| 282 def compute_dfa(self): | 269 def compute_dfa(self): |
| 283 self.__compute_epsilon_closures() | 270 self.__compute_epsilon_closures() |
| 284 dfa_nodes = {} | 271 dfa_nodes = {} |
| 285 end_nodes = set() | 272 end_nodes = set() |
| 286 dfa_builder = (dfa_nodes, end_nodes, self.__end) | 273 dfa_builder = (dfa_nodes, end_nodes, self.__end) |
| 287 start_name = self.__to_dfa(set([self.__start]), dfa_builder) | 274 start_name = self.__to_dfa(set([self.__start]), dfa_builder) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 305 digraph finite_state_machine { | 292 digraph finite_state_machine { |
| 306 rankdir=LR; | 293 rankdir=LR; |
| 307 node [shape = circle, style=filled, bgcolor=lightgrey]; S_%s | 294 node [shape = circle, style=filled, bgcolor=lightgrey]; S_%s |
| 308 node [shape = doublecircle, style=unfilled]; S_%s | 295 node [shape = doublecircle, style=unfilled]; S_%s |
| 309 node [shape = circle]; | 296 node [shape = circle]; |
| 310 %s | 297 %s |
| 311 } | 298 } |
| 312 ''' % (self.__start.node_number(), | 299 ''' % (self.__start.node_number(), |
| 313 self.__end.node_number(), | 300 self.__end.node_number(), |
| 314 "\n".join(node_content)) | 301 "\n".join(node_content)) |
| OLD | NEW |