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

Unified Diff: tools/lexer_generator/nfa_builder.py

Issue 137883006: Experimental parser: use Terms instead of tuples (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 11 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 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/regex_parser.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/lexer_generator/nfa_builder.py
diff --git a/tools/lexer_generator/nfa_builder.py b/tools/lexer_generator/nfa_builder.py
index 0c066d9e8c858d403a6d757df8bbfa2e510da3a3..a7ee4bf90e5314705753369ecfcb971b06dc36a6 100644
--- a/tools/lexer_generator/nfa_builder.py
+++ b/tools/lexer_generator/nfa_builder.py
@@ -27,6 +27,7 @@
from types import TupleType
from inspect import getmembers
+from action import *
from nfa import *
# Nfa is built in two stages:
@@ -40,7 +41,7 @@ from nfa import *
class NfaBuilder(object):
- def __init__(self, encoding, character_classes = {}):
+ def __init__(self, encoding, character_classes):
self.__node_number = 0
self.__operation_map = {}
self.__members = getmembers(self)
@@ -58,39 +59,39 @@ class NfaBuilder(object):
self.__global_end_node = self.__new_state()
return self.__global_end_node
- def __or(self, graph):
+ def __or(self, args):
start = self.__new_state()
ends = []
- for x in [self.__process(graph[1]), self.__process(graph[2])]:
+ for x in [self.__process(args[0]), self.__process(args[1])]:
start.add_epsilon_transition(x[0])
ends += x[1]
start.close(None)
return (start, ends)
- def __one_or_more(self, graph):
- (start, ends) = self.__process(graph[1])
+ def __one_or_more(self, args):
+ (start, ends) = self.__process(args[0])
end = self.__new_state()
end.add_epsilon_transition(start)
self.__patch_ends(ends, end)
return (start, [end])
- def __zero_or_more(self, graph):
- (node, ends) = self.__process(graph[1])
+ def __zero_or_more(self, args):
+ (node, ends) = self.__process(args[0])
start = self.__new_state()
start.add_epsilon_transition(node)
self.__patch_ends(ends, start)
return (start, [start])
- def __zero_or_one(self, graph):
- (node, ends) = self.__process(graph[1])
+ def __zero_or_one(self, args):
+ (node, ends) = self.__process(args[0])
start = self.__new_state()
start.add_epsilon_transition(node)
return (start, ends + [start])
- def __repeat(self, graph):
- param_min = int(graph[1])
- param_max = int(graph[2])
- subgraph = graph[3]
+ def __repeat(self, args):
+ param_min = int(args[0])
+ param_max = int(args[1])
+ subgraph = args[2]
(start, ends) = self.__process(subgraph)
for i in xrange(1, param_min):
(start2, ends2) = self.__process(subgraph)
@@ -109,8 +110,8 @@ class NfaBuilder(object):
return (start, ends + midpoints)
- def __cat(self, graph):
- (left, right) = (self.__process(graph[1]), self.__process(graph[2]))
+ def __cat(self, args):
+ (left, right) = (self.__process(args[0]), self.__process(args[1]))
self.__patch_ends(left[1], right[0])
return (left[0], right[1])
@@ -119,30 +120,27 @@ class NfaBuilder(object):
state.add_unclosed_transition(key)
return (state, [state])
- def __literal(self, graph):
+ def __literal(self, args):
+ assert len(args) == 1
return self.__key_state(
- TransitionKey.single_char(self.__encoding, graph[1]))
+ TransitionKey.single_char(self.__encoding, args[0]))
- def __class(self, graph):
+ def __class(self, args):
+ assert len(args) == 1
return self.__key_state(TransitionKey.character_class(
- self.__encoding, graph, self.__character_classes))
+ self.__encoding, Term('CLASS', args[0]), self.__character_classes))
- def __not_class(self, graph):
+ def __not_class(self, args):
+ assert len(args) == 1
return self.__key_state(TransitionKey.character_class(
- self.__encoding, graph, self.__character_classes))
+ self.__encoding, Term('NOT_CLASS', args[0]), self.__character_classes))
- def __any(self, graph):
+ def __any(self, args):
return self.__key_state(TransitionKey.any(self.__encoding))
- def __epsilon(self, graph):
- start = self.__new_state()
- end = self.__new_state()
- start.close(end)
- return (start, [end])
-
- def __action(self, graph):
- (start, ends) = self.__process(graph[1])
- action = graph[2]
+ def __action(self, args):
+ (start, ends) = self.__process(args[0])
+ action = Action.from_term(args[1])
end = self.__new_state()
self.__patch_ends(ends, end)
end.set_action(action)
@@ -151,19 +149,18 @@ class NfaBuilder(object):
end.add_epsilon_transition(global_end)
return (start, [end])
- def __continue(self, graph):
- (start, ends) = self.__process(graph[1])
+ def __continue(self, args):
+ (start, ends) = self.__process(args[0])
state = self.__peek_state()
if not state['start_node']:
state['start_node'] = self.__new_state()
self.__patch_ends(ends, state['start_node'])
return (start, [])
- def __unique_key(self, graph):
- return self.__key_state(TransitionKey.unique(graph[1]))
+ def __unique_key(self, args):
+ return self.__key_state(TransitionKey.unique(args[0]))
- def __join(self, graph):
- (graph, name, subgraph) = graph[1:]
+ def __join(self, (graph, name, subgraph)):
subgraphs = self.__peek_state()['subgraphs']
if not name in subgraphs:
subgraphs[name] = self.__nfa(subgraph)
@@ -177,14 +174,14 @@ class NfaBuilder(object):
else:
return (start, [])
- def __process(self, graph):
- assert type(graph) == TupleType
- method = "_NfaBuilder__" + graph[0].lower()
+ def __process(self, term):
+ assert isinstance(term, Term)
+ method = "_NfaBuilder__" + term.name().lower()
if not method in self.__operation_map:
matches = filter(lambda (name, func): name == method, self.__members)
assert len(matches) == 1
self.__operation_map[method] = matches[0][1]
- return self.__operation_map[method](graph)
+ return self.__operation_map[method](term.args())
def __patch_ends(self, ends, new_end):
for end in ends:
@@ -203,10 +200,10 @@ class NfaBuilder(object):
def __peek_state(self):
return self.__states[-1]
- def __nfa(self, graph):
+ def __nfa(self, term):
start_node_number = self.__node_number
self.__push_state()
- (start, ends) = self.__process(graph)
+ (start, ends) = self.__process(term)
state = self.__pop_state()
if state['start_node']:
state['start_node'].close(start)
@@ -257,8 +254,11 @@ class NfaBuilder(object):
transitions[inverse_key] = transitions[catch_all]
del transitions[catch_all]
- def nfa(self, graph):
- (start, end, nodes_created) = self.__nfa(graph)
+ @staticmethod
+ def nfa(encoding, character_classes, rule_term):
+
+ self = NfaBuilder(encoding, character_classes)
+ (start, end, nodes_created) = self.__nfa(rule_term)
global_end_to_return = self.__global_end_node or end
assert global_end_to_return
@@ -267,10 +267,6 @@ class NfaBuilder(object):
global_end_to_return.close(None)
- # FIXME: the same NfaBuilder should not be called twice, so this cleanup
- # should be unnecessary.
- self.__global_end_node = None
-
self.__compute_epsilon_closures(start)
f = lambda node, state: self.__replace_catch_all(self.__encoding, node)
Automaton.visit_states(set([start]), f)
@@ -278,63 +274,28 @@ class NfaBuilder(object):
return Nfa(self.__encoding, start, global_end_to_return, nodes_created)
@staticmethod
- def rule_tree_dot(graph):
- node_ix = [0]
- node_template = 'node [label="%s"]; N_%d;'
- edge_template = 'N_%d -> N_%d'
- nodes = []
- edges = []
-
- def escape(v):
- v = str(v)
- v = v.replace('\r', '\\\\r').replace('\t', '\\\\t').replace('\n', '\\\\n')
- v = v.replace('\\', '\\\\').replace('\"', '\\\"')
- return v
-
- def process_thing(thing):
- if isinstance(thing, str):
- node_ix[0] += 1
- nodes.append(node_template % (escape(thing), node_ix[0]))
- return node_ix[0]
- if isinstance(thing, tuple):
- child_ixs = map(process_thing, list(thing)[1:])
- node_ix[0] += 1
- nodes.append(node_template % (escape(thing[0]), node_ix[0]))
- for child_ix in child_ixs:
- edges.append(edge_template % (node_ix[0], child_ix))
- return node_ix[0]
- if isinstance(thing, Action):
- node_ix[0] += 1
- nodes.append(node_template % (str(thing), node_ix[0]))
- return node_ix[0]
- raise Exception
-
- process_thing(graph)
- return 'digraph { %s %s }' % ('\n'.join(nodes), '\n'.join(edges))
-
- @staticmethod
- def add_action(graph, action):
- return ('ACTION', graph, action)
+ def add_action(term, action):
+ return Term('ACTION', term, action.to_term())
@staticmethod
- def add_continue(graph):
- return ('CONTINUE', graph)
+ def add_continue(term):
+ return Term('CONTINUE', term)
@staticmethod
def unique_key(name):
- return ('UNIQUE_KEY', name)
+ return Term('UNIQUE_KEY', name)
@staticmethod
- def join_subgraph(graph, name, subgraph):
- return ('JOIN', graph, name, subgraph)
+ def join_subgraph(term, name, subgraph_term):
+ return Term('JOIN', term, name, subgraph_term)
@staticmethod
- def or_graphs(graphs):
- return reduce(lambda acc, g: ('OR', acc, g), graphs)
+ def or_terms(terms):
+ return reduce(lambda acc, g: Term('OR', acc, g), terms)
@staticmethod
- def cat_graphs(graphs):
- return reduce(lambda acc, g: ('CAT', acc, g), graphs)
+ def cat_terms(terms):
+ return reduce(lambda acc, g: Term('CAT', acc, g), terms)
__modifer_map = {
'+': 'ONE_OR_MORE',
@@ -343,5 +304,5 @@ class NfaBuilder(object):
}
@staticmethod
- def apply_modifier(modifier, graph):
- return (NfaBuilder.__modifer_map[modifier], graph)
+ def apply_modifier(modifier, term):
+ return Term(NfaBuilder.__modifer_map[modifier], term)
« no previous file with comments | « tools/lexer_generator/lexer_test.py ('k') | tools/lexer_generator/regex_parser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698