Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: tools/lexer_generator/nfa.py

Issue 160443002: Experimental parser: remove match actions (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/lexer_generator/lexer_test.py ('k') | tools/lexer_generator/nfa_builder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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)
OLDNEW
« no previous file with comments | « tools/lexer_generator/lexer_test.py ('k') | tools/lexer_generator/nfa_builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698