| 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 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 class NfaState(AutomatonState): | 31 class NfaState(AutomatonState): |
| 32 | 32 |
| 33 def __init__(self): | 33 def __init__(self): |
| 34 super(NfaState, self).__init__() | 34 super(NfaState, self).__init__() |
| 35 self.__transitions = {} | 35 self.__transitions = {} |
| 36 self.__unclosed = set() | 36 self.__unclosed = set() |
| 37 self.__epsilon_closure = None | 37 self.__epsilon_closure = None |
| 38 self.__action = Action.empty_action() | 38 self.__action = Action.empty_action() |
| 39 | 39 |
| 40 def epsilon_closure_iter(self): | |
| 41 return iter(self.__epsilon_closure) | |
| 42 | |
| 43 def set_epsilon_closure(self, closure): | |
| 44 assert self.is_closed() | |
| 45 assert self.__epsilon_closure == None | |
| 46 self.__epsilon_closure = frozenset(closure) | |
| 47 | |
| 48 def action(self): | 40 def action(self): |
| 49 assert self.is_closed() | 41 assert self.__is_closed() |
| 50 return self.__action | 42 return self.__action |
| 51 | 43 |
| 52 def set_action(self, action): | 44 def set_action(self, action): |
| 53 assert not self.is_closed() | 45 assert not self.__is_closed() |
| 54 assert not self.__action | 46 assert not self.__action |
| 55 assert isinstance(action, Action) | 47 assert isinstance(action, Action) |
| 56 self.__action = action | 48 self.__action = action |
| 57 | 49 |
| 58 def state_iter_for_key(self, key): | |
| 59 assert self.is_closed() | |
| 60 if not key in self.__transitions: | |
| 61 return iter([]) | |
| 62 return iter(self.__transitions[key]) | |
| 63 | |
| 64 def swap_key(self, old_key, new_key): | |
| 65 'this is one of the few mutations allowed after closing' | |
| 66 assert self.is_closed() | |
| 67 assert not new_key == TransitionKey.epsilon(), "changes epsilon closure" | |
| 68 value = self.__transitions[old_key] | |
| 69 del self.__transitions[old_key] | |
| 70 self.__transitions[new_key] = value | |
| 71 | |
| 72 def __add_transition(self, key, next_state): | 50 def __add_transition(self, key, next_state): |
| 73 assert key != None | 51 assert key != None |
| 74 if next_state == None: | 52 if next_state == None: |
| 75 assert not self.is_closed(), "already closed" | 53 assert not self.__is_closed(), "already closed" |
| 76 self.__unclosed.add(key) | 54 self.__unclosed.add(key) |
| 77 return | 55 return |
| 78 if not key in self.__transitions: | 56 if not key in self.__transitions: |
| 79 self.__transitions[key] = set() | 57 self.__transitions[key] = set() |
| 58 else: |
| 59 assert key == TransitionKey.epsilon() |
| 80 self.__transitions[key].add(next_state) | 60 self.__transitions[key].add(next_state) |
| 81 | 61 |
| 82 def add_unclosed_transition(self, key): | 62 def add_unclosed_transition(self, key): |
| 83 assert key != TransitionKey.epsilon() | 63 assert key != TransitionKey.epsilon() |
| 84 self.__add_transition(key, None) | 64 self.__add_transition(key, None) |
| 85 | 65 |
| 66 def add_transition(self, key, state): |
| 67 assert not self.__is_closed(), "already closed" |
| 68 assert state != None |
| 69 self.__add_transition(key, state) |
| 70 |
| 86 def add_epsilon_transition(self, state): | 71 def add_epsilon_transition(self, state): |
| 87 assert state != None | 72 self.add_transition(TransitionKey.epsilon(), state) |
| 88 self.__add_transition(TransitionKey.epsilon(), state) | |
| 89 | 73 |
| 90 def is_closed(self): | 74 def __is_closed(self): |
| 91 return self.__unclosed == None | 75 return self.__unclosed == None |
| 92 | 76 |
| 93 def close(self, end): | 77 def close(self, end): |
| 94 assert not self.is_closed() | 78 assert not self.__is_closed() |
| 95 unclosed, self.__unclosed = self.__unclosed, None | 79 unclosed, self.__unclosed = self.__unclosed, None |
| 96 if end == None: | 80 if end == None: |
| 97 assert not unclosed | 81 assert not unclosed |
| 98 return | 82 return |
| 99 for key in unclosed: | 83 for key in unclosed: |
| 100 self.__add_transition(key, end) | 84 self.__add_transition(key, end) |
| 101 if not unclosed: | 85 if not unclosed: |
| 102 self.__add_transition(TransitionKey.epsilon(), end) | 86 self.__add_transition(TransitionKey.epsilon(), end) |
| 103 | 87 |
| 88 def post_creation_verify(self): |
| 89 assert self.__is_closed() |
| 90 assert self.__epsilon_closure != None |
| 91 |
| 92 def state_iter_for_key(self, key): |
| 93 assert self.__is_closed() |
| 94 if not key in self.__transitions: |
| 95 return iter([]) |
| 96 return iter(self.__transitions[key]) |
| 97 |
| 104 def key_state_iter( | 98 def key_state_iter( |
| 105 self, | 99 self, |
| 106 key_filter = lambda x: True, | 100 key_filter = lambda x: True, |
| 107 state_filter = lambda x: True, | 101 state_filter = lambda x: True, |
| 108 match_func = lambda x, y: True, | 102 match_func = lambda x, y: True, |
| 109 yield_func = lambda x, y: (x, y)): | 103 yield_func = lambda x, y: (x, y)): |
| 110 assert self.is_closed() | 104 assert self.__is_closed() |
| 111 for key, states in self.__transitions.items(): | 105 for key, states in self.__transitions.items(): |
| 112 if key_filter(key): | 106 if key_filter(key): |
| 113 for state in states: | 107 for state in states: |
| 114 if state_filter(state) and match_func(key, state): | 108 if state_filter(state) and match_func(key, state): |
| 115 yield yield_func(key, state) | 109 yield yield_func(key, state) |
| 116 | 110 |
| 111 def epsilon_closure_iter(self): |
| 112 return iter(self.__epsilon_closure) |
| 113 |
| 114 def set_epsilon_closure(self, closure): |
| 115 assert self.__is_closed() |
| 116 assert self.__epsilon_closure == None |
| 117 self.__epsilon_closure = frozenset(closure) |
| 118 |
| 119 def swap_key(self, old_key, new_key): |
| 120 'this is one of the few mutations allowed after closing' |
| 121 self.post_creation_verify() |
| 122 assert not old_key == TransitionKey.epsilon(), "changes epsilon closure" |
| 123 assert not new_key == TransitionKey.epsilon(), "changes epsilon closure" |
| 124 value = self.__transitions[old_key] |
| 125 del self.__transitions[old_key] |
| 126 self.__transitions[new_key] = value |
| 127 |
| 117 class Nfa(Automaton): | 128 class Nfa(Automaton): |
| 118 | 129 |
| 119 def __init__(self, encoding, start, end, nodes_created): | 130 def __init__(self, encoding, start, end, nodes_created): |
| 120 super(Nfa, self).__init__(encoding) | 131 super(Nfa, self).__init__(encoding) |
| 121 self.__start = start | 132 self.__start = start |
| 122 self.__end = end | 133 self.__end = end |
| 123 self.__verify(nodes_created) | 134 self.__verify(nodes_created) |
| 124 | 135 |
| 125 def start_state(self): | 136 def start_state(self): |
| 126 return self.__start | 137 return self.__start |
| 127 | 138 |
| 128 def terminal_set(self): | 139 def terminal_set(self): |
| 129 return set([self.__end]) | 140 return set([self.__end]) |
| 130 | 141 |
| 131 def __verify(self, nodes_created): | 142 def __verify(self, nodes_created): |
| 132 def f(node, count): | 143 def f(node, count): |
| 133 assert node.is_closed() | 144 node.post_creation_verify() |
| 134 return count + 1 | 145 return count + 1 |
| 135 count = self.visit_all_states(f, 0) | 146 count = self.visit_all_states(f, 0) |
| 136 assert count == nodes_created | 147 assert count == nodes_created |
| 137 | 148 |
| 138 @staticmethod | 149 @staticmethod |
| 139 def __gather_transition_keys(encoding, state_set): | 150 def __gather_transition_keys(encoding, state_set): |
| 140 keys = set(chain(*map(lambda state: state.key_iter(), state_set))) | 151 keys = set(chain(*map(lambda state: state.key_iter(), state_set))) |
| 141 keys.discard(TransitionKey.epsilon()) | 152 keys.discard(TransitionKey.epsilon()) |
| 142 return TransitionKey.disjoint_keys(encoding, keys) | 153 return TransitionKey.disjoint_keys(encoding, keys) |
| 143 | 154 |
| 144 def __to_dfa(self, nfa_state_set, dfa_nodes): | 155 def __to_dfa(self, nfa_state_set, dfa_nodes): |
| 145 nfa_state_set = Automaton.epsilon_closure(nfa_state_set) | 156 nfa_state_set = Automaton.epsilon_closure(nfa_state_set) |
| 146 # nfa_state_set will be a state in the dfa. | 157 # nfa_state_set will be a state in the dfa. |
| 147 assert nfa_state_set | 158 assert nfa_state_set |
| 148 name = ".".join(str(x.node_number()) for x in sorted(nfa_state_set)) | 159 name = ".".join(str(x.node_number()) for x in sorted(nfa_state_set)) |
| 149 if name in dfa_nodes: | 160 if name in dfa_nodes: |
| 150 return name | 161 return name |
| 151 dfa_nodes[name] = { | 162 dfa_nodes[name] = { |
| 152 'transitions': {}, | 163 'transitions': {}, |
| 153 'terminal': self.__end in nfa_state_set, | 164 'terminal': self.__end in nfa_state_set, |
| 154 'action' : Action.dominant_action(nfa_state_set)} | 165 'action' : self.dominant_action(nfa_state_set)} |
| 155 # Gather the set of transition keys for which the dfa state will have | 166 # Gather the set of transition keys for which the dfa state will have |
| 156 # transitions (the disjoint set of all the transition keys from all the | 167 # transitions (the disjoint set of all the transition keys from all the |
| 157 # states combined). For example, if a state in the state set has a | 168 # states combined). For example, if a state in the state set has a |
| 158 # transition for key [a-c], and another state for [b-d], the dfa state will | 169 # transition for key [a-c], and another state for [b-d], the dfa state will |
| 159 # have transitions with keys ([a], [b-c], [d]). | 170 # have transitions with keys ([a], [b-c], [d]). |
| 160 for key in Nfa.__gather_transition_keys(self.encoding(), nfa_state_set): | 171 for key in Nfa.__gather_transition_keys(self.encoding(), nfa_state_set): |
| 161 # Find out which states we can reach with "key", starting from any of the | 172 # Find out which states we can reach with "key", starting from any of the |
| 162 # states in "nfa_state_set". The corresponding dfa state will have a | 173 # states in "nfa_state_set". The corresponding dfa state will have a |
| 163 # transition with "key" to a state which corresponds to the set of the | 174 # transition with "key" to a state which corresponds to the set of the |
| 164 # states ("match_states") (more accurately, its epsilon closure). | 175 # states ("match_states") (more accurately, its epsilon closure). |
| 165 f = lambda state: state.transition_state_iter_for_key(key) | 176 f = lambda state: state.transition_state_iter_for_key(key) |
| 166 match_states = set(chain(*map(f, nfa_state_set))) | 177 match_states = set(chain(*map(f, nfa_state_set))) |
| 167 transition_state = self.__to_dfa(match_states, dfa_nodes) | 178 transition_state = self.__to_dfa(match_states, dfa_nodes) |
| 168 dfa_nodes[name]['transitions'][key] = transition_state | 179 dfa_nodes[name]['transitions'][key] = transition_state |
| 169 return name | 180 return name |
| 170 | 181 |
| 171 def compute_dfa(self): | 182 def compute_dfa(self): |
| 172 dfa_nodes = {} | 183 dfa_nodes = {} |
| 173 start_name = self.__to_dfa(set([self.__start]), dfa_nodes) | 184 start_name = self.__to_dfa(set([self.__start]), dfa_nodes) |
| 174 return (start_name, dfa_nodes) | 185 return (start_name, dfa_nodes) |
| OLD | NEW |