trac-gviz / trac-dev / gviz / tracgviz / util / parsing.py

Diff from to

trac-dev/gviz/tracgviz/util/parsing.py

     a new set of grammar productions. All previous state is discarded.
     """
     self.start_state = None
-    self.nfirst = {}
-    self.nlast = {}
-    self.pre = {}
-    self.post = {}
     self.precedence = {}
     self.productions_tree = {}
 
+    self.precedence, self.productions_tree = self.process_productions(
+        *productions)
+
+    # Everything ok , assign instance methods now
+    self.start_state = start_state
+
+  @classmethod
+  def process_productions(cls, *productions):
+    r"""Generate precedence and production look up tree according to 
+    a set of grammar productions.
+    """
     nfirst = {}
     nlast = {}
     pre = {}
 
       for prod_id, state, ps in productions:
         if not ps:
-          raise InvalidProduction(self, 'Empty productions not allowed')
+          raise InvalidProduction(cls, 'Empty productions not allowed')
 
         # Update skeletal production path
         choices = productions_tree
         if len(ps) == 1:
           if subtkn in NonTerminal:
             if state == subval:
-              raise InvalidProduction(self, 'Infinite recursion state=' + state)
+              raise InvalidProduction(cls, 'Infinite recursion state=' + state)
             else:
               # PRE and POST for subval should be propagated back to state
               _update(state, nfirst, pre, nt=subval)
                 # Terminals in PRE have less precedence
                 for terminal in pre.setdefault(subval, set()):
                   key = (prev_t, terminal)
-                  if precedence.get(key) not in (None, self.LessPrecedence):
+                  if precedence.get(key) not in (None, cls.LessPrecedence):
                     raise InvalidParserConfiguration(
                         "Failed to establish precedence")
-                  precedence[key] = self.LessPrecedence
+                  precedence[key] = cls.LessPrecedence
             prev_nt = subval
           else:
             if prev_t:
               # Adjacent terminals have the same precedence
               key = (prev_t, (subtkn, subval))
-              if precedence.get(key) not in (None, self.SamePrecedence):
+              if precedence.get(key) not in (None, cls.SamePrecedence):
                 raise InvalidParserConfiguration(
                     "Failed to establish precedence")
-              precedence[key] = self.SamePrecedence
+              precedence[key] = cls.SamePrecedence
             if prev_nt:
               # Terminals in previous non-terminal's POST have more precedence
               for terminal in post.setdefault(prev_nt, set()):
                 key = (terminal, (subtkn, subval))
-                if precedence.get(key) not in (None, self.MorePrecedence):
+                if precedence.get(key) not in (None, cls.MorePrecedence):
                   raise InvalidParserConfiguration(
                       "Failed to establish precedence")
-                precedence[key] = self.MorePrecedence
+                precedence[key] = cls.MorePrecedence
             prev_t = (subtkn, subval)
             # Non-terminal has to be adjacent to terminal
             prev_nt = None
     # End-markers precedence
     for nt, nt_pre in pre.iteritems():
       for terminal in nt_pre:
-        precedence[((EndMarker, nt), terminal)] = self.LessPrecedence
+        precedence[((EndMarker, nt), terminal)] = cls.LessPrecedence
     for nt, nt_post in post.iteritems():
       for terminal in nt_post:
-        precedence[(terminal, (EndMarker, nt))] = self.MorePrecedence
+        precedence[(terminal, (EndMarker, nt))] = cls.MorePrecedence
 
-    # Everything ok , assign instance methods now
-    self.start_state = start_state
-    self.nfirst = nfirst
-    self.nlast = nlast
-    self.pre = pre
-    self.post = post
-    self.precedence = precedence
-    self.productions_tree = productions_tree
+    return precedence, productions_tree
 
   def parse(self, stream, on_reduce, start_state=None):
     r"""Parse a token `stream` of tokens.
     RuntimeError.__init__(self, *args)
 
   def __unicode__(self):
-    return "Parser %s failed: %" % (self.parser.__class__.__name__,
+    cls = self.parser \
+        if isinstance(self.parser, type) else self.parser.__class__
+    return "Parser %s failed: %s" % (cls.__name__,
         RuntimeError.__unicode__(self))
 
 class InvalidParserConfiguration(ParserError):
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.