Olemis Lang avatar Olemis Lang committed 8c84312

GViz QL: GViz QL grammar. Production processing algorithm is class method now

Comments (0)

Files changed (2)

trac-dev/gviz/tracgviz/grammar.py

 # Grammar
 # =======
 
-GVIZ_START_STATE = 'GVIZ_SQL'
+GVIZ_QL_START_STATE = 'GVIZ_SQL'
 
-_And        = (Operator.Word.Boolean, 'and')
-_Or         = (Operator.Word.Boolean, 'or')
-_Not        = (Operator.Word.Boolean, 'not')
-_Number     = (Number, Any)
-_Var        = (Name.Variable, Any)
-_Str        = (String, Any)
-_Date       = (Literal.Date, Any)
-_Const      = (Name.Constant, Any)
-_Builtin    = (Name.Builtin, Any)
-_Function   = (Name.Function, Any)
-_Comma      = (Punctuation, ',')
-_OpenP      = (Punctuation, '(')
-_CloseP     = (Punctuation, ')')
-_Sum        = (Operator.Arithmetic, '+')
-_Multiply   = (Operator.Arithmetic, '*')
-_Subtract   = (Operator.Arithmetic, '-')
-_Divide     = (Operator.Arithmetic, '/')
-_BoolOp     = (Operator.Comparison, Any)
-_BoolWordOp = (Operator.Word.Comparison, Any)
-_EndAE      = (EndMarker, 'ARITHMETIC_EXPR')
-_EndBE      = (EndMarker, 'BOOL_EXPR')
-_EndSuite   = (EndMarker, 'SUITE')
+def gen_gvizql_grammar():
+  GVIZ_QL_SYMBOLS = [ 
+      (Operator.Word.Boolean, 'and'), 
+      (Operator.Word.Boolean, 'or'), 
+      (Operator.Word.Boolean, 'not'), 
+      (Number, Any), 
+      (Name.Variable, Any), 
+      (String, Any), 
+      (Literal.Date, Any), 
+      (Name.Constant, Any), 
+      (Name.Builtin, Any), 
+      (Name.Function, Any), 
+      (Punctuation, ','), 
+      (Punctuation, '('), 
+      (Punctuation, ')'), 
+      (Operator.Arithmetic, '+'), 
+      (Operator.Arithmetic, '*'), 
+      (Operator.Arithmetic, '-'), 
+      (Operator.Arithmetic, '/'), 
+      (Operator.Comparison, Any), 
+      (Operator.Word.Comparison, Any), 
+      (Keyword.Reserved, 'select'),
+      (Keyword.Reserved, 'where'),
+      (Keyword.Reserved, 'group by'),
+      (Keyword.Reserved, 'pivot'),
+      (Keyword.Reserved, 'order by'),
+      (Keyword.Reserved, 'limit'),
+      (Keyword.Reserved, 'offset'),
+      (Keyword.Reserved, 'label'),
+      (Keyword.Reserved, 'format'),
+      (Keyword.Reserved, 'options'),
+    ]
 
-GVIZ_PRODUCTIONS = [
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ['', '', [  ] ],
-  ],
+  _And, _Or, _Not, _Number, _Var, _Str, _Date, _Const, _Builtin, _Function, \
+  _Comma, _OpenP, _CloseP, _Plus, _Mult, _Minus, _Div, _BoolOp, \
+  _BoolWordOp, _Select, _Where, _GroupBy, _Pivot, _OrderBy, _Limit, _Offset, \
+  _Label, _Format, _Options = GVIZ_QL_TERMINALS
 
-#  1.   VALUE -> Number
-#  2.   VALUE -> Variable
-#  3.   VALUE -> String
-#  4.   VALUE -> Date
-#  5.   VALUE -> Constant
-#  6.   VALUE -> Builtin ( )
-#  7.   VALUE -> Builtin ( SUITE )
-#  8.   VALUE -> Function ( )
-#  9.   VALUE -> Function ( SUITE )
-#  10.  SUITE -> SUITE , ARITMETIC_EXPR
-#  10a. SUITE -> ARITMETIC_EXPR
-#  13.  ARITMETIC_EXPR -> ARITMETIC_EXPR + TERM
-#  14.  ARITMETIC_EXPR -> ARITMETIC_EXPR - TERM
-#  14a. ARITMETIC_EXPR -> TERM
-#  15.  TERM -> TERM * FACTOR
-#  15.a TERM -> FACTOR
-#  16.  FACTOR -> FACTOR / SIMPLE_EXPR
-#  16a. FACTOR -> SIMPLE_EXPR
-#  17.  SIMPLE_EXPR -> ( ARITHMETIC_EXPR )
-#  17a. SIMPLE_EXPR -> VALUE
-#  18.  BOOL_VALUE -> ARITHMETIC_EXPR Operator.Comparison ARITHMETIC_EXPR
-#  19.  BOOL_VALUE -> ARITHMETIC_EXPR Operator.Word.Comparison ARITHMETIC_EXPR
-#  20.  BOOL_VALUE -> not BOOL_VALUE
-#  21.  BOOL_EXPR -> BOOL_EXPR and OR_EXPR
-#  21a. BOOL_EXPR -> OR_EXPR
-#  22.  OR_EXPR -> OR_EXPR or BOOL_VALUE
-#  22a. OR_EXPR -> BOOL_VALUE
+  # GViz QL non-terminals
+  GVIZQL, CLAUSE, SEQ, COL_SEQ, COLUMN, BOOL_EXPR, LABEL_SEQ, \
+  LABEL_EXPR, VALUE, ARITHMETIC_EXPR, TERM, FACTOR, SIMPLE_EXPR, \
+  BOOL_VALUE, BOOL_EXPR, OR_EXPR = [(NonTerminal, x) for x in (
+    'GVIZQL', 'CLAUSE', 'SEQ', 'COLSEQ', 'COLUMN', 'BOOL_EXPR', 'LABELSEQ', \
+    'LABEL_EXPR', 'VALUE', 'ARITHMETIC_EXPR', 'TERM', 'FACTOR', 'SIMPLE_EXPR', \
+    'BOOL_VALUE', 'BOOL_EXPR', 'OR_EXPR' )]
+
+  GVIZ_PRODUCTIONS = [
+      # SQL clauses
+      ('gvizql',  GVIZQL,     [ GVIZQL, (Whitespace, Any), CLAUSE ] ),
+      ('',        GVIZQL,     [ CLAUSE ] ),
+      ('select',  CLAUSE,     [ _Select, SEQ ] ),
+      ('where',   CLAUSE,     [ _Where, BOOL_EXPR ] ),
+      ('groupby', CLAUSE,     [ _GroupBy, COL_SEQ ] ),
+      ('pivot',   CLAUSE,     [ _Pivot, COL_SEQ ] ),
+      ('orderby', CLAUSE,     [ _OrderBy, SEQ ] ),
+      ('limit',   CLAUSE,     [ _Limit, _Number ] ),
+      ('offset',  CLAUSE,     [ _Offset, _Number ] ),
+      ('label',   CLAUSE,     [ _Label, LABEL_SEQ ] ),
+      ('format',  CLAUSE,     [ _Format, LABEL_SEQ ] ),
+      ('options', CLAUSE,     [ _Options, COL_SEQ ] ),
+      ('colseq',  COL_SEQ,    [ COL_SEQ , _Comma , COLUMN ] ),
+      ('',        COL_SEQ,    [ COLUMN ] ),
+      ('column',  COLUMN,     [ _Var ] ),
+      ('lblseq',  LABEL_SEQ,  [ LABEL_SEQ, _Comma, LABEL_EXPR ] ),
+      ('',        LABEL_SEQ,  [ LABEL_EXPR ] ),
+      ('lblexpr', LABEL_EXPR, [ _Var, _Str ] ),
+
+      # Boolean expressions
+      ('boolexp', BOOL_EXPR,  [ BOOL_EXPR, _And, OR_EXPR ] ),
+      ('',        BOOL_EXPR,  [ OR_EXPR ] ),
+      ('orexp',   OR_EXPR,    [ OR_EXPR, _Or, BOOL_VALUE ] ),
+      ('',        OR_EXPR,    [ BOOL_VALUE ] ),
+      ('not',     BOOL_VALUE, [ _Not BOOL_VALUE ] ),
+      ('cmp',     BOOL_VALUE, [ ARITHMETIC_EXPR, _BoolOp, ARITHMETIC_EXPR ] ),
+      ('strcmp',  BOOL_VALUE, [ ARITHMETIC_EXPR, _BoolWordOp, ARITHMETIC_EXPR ] ),
+
+      # Arithmetic expressions
+      ('sum',     ARITHMETIC_EXPR,  [ ARITHMETIC_EXPR, _Plus, TERM ] ),
+      ('sub',     ARITHMETIC_EXPR,  [ ARITHMETIC_EXPR, _Minus, TERM ] ),
+      ('',        ARITHMETIC_EXPR,  [ TERM ] ),
+      ('mult',    TERM,             [ TERM, _Mult, FACTOR ] ),
+      ('',        TERM,             [ FACTOR ] ),
+      ('div',     FACTOR,           [ FACTOR, _Div, SIMPLE_EXPR ] ),
+      ('',        FACTOR,           [ SIMPLE_EXPR ] ),
+      ('par',     SIMPLE_EXPR,      [ _OpenP, ARITHMETIC_EXPR, _CloseP ] ),
+      ('',        SIMPLE_EXPR,      [ VALUE ] ),
+
+      # Function calls
+      ('bfunc',     VALUE, [ _Builtin, OpenP, CloseP ] ),
+      ('func',      VALUE, [ _Function, OpenP, CloseP ] ),
+      ('bfuncargs', VALUE, [ _Builtin, OpenP, SEQ, CloseP ] ),
+      ('funcargs',  VALUE, [ _Function, OpenP, SEQ, CloseP ] ),
+      ('seq',       SEQ, [ SEQ, _Comma, ARITHMETIC_EXPR ] ),
+      ('',          SEQ, [ ARITHMETIC_EXPR ] ),
+
+      # Literals and constants
+      ('number',    VALUE, [ _Number ] ),
+      ('var',       VALUE, [ _Var ] ),
+      ('str',       VALUE, [ _Str ] ),
+      ('date',      VALUE, [ _Date ] ),
+      ('const',     VALUE, [ _Const ] ),
+    ],
+
+  #  1.   VALUE -> Number
+  #  2.   VALUE -> Variable
+  #  3.   VALUE -> String
+  #  4.   VALUE -> Date
+  #  5.   VALUE -> Constant
+  #  6.   VALUE -> Builtin ( )
+  #  7.   VALUE -> Builtin ( SUITE )
+  #  8.   VALUE -> Function ( )
+  #  9.   VALUE -> Function ( SUITE )
+  #  10.  SUITE -> SUITE , ARITMETIC_EXPR
+  #  10a. SUITE -> ARITMETIC_EXPR
+  #  13.  ARITMETIC_EXPR -> ARITMETIC_EXPR + TERM
+  #  14.  ARITMETIC_EXPR -> ARITMETIC_EXPR - TERM
+  #  14a. ARITMETIC_EXPR -> TERM
+  #  15.  TERM -> TERM * FACTOR
+  #  15.a TERM -> FACTOR
+  #  16.  FACTOR -> FACTOR / SIMPLE_EXPR
+  #  16a. FACTOR -> SIMPLE_EXPR
+  #  17.  SIMPLE_EXPR -> ( ARITHMETIC_EXPR )
+  #  17a. SIMPLE_EXPR -> VALUE
+  #  18.  BOOL_VALUE -> ARITHMETIC_EXPR Operator.Comparison ARITHMETIC_EXPR
+  #  19.  BOOL_VALUE -> ARITHMETIC_EXPR Operator.Word.Comparison ARITHMETIC_EXPR
+  #  20.  BOOL_VALUE -> not BOOL_VALUE
+  #  21.  BOOL_EXPR -> BOOL_EXPR and OR_EXPR
+  #  21a. BOOL_EXPR -> OR_EXPR
+  #  22.  OR_EXPR -> OR_EXPR or BOOL_VALUE
+  #  22a. OR_EXPR -> BOOL_VALUE
 
 GVIZ_GRAMMAR_PRECEDENCE = {
     CloseP : {

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.