Revision: 17576
Author:   [email protected]
Date:     Fri Nov  8 07:29:01 2013 UTC
Log:      Experimental parser: some support for adding subraphs

[email protected]

BUG=

Review URL: https://codereview.chromium.org/66293002
http://code.google.com/p/v8/source/detail?r=17576

Modified:
 /branches/experimental/parser/tools/lexer_generator/generator.py
 /branches/experimental/parser/tools/lexer_generator/nfa.py

=======================================
--- /branches/experimental/parser/tools/lexer_generator/generator.py Thu Nov 7 12:03:35 2013 UTC +++ /branches/experimental/parser/tools/lexer_generator/generator.py Fri Nov 8 07:29:01 2013 UTC
@@ -80,12 +80,34 @@
   builder = NfaBuilder()
   builder.set_character_classes(parser_state.character_classes)
   assert 'default' in parser_state.rules
-  for k, v in parser_state.rules.items():
+  def process(k, v):
     assert 'default' in v
     graphs = []
     for (graph, action) in v['regex']:
-      graphs.append(NfaBuilder.add_action(graph, action))
-    rule_map[k] = NfaBuilder.or_graphs(graphs)
+      (precedence, code, transition) = action
+      if code:
+        graph = NfaBuilder.add_action(graph, (precedence, code, None))
+      if transition == 'continue':
+        graph = NfaBuilder.add_continue(graph)
+      elif (transition == 'break' or
+            transition == 'terminate' or
+            transition == 'terminate_illegal'):
+        pass
+      else:
+        assert k == 'default'
+ graph = NfaBuilder.join_subgraph(graph, transition, rule_map[transition])
+      graphs.append(graph)
+    graph = NfaBuilder.or_graphs(graphs)
+    # merge default action
+    (precedence, code, transition) = v['default'][1]
+    assert transition == 'continue' or transition == 'break'
+    if code:
+ graph = NfaBuilder.add_incoming_action(graph, (precedence, code, None))
+    rule_map[k] = graph
+  for k, v in parser_state.rules.items():
+    if k == 'default': continue
+    process(k, v)
+  process('default', parser_state.rules['default'])
   html_data = []
   for rule_name, graph in rule_map.items():
     nfa = builder.nfa(graph)
@@ -98,11 +120,12 @@

   parser = argparse.ArgumentParser()
   parser.add_argument('--html')
+  parser.add_argument('--re', default='src/lexer/lexer_py.re')
   args = parser.parse_args()

-  re_file = 'src/lexer/lexer_py.re'
-
+  re_file = args.re
   parser_state = RuleParserState()
+  print "parsing %s" % re_file
   with open(re_file, 'r') as f:
     RuleParser.parse(f.read(), parser_state)
   html_data = process_rules(parser_state)
=======================================
--- /branches/experimental/parser/tools/lexer_generator/nfa.py Thu Nov 7 12:55:33 2013 UTC +++ /branches/experimental/parser/tools/lexer_generator/nfa.py Fri Nov 8 07:29:01 2013 UTC
@@ -88,8 +88,7 @@
     unclosed, self.__unclosed = self.__unclosed, None
     action, self.__transition_action = self.__transition_action, None
     if end == None:
-      assert not unclosed
-      assert not action
+      assert not unclosed and not action
       return
     for key in unclosed:
       self.__add_transition(key, action, end)
@@ -121,6 +120,7 @@
     self.__operation_map = {}
     self.__members = getmembers(self)
     self.__character_classes = {}
+    self.__states = []

   def set_character_classes(self, classes):
     self.__character_classes = classes
@@ -205,21 +205,42 @@
     return self.__key_state(TransitionKey.any())

   def __action(self, graph):
-    result = self.__process(graph[1])
-    for end in result[1]:
-      end.set_transition_action(graph[2])
-    return result
+    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:
+      for end in ends:
+        end.set_transition_action(action)
+    return (start, ends)

   def __continue(self, graph):
     (start, ends) = self.__process(graph[1])
-    if not self.__start_node:
-      self.__start_node = self.__new_state()
+    state = self.__peek_state()
+    if not state['start_node']:
+      state['start_node'] = self.__new_state()
     end = self.__new_state()
     self.__patch_ends(ends, end)
     ends = [end]
-    end.add_epsilon_transition(self.__start_node)
+    end.add_epsilon_transition(state['start_node'])
     return (start, ends)

+  def __join(self, graph):
+    (graph, name, subgraph) = 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)
+    self.__patch_ends(ends, subgraph_start)
+    end = self.__new_state()
+    subgraph_end.add_epsilon_transition(end)
+    return (start, [end])
+
   def __process(self, graph):
     assert type(graph) == TupleType
     method = "_NfaBuilder__" + graph[0].lower()
@@ -233,26 +254,53 @@
     for end in ends:
       end.close(new_end)

-  def nfa(self, graph):
-    self.__start_node = None
+  def __push_state(self):
+    self.__states.append({
+      'start_node' : None,
+      'subgraphs' : {},
+    })
+
+  def __pop_state(self):
+    return self.__states.pop()
+
+  def __peek_state(self):
+    return self.__states[len(self.__states) - 1]
+
+  def __nfa(self, graph):
     start_node_number = self.__node_number
+    self.__push_state()
     (start, ends) = self.__process(graph)
-    if self.__start_node:
-      self.__start_node.close(start)
-      start = self.__start_node
+    state = self.__pop_state()
+    if state['start_node']:
+      state['start_node'].close(start)
+      start = state['start_node']
+    for k, subgraph in state['subgraphs'].items():
+      subgraph[1].close(None)
     end =  self.__new_state()
     self.__patch_ends(ends, end)
+    return (start, end, self.__node_number - start_node_number)
+
+  def nfa(self, graph):
+    (start, end, nodes_created) = self.__nfa(graph)
     end.close(None)
-    return Nfa(start, end, self.__node_number - start_node_number)
+    return Nfa(start, end, nodes_created)

   @staticmethod
   def add_action(graph, action):
-    return ('ACTION', graph, action)
+    return ('ACTION', graph, action, False)
+
+  @staticmethod
+  def add_incoming_action(graph, action):
+    return ('ACTION', graph, action, True)

   @staticmethod
   def add_continue(graph):
     return ('CONTINUE', graph)

+  @staticmethod
+  def join_subgraph(graph, name, subgraph):
+    return ('JOIN', graph, name, subgraph)
+
   @staticmethod
   def or_graphs(graphs):
     return reduce(lambda acc, g: ('OR', acc, g), graphs)

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to