[pypy-svn] r35173 - pypy/dist/pypy/rlib/parsing

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Nov 30 17:06:34 CET 2006


Author: cfbolz
Date: Thu Nov 30 17:06:33 2006
New Revision: 35173

Modified:
   pypy/dist/pypy/rlib/parsing/ebnfparse.py
Log:
nicer way to create the rules for *, ? and +


Modified: pypy/dist/pypy/rlib/parsing/ebnfparse.py
==============================================================================
--- pypy/dist/pypy/rlib/parsing/ebnfparse.py	(original)
+++ pypy/dist/pypy/rlib/parsing/ebnfparse.py	Thu Nov 30 17:06:33 2006
@@ -214,11 +214,14 @@
 
     def add_all_possibilities(self):
         all_rules = []
+        other_rules = []
         all_changes = []
+        other_changes = []
         for rule, changes in zip(self.rules, self.changes):
             real_changes = []
             real_expansions = []
-            for expansion, change in zip(rule.expansions, changes):
+            for index, (expansion, change) in enumerate(
+                    zip(rule.expansions, changes)):
                 maybe_pattern = [symbol in self.maybe_rules
                                      for symbol in expansion]
                 n = maybe_pattern.count(True)
@@ -229,23 +232,41 @@
                 assert n != len(expansion), (
                     "currently an expansion needs at least one"
                     "symbol that always has to occur")
-                maybe_index = {}
-                for i, star in enumerate(maybe_pattern):
-                    if star:
-                        maybe_index[i] = len(maybe_index)
-                for i in range(2 ** n):
-                    real_expansion = []
-                    real_change = []
-                    for j, (symbol, ch) in enumerate(zip(expansion, change)):
-                        if (j not in maybe_index or
-                            (i & (2 ** (n - 1) >> maybe_index[j])) == 0):
-                            real_expansion.append(symbol)
-                            real_change.append(ch)
-                    real_expansions.append(real_expansion)
-                    real_changes.append(real_change)
+                slices = []
+                start = 0
+                for i, (maybe, symbol) in enumerate(
+                        zip(maybe_pattern, expansion)):
+                    if maybe:
+                        slices.append((start, i + 1))
+                        start = i + 1
+                rest_slice = (start, i + 1)
+                name = rule.nonterminal
+                for i, (start, stop) in enumerate(slices):
+                    nextname = "__%s_rest_%s_%s" % (rule.nonterminal, index, i)
+                    if i < len(slices) - 1:
+                        new_expansions = [
+                            expansion[start: stop] + [nextname],
+                            expansion[start: stop - 1] + [nextname]]
+                        new_changes = [change[start: stop] + ">",
+                                       change[start: stop - 1] + ">"]
+                    else:
+                        rest_expansion = expansion[slice(*rest_slice)]
+                        new_expansions = [
+                            expansion[start: stop] + rest_expansion,
+                            expansion[start: stop - 1] + rest_expansion]
+                        rest_change = change[slice(*rest_slice)]
+                        new_changes = [change[start: stop] + rest_change,
+                                       change[start: stop - 1] + rest_change]
+                    if i == 0:
+                        real_expansions += new_expansions
+                        real_changes += new_changes
+                    else:
+                        other_rules.append(Rule(name, new_expansions))
+                        other_changes.append(new_changes)
+                    name = nextname
             all_rules.append(Rule(rule.nonterminal, real_expansions))
             all_changes.append(real_changes)
-        return all_rules, all_changes
+        return all_rules + other_rules, all_changes + other_changes
 
 class TransformerMaker(object):
     def __init__(self, rules, changes):
@@ -280,6 +301,7 @@
         assert isinstance(ToAST, type)
         assert ToAST.__name__ == "ToAST"
         ToAST.source = code
+        ToAST.changes = self.changes
         return ToAST
 
     def emit(self, line):



More information about the Pypy-commit mailing list