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

Unified Diff: tools/lexer_generator/nfa.py

Issue 68343004: Experimental parser: better actions (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/lexer_generator/lexer_test.py ('k') | tools/lexer_generator/rule_lexer.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/lexer_generator/nfa.py
diff --git a/tools/lexer_generator/nfa.py b/tools/lexer_generator/nfa.py
index 46ddc711765dca4799ad34a3b750584dae0f2c96..e818a7da5cb6b8300b691ca2c1488bb0f938b04e 100644
--- a/tools/lexer_generator/nfa.py
+++ b/tools/lexer_generator/nfa.py
@@ -37,7 +37,7 @@ class NfaState(AutomatonState):
self.__transitions = {}
self.__unclosed = set()
self.__epsilon_closure = None
- self.__transition_action = None
+ self.__action = None
def epsilon_closure(self):
return self.__epsilon_closure
@@ -47,10 +47,14 @@ class NfaState(AutomatonState):
assert self.__epsilon_closure == None
self.__epsilon_closure = frozenset(closure)
- def set_transition_action(self, action):
+ def action(self):
+ assert self.is_closed()
+ return self.__action
+
+ def set_action(self, action):
assert not self.is_closed()
- assert self.__transition_action == None
- self.__transition_action = action
+ assert not self.__action
+ self.__action = action
def transitions(self):
assert self.is_closed()
@@ -58,27 +62,25 @@ class NfaState(AutomatonState):
def next_states(self, key_filter):
assert self.is_closed()
- first = lambda v: [x[0] for x in v]
- f = lambda acc, (k, v) : acc if not key_filter(k) else acc | set(first(v))
+ f = lambda acc, (k, v) : acc if not key_filter(k) else acc | set(v)
return reduce(f, self.__transitions.items(), set())
- def __add_transition(self, key, action, next_state):
+ def __add_transition(self, key, next_state):
if next_state == None:
- assert not action
assert not self.is_closed(), "already closed"
self.__unclosed.add(key)
return
if not key in self.__transitions:
self.__transitions[key] = set()
- self.__transitions[key].add((next_state, action))
+ self.__transitions[key].add(next_state)
def add_unclosed_transition(self, key):
assert key != TransitionKey.epsilon()
- self.__add_transition(key, None, None)
+ self.__add_transition(key, None)
def add_epsilon_transition(self, state):
assert state != None
- self.__add_transition(TransitionKey.epsilon(), None, state)
+ self.__add_transition(TransitionKey.epsilon(), state)
def is_closed(self):
return self.__unclosed == None
@@ -86,14 +88,13 @@ class NfaState(AutomatonState):
def close(self, end):
assert not self.is_closed()
unclosed, self.__unclosed = self.__unclosed, None
- action, self.__transition_action = self.__transition_action, None
if end == None:
- assert not unclosed and not action
+ assert not unclosed
return
for key in unclosed:
- self.__add_transition(key, action, end)
+ self.__add_transition(key, end)
if not unclosed:
- self.__add_transition(TransitionKey.epsilon(), action, end)
+ self.__add_transition(TransitionKey.epsilon(), end)
def __matches(self, match_func, value):
f = lambda acc, (k, vs): acc | vs if match_func(k, value) else acc
@@ -105,9 +106,6 @@ class NfaState(AutomatonState):
def key_matches(self, value):
return self.__matches(lambda k, v : k.matches_key(v), value)
- def __str__(self):
- return "NfaState(" + str(self.node_number()) + ")"
-
@staticmethod
def gather_transition_keys(state_set):
f = lambda acc, state: acc | set(state.__transitions.keys())
@@ -205,21 +203,12 @@ class NfaBuilder:
return self.__key_state(TransitionKey.any())
def __action(self, graph):
- incoming = graph[3]
(start, ends) = self.__process(graph[1])
action = graph[2]
- if incoming:
- new_start = self.__new_state()
- new_start.set_transition_action(action)
- new_start.close(start)
- start = new_start
- else:
- new_end = self.__new_state()
- for end in ends:
- end.set_transition_action(action)
- self.__patch_ends(ends, new_end)
- ends = [new_end]
- return (start, ends)
+ end = self.__new_state()
+ self.__patch_ends(ends, end)
+ end.set_action(action)
+ return (start, [end])
def __continue(self, graph):
(start, ends) = self.__process(graph[1])
@@ -233,12 +222,16 @@ class NfaBuilder:
return (start, ends)
def __join(self, graph):
- (graph, name, subgraph) = graph[1:]
+ (graph, name, subgraph, modifier) = graph[1:]
subgraphs = self.__peek_state()['subgraphs']
if not name in subgraphs:
subgraphs[name] = self.__nfa(subgraph)
(subgraph_start, subgraph_end, nodes_in_subgraph) = subgraphs[name]
(start, ends) = self.__process(graph)
+ if modifier:
+ assert modifier == 'ZERO_OR_MORE'
+ for end in ends:
+ end.add_epsilon_transition(subgraph_end)
self.__patch_ends(ends, subgraph_start)
end = self.__new_state()
subgraph_end.add_epsilon_transition(end)
@@ -290,19 +283,17 @@ class NfaBuilder:
@staticmethod
def add_action(graph, action):
- return ('ACTION', graph, action, False)
-
- @staticmethod
- def add_incoming_action(graph, action):
- return ('ACTION', graph, action, True)
+ return ('ACTION', graph, action)
@staticmethod
def add_continue(graph):
return ('CONTINUE', graph)
@staticmethod
- def join_subgraph(graph, name, subgraph):
- return ('JOIN', graph, name, subgraph)
+ def join_subgraph(graph, name, subgraph, modifier):
+ if modifier:
+ modifier = NfaBuilder.__modifer_map[modifier]
+ return ('JOIN', graph, name, subgraph, modifier)
@staticmethod
def or_graphs(graphs):
@@ -372,7 +363,7 @@ class Nfa(Automaton):
transitions = reduce(f, valid_states, set())
if not transitions:
return False
- valid_states = Nfa.__close(set([x[0] for x in transitions]))
+ valid_states = Nfa.__close(transitions)
return self.__end in valid_states
@staticmethod
@@ -382,38 +373,25 @@ class Nfa(Automaton):
name = ".".join(str(x.node_number()) for x in sorted(nfa_state_set))
if name in dfa_nodes:
return name
+ def gather_actions(states):
+ actions = set()
+ for state in states:
+ if state.action():
+ actions.add(state.action())
+ actions = list(actions)
+ actions.sort()
+ return actions
dfa_nodes[name] = {
'transitions': {},
- 'terminal': end_node in nfa_state_set}
+ 'terminal': end_node in nfa_state_set,
+ 'actions' : gather_actions(nfa_state_set)}
for key in NfaState.gather_transition_keys(nfa_state_set):
- f = lambda acc, state: acc | state.key_matches(key)
- transitions = reduce(f, nfa_state_set, set())
match_states = set()
- actions = []
- for (state, action) in transitions:
+ f = lambda acc, state: acc | state.key_matches(key)
+ for state in reduce(f, nfa_state_set, set()):
match_states.add(state)
- if action:
- actions.append(action)
-
- # Pull in actions which can be taken with an epsilon transition from the
- # match state.
- e = TransitionKey.epsilon()
- if e in state.transitions():
- for e_trans in state.transitions()[e]:
- if e_trans[1]:
- actions.append(e_trans[1])
- for s in state.epsilon_closure():
- if e in s.transitions():
- for e_trans in s.transitions()[e]:
- if e_trans[1]:
- actions.append(e_trans[1])
-
- assert len(match_states) == len(transitions)
-
- actions.sort()
- action = actions[0] if actions else None
transition_state = Nfa.__to_dfa(match_states, dfa_nodes, end_node)
- dfa_nodes[name]['transitions'][key] = (transition_state, action)
+ dfa_nodes[name]['transitions'][key] = transition_state
return name
def compute_dfa(self):
@@ -424,4 +402,5 @@ class Nfa(Automaton):
def to_dot(self):
iterator = lambda visitor, state: self.__visit_all_edges(visitor, state)
- return self.generate_dot(self.__start, set([self.__end]), iterator)
+ state_iterator = lambda x : x
+ return self.generate_dot(self.__start, set([self.__end]), iterator, state_iterator)
« no previous file with comments | « tools/lexer_generator/lexer_test.py ('k') | tools/lexer_generator/rule_lexer.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698