Anonymous avatar Anonymous committed f87df25

some bugfixes and a new tuple handling for compose()

Comments (0)

Files changed (1)

pypeg2/__init__.py

 import collections
 import sys
 import weakref
+import warnings
 from functools import reduce
 from types import FunctionType
 
     Instance variables:
         Class       reference to Attribute class generated by namedtuple()
     """
+    if __debug__:
+        if isinstance(thing, (tuple, Concat)):
+            warnings.warn(type(thing).__name__ + " not recommended as grammar of attribute "
+                    + repr(name), SyntaxWarning)
     return attr.Class(name, thing, subtype)
 
 attr.Class = collections.namedtuple("Attribute", ("name", "thing", "subtype"))
         self.text = None
         self.filename = None
         self._memory = {}
-        self._got_endl = False
+        self._got_endl = True
 
     def parse(self, text, thing, filename=None):
         """(Partially) parse text following thing as grammar and return the
             GrammarValueError
                             if grammar contains an illegal cardinality value
         """
- 
+        if __debug__:
+            # make sure that we're not having this type error
+            compose = None
+
         def terminal_indent():
             if self._got_endl:
                 result = self.indent * self.indention_level
             try:
                 grammar = type(thing).grammar
             except AttributeError:
-                if isinstance(thing, list):
+                if isinstance(thing, Symbol):
+                    grammar = type(thing).regex
+                elif isinstance(thing, list):
                     grammar = csl(Symbol)
                 else:
                     grammar = word
+            else:
+                if isinstance(thing, Symbol):
+                    grammar = type(thing).regex
 
         if grammar is None:
             result = ""
 
         elif type(grammar) == FunctionType:
             if grammar == endl:
-                result = "\n"
+                result = endl(thing, self)
                 self._got_endl = True
             else:
                 result = self.compose(thing, grammar(thing, self))
             if m:
                 result = terminal_indent() + str(thing)
             else:
-                raise ValueError(repr(thing) + " does not match " + grammar.pattern)
+                raise ValueError(repr(thing) + " does not match "
+                        + grammar.pattern)
 
         elif isinstance(grammar, (str, Literal)):
             result = terminal_indent() + str(grammar)
         elif isinstance(grammar, attr.Class):
             if grammar.subtype == "Flag":
                 if getattr(thing, grammar.name):
-                    result = terminal_indent() + compose(grammar.thing)
+                    result = self.compose(grammar.thing)
                 else:
-                    result = ""
+                    result = terminal_indent()
             else:
-                result = self.compose(getattr(thing, grammar.name), grammar.thing)
+                result = self.compose(getattr(thing, grammar.name),
+                        grammar.thing)
 
         elif isinstance(grammar, (tuple, Concat)):
             def compose_tuple(thing, things, grammar):
                 multiple, card = 1, 1
                 indenting = 0
                 for g in grammar:
-                    if type(g) == int:
+                    if g is None:
+                        multiple = 1
+                        if self.indenting:
+                            self.indention_level -= indenting
+                            self.indenting = 0
+                    elif type(g) == int:
                         if g < -3:
                             raise GrammarValueError(
                                 "illegal cardinality value in grammar: " +
                             multiple = 1
                             if g == -3:
                                 self.indention_level += 1
-                                indenting = 1
+                                indenting += 1
                         else:
                             multiple = g
                     else:
-                        if card == -2 and not things:
-                            raise ValueError("not enough things to compose; "
-                                    + "expecting " + repr(g))
-                        if indenting == 1:
-                            indenting = 2
-                        elif indenting == 2:
-                            self.indention_level -= 1
+                        passes = 0
+                        try:
+                            for r in range(multiple):
+                                if isinstance(g, (str, Symbol, Literal)):
+                                    text.append(terminal_indent() + str(g))
+                                    if card < 1:
+                                        break
+                                elif isinstance(g, FunctionType):
+                                    text.append(self.compose(thing, g))
+                                    if card < 1:
+                                        break
+                                elif isinstance(g, attr.Class):
+                                    text.append(self.compose(thing, g))
+                                    if card < 1:
+                                        break
+                                elif isinstance(g, (tuple, Concat)):
+                                    text.append(compose_tuple(thing, things, g))
+                                    if not things:
+                                        break
+                                else:
+                                    text.append(self.compose(things.pop(), g))
+                                passes += 1
+                        except (IndexError, ValueError):
+                            if card == -2:
+                                if passes < 1:
+                                    raise ValueError(repr(g)
+                                            + " has to be there at least once")
+                            elif card > 0:
+                                if passes < multiple:
+                                    raise ValueError(repr(g)
+                                            + " has to be there exactly "
+                                            + str(multiple) + " times")
+                        multiple = 1
+                        if indenting:
+                            self.indention_level -= indenting
                             indenting = 0
-                        if type(g) == attr.Class:
-                            text.append(self.compose(thing, g))
-                        elif type(g) == str or isinstance(g, Keyword):
-                            if card > 0:
-                                for i in range(multiple):
-                                    text.append(terminal_indent() + str(g))
-                            elif card == -2:
-                                text.append(terminal_indent() + str(g))
-                        else:
-                            for j in range(multiple):
-                                try:
-                                    if type(g) == tuple:
-                                        if not things:
-                                            return ''.join(text)
-                                        text.append(compose_tuple(thing,
-                                            things, g))
-                                    else:
-                                        if g is None:
-                                            pass
-                                        elif type(g) == FunctionType:
-                                            text.append(self.compose(things,
-                                                g))
-                                        elif type(g) == str or isinstance(g,
-                                                Keyword):
-                                            text.append(self.compose(things,
-                                                g))
-                                        elif type(things) == list:
-                                            if not things:
-                                                return ''.join(text)
-                                            text.append(self.compose(things[0],
-                                                g))
-                                            del things[0]
-                                        else:
-                                            text.append(self.compose(things,
-                                                g))
-                                except ValueError:
-                                    if card == -1 or card == 0:
-                                        return ''.join(text)
-                                    else:
-                                        raise
-                        multiple = 1
-                    if indenting == 2:
-                        self.indention_level -= 1
-                        indenting = 0
+
                 return ''.join(text)
 
             if isinstance(thing, Namespace):
                 L = [e for e in thing.values()]
-                result = compose_tuple(thing, L, grammar)
+                L.reverse()
             elif isinstance(thing, list):
-                result = compose_tuple(thing, thing[:], grammar)
+                L = thing[:]
+                L.reverse()
             else:
-                result = compose_tuple(thing, thing, grammar)
+                L = [thing]
+            result = compose_tuple(thing, L, grammar)
 
         elif isinstance(grammar, list):
             found = False
                 try:
                     grammar.grammar
                 except AttributeError:
-                    if isinstance(grammar, list):
-                        result = self.compose(thing, csl(Symbol))
+                    if _issubclass(grammar, Symbol):
+                        result = self.compose(thing, grammar.regex)
                     else:
-                        result = self.compose(thing, word)
+                        result = self.compose(thing)
                 else:
                     result = self.compose(thing, grammar.grammar)
             else:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.