Olemis Lang avatar Olemis Lang committed fc0334a Merge

Merge 328eb84f04e7 6fbe10c0a48c : Incorporating enhanced GViz QL parsing strategy (i.e. operator precedence grammar)

Comments (0)

Files changed (14)

trac-dev/gviz/CHANGES

 
 - New! GViz providers list rendered on accessing `/gviz` path.
 
+- New! Support for parsing other (more complex) expressions in `select` 
+  clause (e.g. aggregate functions, -date- constants).
+
+- New! Support for parsing `WHERE` clause in detail
+
+- New! Support for parsing more complex expressions in `ORDER BY` clause 
+  (e.g. aggregate functions).
+
+- New! Constants accepted in `select` clause.
+
+- New! Support for parsing and evaluating scalar functions in `select` clause.
+
+- New! Support for parsing and evaluating expressions in `select` clause.
+
+- New! GViz QL grammar to include SQL clauses and refactor 
+  current parsing solution.
+
 - CSV and TSV encoders are implemented by using `csv` module in stdlib.
 
 - Include helper to convert CSV attachments to GViz API JSON format.

trac-dev/gviz/TODO

   those columns that appear in data tables only when some run-time 
   conditions are met e.g. ticket custom fields in 
   `ticket.GVizTicketReport`).
-
 - Execute reports defined using URLs pointing to saved custom queries.
-
 - Introduce support for GViz warnings (specially `data_truncated` 
   warnings).
-
 - Implement architecture in order to export data.
-
 - Export data to Google Spreadsheets.
 
 - Provide default border images for gadgets.
 
 - Provide alternative offline graphs based on JS library : 
   RGraph, Flot 
-

trac-dev/gviz/setup.py

   install_requires = [
       'setuptools>=0.6b1',
       'Trac>=0.11',
-      'TracXMLRPC<1.0.7',
+      'TracXMLRPC',
       'Pygments>=1.0',
   ],
   package_dir = dict([p, i[0]] for p, i in PKG_INFO.iteritems()),

trac-dev/gviz/tracgviz/aggregate.py

+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+# Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+r"""Aggregation functions defined by Google Visualization API (version 7.0)
+
+https://developers.google.com/chart/interactive/docs/querylanguage#aggregation_functions
+
+Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
+Licensed under the Apache License, Version 2.0 
+"""
+__author__ = 'Olemis Lang'
+__all__ = 'avg count max min sum'.split()
+
+def notimpl(*args, **kwds):
+  raise NotImplementedError('Aggregation not supported ... yet')
+
+avg = lambda *args, **kwds: notimpl(*args, **kwds)
+avg.return_type = 'number'
+
+count = lambda *args, **kwds: notimpl(*args, **kwds)
+count.return_type = 'number'
+
+max = lambda *args, **kwds: notimpl(*args, **kwds)
+
+min = lambda *args, **kwds: notimpl(*args, **kwds)
+
+sum = lambda *args, **kwds: notimpl(*args, **kwds)
+sum.return_type = 'number'
+
+

trac-dev/gviz/tracgviz/api.py

 from xmlrpclib import DateTime
 from datetime import datetime
 
-try:
-  from gvizql import prepare_ql_data
-except ImportError :
-  def prepare_ql_data(provider, tq, req, **params):
-    r"""Fall back to this implementation if `Pygments` import fails.
-    Please read `gvizql.prepare_ql_data` docstrings for further details.
-    """
-    if not tq:
-      sch = provider.get_data_schema.im_func.func_code
-      sch_args = (sch.co_argcount > 1) and (req,) or ()
-      data = provider.get_data(req, None, **params)
-      return (provider.get_data_schema(*sch_args), data)
-    else:
-      raise GVizUnsupportedQueryOp("Unable to process query : " \
-                                    "Pygments is not installed ?")
-
 class GVizException(Exception):
   r"""Base class for all exception types defined in this package"""
 
     pattern has been specified by the end-user.
     """
 
+class GVizRuntimeError(GVizException):
+    r"""An error detected at run-time when processing GViz request.
+    """
+
 def gviz_col(col_id, col_doc):
     r"""This function can be used to document the meaning of the 
     different columns in the table returned by GViz data sources as 
 # TODO : Cache the requests and optimize the call/response life cycle
 #            by using the `reqId` parameter.
 
+# Imports introducing circular reference with tracgviz.gvizql
+
+try:
+  from gvizql import prepare_ql_data
+except ImportError :
+  def prepare_ql_data(provider, tq, req, **params):
+    r"""Fall back to this implementation if `Pygments` import fails.
+    Please read `gvizql.prepare_ql_data` docstrings for further details.
+    """
+    if not tq:
+      sch = provider.get_data_schema.im_func.func_code
+      sch_args = (sch.co_argcount > 1) and (req,) or ()
+      data = provider.get_data(req, None, **params)
+      return (provider.get_data_schema(*sch_args), data)
+    else:
+      raise GVizUnsupportedQueryOp("Unable to process query : " \
+                                    "Pygments is not installed ?")
+

trac-dev/gviz/tracgviz/grammar.py

+#!/usr/bin/env python
+
+# Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+r"""Internal representation of operator precedence grammar used to parse
+Google Visualization API Query Language expressions.
+
+Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
+Licensed under the Apache License, Version 2.0 
+"""
+__author__ = 'Olemis Lang'
+
+__all__ = 'GVIZ_GRAMMAR_PRECEDENCE', 'GVIZ_GRAMMAR_PRODUCTIONS'
+
+from pygments.token import *
+
+from tracgviz.util.parsing import Any, EndMarker, NonTerminal, \
+    OperatorPrecedenceParser as Parser
+
+LessPrecedence = Parser.LessPrecedence
+SamePrecedence = Parser.SamePrecedence
+MorePrecedence = Parser.MorePrecedence
+
+# Grammar
+# =======
+
+GVIZ_QL_START_STATE = 'GVIZQL'
+
+GVIZ_QL_TERMINALS = [ 
+    (Operator.Word.Boolean, 'and'), 
+    (Operator.Word.Boolean, 'or'), 
+    (Operator.Word.Boolean, 'not'), 
+    (Number, Any), 
+    (Name.Variable, Any), 
+    (String, Any), 
+    (Literal.Date, Any), 
+    (Keyword.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'),
+    (Name.Other, '*'),
+    (Keyword.Reserved, 'from'),
+    (Keyword, 'asc'),
+    (Keyword, 'desc'),
+  ]
+
+_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, _Wildchar, _From, _Asc, _Desc = GVIZ_QL_TERMINALS
+
+# 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, BODY, ORDER_SEQ, \
+ORDER_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', 'BODY', 'ORDER_SEQ', 'ORDER_EXPR' )]
+
+def gvizql_grammar():
+  GVIZ_QL_PRODUCTIONS = [
+      # SQL clauses
+      ('gvizql',  GVIZQL,     [ BODY, (Whitespace, '\n') ] ),
+      ('body',    BODY,       [ BODY, (Whitespace, ' '), CLAUSE ] ),
+      ('',        BODY,       [ CLAUSE ] ),
+      ('select',  CLAUSE,     [ _Select, SEQ ] ),
+      ('from',    CLAUSE,     [ _From, COLUMN ] ),
+      ('selall',  CLAUSE,     [ _Select, _Wildchar ] ),
+      ('where',   CLAUSE,     [ _Where, BOOL_EXPR ] ),
+      ('groupby', CLAUSE,     [ _GroupBy, SEQ ] ),
+      ('pivot',   CLAUSE,     [ _Pivot, SEQ ] ),
+      ('orderby', CLAUSE,     [ _OrderBy, ORDER_SEQ ] ),
+      ('limit',   CLAUSE,     [ _Limit, _Number ] ),
+      ('offset',  CLAUSE,     [ _Offset, _Number ] ),
+      ('label',   CLAUSE,     [ _Label, LABEL_SEQ ] ),
+      ('format',  CLAUSE,     [ _Format, LABEL_SEQ ] ),
+      ('options', CLAUSE,     [ _Options, COL_SEQ ] ),
+
+      # Special sequences
+      ('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 ] ),
+      ('orderseq',  ORDER_SEQ,  [ ORDER_SEQ, _Comma, ORDER_EXPR ] ),
+      ('',          ORDER_SEQ,  [ ORDER_EXPR ] ),
+      ('',          ORDER_EXPR, [ ARITHMETIC_EXPR ] ),
+      ('orderasc',  ORDER_EXPR, [ ARITHMETIC_EXPR , _Asc ] ),
+      ('orderdsc',  ORDER_EXPR, [ ARITHMETIC_EXPR , _Desc ] ),
+
+      # 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 ] ),
+      ('boolpar', BOOL_VALUE, [ _OpenP, BOOL_EXPR, _CloseP ] ),
+
+      # 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, COLUMN, _CloseP ] ),
+      ('func',      VALUE, [ _Function, _OpenP, _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 ] ),
+    ]
+  return GVIZ_QL_PRODUCTIONS
+
+def pretty_gviz_grammar():
+  r"""Generate he readable representation of GViz QL grammar.
+
+  PS: shown below
+  """
+  # Generate grammar precedence and productions lookup table
+  from tracgviz.util.parsing import OperatorPrecedenceParser as Parser
+
+  productions = [(prod_id, nt[1], ps) for prod_id, nt, ps in gvizql_grammar()]
+  prec, prod = Parser.process_productions(*productions)
+
+  # Readable representation for mappings and dicts
+
+  from pprint import pprint
+  from StringIO import StringIO
+
+  sio = StringIO()
+  pprint(prec, stream=sio)
+  prec_text = sio.getvalue()
+
+  sio = StringIO()
+  pprint(prod, stream=sio)
+  prod_text = sio.getvalue()
+
+  sio = None
+
+  # Perform substitutions
+
+  def find_token(tkn):
+    for attr, value in globals().iteritems():
+      if value == tkn:
+        return attr
+
+  token_subs = dict([tkn, find_token(tkn)] for tkn in GVIZ_QL_TERMINALS)
+
+  for tkn, attrnm in token_subs.iteritems():
+    prec_text = prec_text.replace(str(tkn), attrnm)
+    prod_text = prod_text.replace(str(tkn), attrnm)
+
+  for tkn in ('Token.Grammar.Relationship.', 'Token.Grammar.'):
+    prec_text = prec_text.replace(tkn, '')
+    prod_text = prod_text.replace(tkn, '')
+
+  return prec_text, prod_text
+
+# Generated precedence and productions lookup tree (gen_readable_gviz_grammar)
+# These are made available to improve performance because of the fact that
+# no production processing is needed , they are ready to use 
+
+GVIZ_GRAMMAR_PRODUCTIONS = {(NonTerminal, Any): {_Format: {EndMarker: 'format'},
+        _From: {EndMarker: 'from'},
+        _GroupBy: {EndMarker: 'groupby'},
+        _Label: {EndMarker: 'label'},
+        _Options: {EndMarker: 'options'},
+        _OrderBy: {EndMarker: 'orderby'},
+        _Pivot: {EndMarker: 'pivot'},
+        _Select: {EndMarker: 'select'},
+        _Where: {EndMarker: 'where'},
+        _Mult: {(NonTerminal, Any): {EndMarker: 'mult'}},
+        _Plus: {(NonTerminal, Any): {EndMarker: 'sum'}},
+        _Minus: {(NonTerminal, Any): {EndMarker: 'sub'}},
+        _Div: {(NonTerminal, Any): {EndMarker: 'div'}},
+        _BoolOp: {(NonTerminal, Any): {EndMarker: 'cmp'}},
+        _And: {(NonTerminal, Any): {EndMarker: 'boolexp'}},
+        _Not: {EndMarker: 'not'},
+        _Or: {(NonTerminal, Any): {EndMarker: 'orexp'}},
+        _BoolWordOp: {(NonTerminal, Any): {EndMarker: 'strcmp'}},
+        _Comma: {(NonTerminal, Any): {EndMarker: 'seq'}},
+        (Token.Text.Whitespace, ' '): {(NonTerminal, Any): {EndMarker: 'body'}}},
+ _Asc: {(NonTerminal, Any): {EndMarker: 'orderasc'}},
+ _Desc: {(NonTerminal, Any): {EndMarker: 'orderdsc'}},
+ _Date: {EndMarker: 'date'},
+ _Number: {_Limit: {EndMarker: 'limit'},
+        _Offset: {EndMarker: 'offset'},
+        EndMarker: 'number'},
+ _Str: {_Var: {EndMarker: 'lblexpr'},
+        EndMarker: 'str'},
+ _Const: {EndMarker: 'const'},
+ _Wildchar: {_Select: {EndMarker: 'selall'}},
+ _Var: {EndMarker: 'var'},
+ _CloseP: {(NonTerminal, Any): {_OpenP: {_Builtin: {EndMarker: 'bfunc'},
+                _Function: {EndMarker: 'funcargs'},
+                EndMarker: 'par'}},
+        _OpenP: {_Function: {EndMarker: 'func'}}},
+ (Token.Text.Whitespace, '\n'): {(NonTerminal, Any): {EndMarker: 'gvizql'}}}
+
+
+GVIZ_GRAMMAR_PRECEDENCE = {((EndMarker, 'ARITHMETIC_EXPR'), _Date): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Number): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Str): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Const): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Function): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Mult): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Plus): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Minus): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _Div): LessPrecedence,
+ ((EndMarker, 'ARITHMETIC_EXPR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'BODY'), _Format): LessPrecedence,
+ ((EndMarker, 'BODY'), _From): LessPrecedence,
+ ((EndMarker, 'BODY'), _GroupBy): LessPrecedence,
+ ((EndMarker, 'BODY'), _Label): LessPrecedence,
+ ((EndMarker, 'BODY'), _Limit): LessPrecedence,
+ ((EndMarker, 'BODY'), _Offset): LessPrecedence,
+ ((EndMarker, 'BODY'), _Options): LessPrecedence,
+ ((EndMarker, 'BODY'), _OrderBy): LessPrecedence,
+ ((EndMarker, 'BODY'), _Pivot): LessPrecedence,
+ ((EndMarker, 'BODY'), _Select): LessPrecedence,
+ ((EndMarker, 'BODY'), _Where): LessPrecedence,
+ ((EndMarker, 'BODY'), (Token.Text.Whitespace, ' ')): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Date): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Number): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Str): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Const): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Function): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Mult): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Plus): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Minus): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Div): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _BoolOp): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _And): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Not): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _Or): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _BoolWordOp): LessPrecedence,
+ ((EndMarker, 'BOOL_EXPR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Date): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Number): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Str): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Builtin): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Const): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Function): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Var): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Mult): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Plus): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Minus): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Div): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _BoolOp): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _Not): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _BoolWordOp): LessPrecedence,
+ ((EndMarker, 'BOOL_VALUE'), _OpenP): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Format): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _From): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _GroupBy): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Label): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Limit): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Offset): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Options): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _OrderBy): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Pivot): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Select): LessPrecedence,
+ ((EndMarker, 'CLAUSE'), _Where): LessPrecedence,
+ ((EndMarker, 'COLSEQ'), _Var): LessPrecedence,
+ ((EndMarker, 'COLSEQ'), _Comma): LessPrecedence,
+ ((EndMarker, 'COLUMN'), _Var): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Date): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Number): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Str): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Const): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Function): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Var): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _Div): LessPrecedence,
+ ((EndMarker, 'FACTOR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Format): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _From): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _GroupBy): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Label): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Limit): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Offset): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Options): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _OrderBy): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Pivot): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Select): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), _Where): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), (Token.Text.Whitespace, '\n')): LessPrecedence,
+ ((EndMarker, 'GVIZQL'), (Token.Text.Whitespace, ' ')): LessPrecedence,
+ ((EndMarker, 'LABELSEQ'), _Var): LessPrecedence,
+ ((EndMarker, 'LABELSEQ'), _Comma): LessPrecedence,
+ ((EndMarker, 'LABEL_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Asc): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Desc): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Date): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Number): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Str): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Const): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Function): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Mult): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Plus): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Minus): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _Div): LessPrecedence,
+ ((EndMarker, 'ORDER_EXPR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Asc): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Desc): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Date): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Number): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Str): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Builtin): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Const): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Function): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Var): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Mult): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Plus): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Minus): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Div): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _OpenP): LessPrecedence,
+ ((EndMarker, 'ORDER_SEQ'), _Comma): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Date): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Number): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Str): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Const): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Function): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Mult): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Plus): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Minus): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Div): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _BoolOp): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Not): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _Or): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _BoolWordOp): LessPrecedence,
+ ((EndMarker, 'OR_EXPR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Date): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Number): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Str): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Builtin): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Const): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Function): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Var): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Mult): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Plus): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Minus): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Div): LessPrecedence,
+ ((EndMarker, 'SEQ'), _OpenP): LessPrecedence,
+ ((EndMarker, 'SEQ'), _Comma): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Date): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Number): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Str): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Builtin): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Const): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Function): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _Var): LessPrecedence,
+ ((EndMarker, 'SIMPLE_EXPR'), _OpenP): LessPrecedence,
+ ((EndMarker, 'TERM'), _Date): LessPrecedence,
+ ((EndMarker, 'TERM'), _Number): LessPrecedence,
+ ((EndMarker, 'TERM'), _Str): LessPrecedence,
+ ((EndMarker, 'TERM'), _Builtin): LessPrecedence,
+ ((EndMarker, 'TERM'), _Const): LessPrecedence,
+ ((EndMarker, 'TERM'), _Function): LessPrecedence,
+ ((EndMarker, 'TERM'), _Var): LessPrecedence,
+ ((EndMarker, 'TERM'), _Mult): LessPrecedence,
+ ((EndMarker, 'TERM'), _Div): LessPrecedence,
+ ((EndMarker, 'TERM'), _OpenP): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Date): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Number): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Str): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Builtin): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Const): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Function): LessPrecedence,
+ ((EndMarker, 'VALUE'), _Var): LessPrecedence,
+ (_Asc, (EndMarker, 'BODY')): MorePrecedence,
+ (_Asc, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Asc, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Asc, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Asc, _Comma): MorePrecedence,
+ (_Asc, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Asc, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Desc, (EndMarker, 'BODY')): MorePrecedence,
+ (_Desc, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Desc, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Desc, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Desc, _Comma): MorePrecedence,
+ (_Desc, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Desc, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Format, (EndMarker, 'BODY')): MorePrecedence,
+ (_Format, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Format, _Var): LessPrecedence,
+ (_Format, _Comma): LessPrecedence,
+ (_Format, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Format, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_From, (EndMarker, 'BODY')): MorePrecedence,
+ (_From, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_From, _Var): LessPrecedence,
+ (_From, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_From, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_GroupBy, (EndMarker, 'BODY')): MorePrecedence,
+ (_GroupBy, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_GroupBy, _Date): LessPrecedence,
+ (_GroupBy, _Number): LessPrecedence,
+ (_GroupBy, _Str): LessPrecedence,
+ (_GroupBy, _Builtin): LessPrecedence,
+ (_GroupBy, _Const): LessPrecedence,
+ (_GroupBy, _Function): LessPrecedence,
+ (_GroupBy, _Var): LessPrecedence,
+ (_GroupBy, _Mult): LessPrecedence,
+ (_GroupBy, _Plus): LessPrecedence,
+ (_GroupBy, _Minus): LessPrecedence,
+ (_GroupBy, _Div): LessPrecedence,
+ (_GroupBy, _OpenP): LessPrecedence,
+ (_GroupBy, _Comma): LessPrecedence,
+ (_GroupBy, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_GroupBy, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Label, (EndMarker, 'BODY')): MorePrecedence,
+ (_Label, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Label, _Var): LessPrecedence,
+ (_Label, _Comma): LessPrecedence,
+ (_Label, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Label, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Limit, _Number): SamePrecedence,
+ (_Offset, _Number): SamePrecedence,
+ (_Options, (EndMarker, 'BODY')): MorePrecedence,
+ (_Options, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Options, _Var): LessPrecedence,
+ (_Options, _Comma): LessPrecedence,
+ (_Options, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Options, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_OrderBy, (EndMarker, 'BODY')): MorePrecedence,
+ (_OrderBy, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_OrderBy, _Asc): LessPrecedence,
+ (_OrderBy, _Desc): LessPrecedence,
+ (_OrderBy, _Date): LessPrecedence,
+ (_OrderBy, _Number): LessPrecedence,
+ (_OrderBy, _Str): LessPrecedence,
+ (_OrderBy, _Builtin): LessPrecedence,
+ (_OrderBy, _Const): LessPrecedence,
+ (_OrderBy, _Function): LessPrecedence,
+ (_OrderBy, _Var): LessPrecedence,
+ (_OrderBy, _Mult): LessPrecedence,
+ (_OrderBy, _Plus): LessPrecedence,
+ (_OrderBy, _Minus): LessPrecedence,
+ (_OrderBy, _Div): LessPrecedence,
+ (_OrderBy, _OpenP): LessPrecedence,
+ (_OrderBy, _Comma): LessPrecedence,
+ (_OrderBy, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_OrderBy, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Pivot, (EndMarker, 'BODY')): MorePrecedence,
+ (_Pivot, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Pivot, _Date): LessPrecedence,
+ (_Pivot, _Number): LessPrecedence,
+ (_Pivot, _Str): LessPrecedence,
+ (_Pivot, _Builtin): LessPrecedence,
+ (_Pivot, _Const): LessPrecedence,
+ (_Pivot, _Function): LessPrecedence,
+ (_Pivot, _Var): LessPrecedence,
+ (_Pivot, _Mult): LessPrecedence,
+ (_Pivot, _Plus): LessPrecedence,
+ (_Pivot, _Minus): LessPrecedence,
+ (_Pivot, _Div): LessPrecedence,
+ (_Pivot, _OpenP): LessPrecedence,
+ (_Pivot, _Comma): LessPrecedence,
+ (_Pivot, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Pivot, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Select, (EndMarker, 'BODY')): MorePrecedence,
+ (_Select, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Select, _Date): LessPrecedence,
+ (_Select, _Number): LessPrecedence,
+ (_Select, _Str): LessPrecedence,
+ (_Select, _Builtin): LessPrecedence,
+ (_Select, _Const): LessPrecedence,
+ (_Select, _Function): LessPrecedence,
+ (_Select, _Wildchar): SamePrecedence,
+ (_Select, _Var): LessPrecedence,
+ (_Select, _Mult): LessPrecedence,
+ (_Select, _Plus): LessPrecedence,
+ (_Select, _Minus): LessPrecedence,
+ (_Select, _Div): LessPrecedence,
+ (_Select, _OpenP): LessPrecedence,
+ (_Select, _Comma): LessPrecedence,
+ (_Select, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Select, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Where, (EndMarker, 'BODY')): MorePrecedence,
+ (_Where, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Where, _Date): LessPrecedence,
+ (_Where, _Number): LessPrecedence,
+ (_Where, _Str): LessPrecedence,
+ (_Where, _Builtin): LessPrecedence,
+ (_Where, _Const): LessPrecedence,
+ (_Where, _Function): LessPrecedence,
+ (_Where, _Var): LessPrecedence,
+ (_Where, _Mult): LessPrecedence,
+ (_Where, _Plus): LessPrecedence,
+ (_Where, _Minus): LessPrecedence,
+ (_Where, _Div): LessPrecedence,
+ (_Where, _BoolOp): LessPrecedence,
+ (_Where, _And): LessPrecedence,
+ (_Where, _Not): LessPrecedence,
+ (_Where, _Or): LessPrecedence,
+ (_Where, _BoolWordOp): LessPrecedence,
+ (_Where, _OpenP): LessPrecedence,
+ (_Where, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Where, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Date, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Date, (EndMarker, 'BODY')): MorePrecedence,
+ (_Date, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Date, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Date, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Date, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Date, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Date, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Date, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Date, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Date, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_Date, (EndMarker, 'TERM')): MorePrecedence,
+ (_Date, (EndMarker, 'VALUE')): MorePrecedence,
+ (_Date, _Asc): MorePrecedence,
+ (_Date, _Desc): MorePrecedence,
+ (_Date, _Mult): MorePrecedence,
+ (_Date, _Plus): MorePrecedence,
+ (_Date, _Minus): MorePrecedence,
+ (_Date, _Div): MorePrecedence,
+ (_Date, _BoolOp): MorePrecedence,
+ (_Date, _And): MorePrecedence,
+ (_Date, _Or): MorePrecedence,
+ (_Date, _BoolWordOp): MorePrecedence,
+ (_Date, _CloseP): MorePrecedence,
+ (_Date, _Comma): MorePrecedence,
+ (_Date, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Date, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Number, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Number, (EndMarker, 'BODY')): MorePrecedence,
+ (_Number, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Number, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Number, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Number, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Number, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Number, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Number, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Number, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Number, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_Number, (EndMarker, 'TERM')): MorePrecedence,
+ (_Number, (EndMarker, 'VALUE')): MorePrecedence,
+ (_Number, _Asc): MorePrecedence,
+ (_Number, _Desc): MorePrecedence,
+ (_Number, _Mult): MorePrecedence,
+ (_Number, _Plus): MorePrecedence,
+ (_Number, _Minus): MorePrecedence,
+ (_Number, _Div): MorePrecedence,
+ (_Number, _BoolOp): MorePrecedence,
+ (_Number, _And): MorePrecedence,
+ (_Number, _Or): MorePrecedence,
+ (_Number, _BoolWordOp): MorePrecedence,
+ (_Number, _CloseP): MorePrecedence,
+ (_Number, _Comma): MorePrecedence,
+ (_Number, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Number, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Str, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'BODY')): MorePrecedence,
+ (_Str, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Str, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Str, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Str, (EndMarker, 'LABELSEQ')): MorePrecedence,
+ (_Str, (EndMarker, 'LABEL_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Str, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Str, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_Str, (EndMarker, 'TERM')): MorePrecedence,
+ (_Str, (EndMarker, 'VALUE')): MorePrecedence,
+ (_Str, _Asc): MorePrecedence,
+ (_Str, _Desc): MorePrecedence,
+ (_Str, _Mult): MorePrecedence,
+ (_Str, _Plus): MorePrecedence,
+ (_Str, _Minus): MorePrecedence,
+ (_Str, _Div): MorePrecedence,
+ (_Str, _BoolOp): MorePrecedence,
+ (_Str, _And): MorePrecedence,
+ (_Str, _Or): MorePrecedence,
+ (_Str, _BoolWordOp): MorePrecedence,
+ (_Str, _CloseP): MorePrecedence,
+ (_Str, _Comma): MorePrecedence,
+ (_Str, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Str, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Builtin, _OpenP): SamePrecedence,
+ (_Const, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Const, (EndMarker, 'BODY')): MorePrecedence,
+ (_Const, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Const, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Const, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Const, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Const, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Const, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Const, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Const, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Const, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_Const, (EndMarker, 'TERM')): MorePrecedence,
+ (_Const, (EndMarker, 'VALUE')): MorePrecedence,
+ (_Const, _Asc): MorePrecedence,
+ (_Const, _Desc): MorePrecedence,
+ (_Const, _Mult): MorePrecedence,
+ (_Const, _Plus): MorePrecedence,
+ (_Const, _Minus): MorePrecedence,
+ (_Const, _Div): MorePrecedence,
+ (_Const, _BoolOp): MorePrecedence,
+ (_Const, _And): MorePrecedence,
+ (_Const, _Or): MorePrecedence,
+ (_Const, _BoolWordOp): MorePrecedence,
+ (_Const, _CloseP): MorePrecedence,
+ (_Const, _Comma): MorePrecedence,
+ (_Const, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Const, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Function, _OpenP): SamePrecedence,
+ (_Wildchar, (EndMarker, 'BODY')): MorePrecedence,
+ (_Wildchar, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Wildchar, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Wildchar, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Var, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Var, (EndMarker, 'BODY')): MorePrecedence,
+ (_Var, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Var, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Var, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Var, (EndMarker, 'COLSEQ')): MorePrecedence,
+ (_Var, (EndMarker, 'COLUMN')): MorePrecedence,
+ (_Var, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Var, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Var, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Var, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Var, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Var, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_Var, (EndMarker, 'TERM')): MorePrecedence,
+ (_Var, (EndMarker, 'VALUE')): MorePrecedence,
+ (_Var, _Asc): MorePrecedence,
+ (_Var, _Desc): MorePrecedence,
+ (_Var, _Str): SamePrecedence,
+ (_Var, _Mult): MorePrecedence,
+ (_Var, _Plus): MorePrecedence,
+ (_Var, _Minus): MorePrecedence,
+ (_Var, _Div): MorePrecedence,
+ (_Var, _BoolOp): MorePrecedence,
+ (_Var, _And): MorePrecedence,
+ (_Var, _Or): MorePrecedence,
+ (_Var, _BoolWordOp): MorePrecedence,
+ (_Var, _CloseP): MorePrecedence,
+ (_Var, _Comma): MorePrecedence,
+ (_Var, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Var, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Mult, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Mult, (EndMarker, 'BODY')): MorePrecedence,
+ (_Mult, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Mult, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Mult, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Mult, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Mult, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Mult, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Mult, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Mult, (EndMarker, 'TERM')): MorePrecedence,
+ (_Mult, _Asc): MorePrecedence,
+ (_Mult, _Desc): MorePrecedence,
+ (_Mult, _Date): LessPrecedence,
+ (_Mult, _Number): LessPrecedence,
+ (_Mult, _Str): LessPrecedence,
+ (_Mult, _Builtin): LessPrecedence,
+ (_Mult, _Const): LessPrecedence,
+ (_Mult, _Function): LessPrecedence,
+ (_Mult, _Var): LessPrecedence,
+ (_Mult, _Mult): MorePrecedence,
+ (_Mult, _Plus): MorePrecedence,
+ (_Mult, _Minus): MorePrecedence,
+ (_Mult, _Div): LessPrecedence,
+ (_Mult, _BoolOp): MorePrecedence,
+ (_Mult, _And): MorePrecedence,
+ (_Mult, _Or): MorePrecedence,
+ (_Mult, _BoolWordOp): MorePrecedence,
+ (_Mult, _OpenP): LessPrecedence,
+ (_Mult, _CloseP): MorePrecedence,
+ (_Mult, _Comma): MorePrecedence,
+ (_Mult, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Mult, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Plus, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Plus, (EndMarker, 'BODY')): MorePrecedence,
+ (_Plus, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Plus, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Plus, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Plus, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Plus, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Plus, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Plus, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Plus, _Asc): MorePrecedence,
+ (_Plus, _Desc): MorePrecedence,
+ (_Plus, _Date): LessPrecedence,
+ (_Plus, _Number): LessPrecedence,
+ (_Plus, _Str): LessPrecedence,
+ (_Plus, _Builtin): LessPrecedence,
+ (_Plus, _Const): LessPrecedence,
+ (_Plus, _Function): LessPrecedence,
+ (_Plus, _Var): LessPrecedence,
+ (_Plus, _Mult): LessPrecedence,
+ (_Plus, _Plus): MorePrecedence,
+ (_Plus, _Minus): MorePrecedence,
+ (_Plus, _Div): LessPrecedence,
+ (_Plus, _BoolOp): MorePrecedence,
+ (_Plus, _And): MorePrecedence,
+ (_Plus, _Or): MorePrecedence,
+ (_Plus, _BoolWordOp): MorePrecedence,
+ (_Plus, _OpenP): LessPrecedence,
+ (_Plus, _CloseP): MorePrecedence,
+ (_Plus, _Comma): MorePrecedence,
+ (_Plus, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Plus, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Minus, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Minus, (EndMarker, 'BODY')): MorePrecedence,
+ (_Minus, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Minus, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Minus, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Minus, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Minus, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Minus, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Minus, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Minus, _Asc): MorePrecedence,
+ (_Minus, _Desc): MorePrecedence,
+ (_Minus, _Date): LessPrecedence,
+ (_Minus, _Number): LessPrecedence,
+ (_Minus, _Str): LessPrecedence,
+ (_Minus, _Builtin): LessPrecedence,
+ (_Minus, _Const): LessPrecedence,
+ (_Minus, _Function): LessPrecedence,
+ (_Minus, _Var): LessPrecedence,
+ (_Minus, _Mult): LessPrecedence,
+ (_Minus, _Plus): MorePrecedence,
+ (_Minus, _Minus): MorePrecedence,
+ (_Minus, _Div): LessPrecedence,
+ (_Minus, _BoolOp): MorePrecedence,
+ (_Minus, _And): MorePrecedence,
+ (_Minus, _Or): MorePrecedence,
+ (_Minus, _BoolWordOp): MorePrecedence,
+ (_Minus, _OpenP): LessPrecedence,
+ (_Minus, _CloseP): MorePrecedence,
+ (_Minus, _Comma): MorePrecedence,
+ (_Minus, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Minus, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Div, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_Div, (EndMarker, 'BODY')): MorePrecedence,
+ (_Div, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Div, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Div, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Div, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_Div, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_Div, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Div, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Div, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Div, (EndMarker, 'TERM')): MorePrecedence,
+ (_Div, _Asc): MorePrecedence,
+ (_Div, _Desc): MorePrecedence,
+ (_Div, _Date): LessPrecedence,
+ (_Div, _Number): LessPrecedence,
+ (_Div, _Str): LessPrecedence,
+ (_Div, _Builtin): LessPrecedence,
+ (_Div, _Const): LessPrecedence,
+ (_Div, _Function): LessPrecedence,
+ (_Div, _Var): LessPrecedence,
+ (_Div, _Mult): MorePrecedence,
+ (_Div, _Plus): MorePrecedence,
+ (_Div, _Minus): MorePrecedence,
+ (_Div, _Div): MorePrecedence,
+ (_Div, _BoolOp): MorePrecedence,
+ (_Div, _And): MorePrecedence,
+ (_Div, _Or): MorePrecedence,
+ (_Div, _BoolWordOp): MorePrecedence,
+ (_Div, _OpenP): LessPrecedence,
+ (_Div, _CloseP): MorePrecedence,
+ (_Div, _Comma): MorePrecedence,
+ (_Div, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Div, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_BoolOp, (EndMarker, 'BODY')): MorePrecedence,
+ (_BoolOp, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_BoolOp, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_BoolOp, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_BoolOp, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_BoolOp, _Date): LessPrecedence,
+ (_BoolOp, _Number): LessPrecedence,
+ (_BoolOp, _Str): LessPrecedence,
+ (_BoolOp, _Builtin): LessPrecedence,
+ (_BoolOp, _Const): LessPrecedence,
+ (_BoolOp, _Function): LessPrecedence,
+ (_BoolOp, _Var): LessPrecedence,
+ (_BoolOp, _Mult): LessPrecedence,
+ (_BoolOp, _Plus): LessPrecedence,
+ (_BoolOp, _Minus): LessPrecedence,
+ (_BoolOp, _Div): LessPrecedence,
+ (_BoolOp, _And): MorePrecedence,
+ (_BoolOp, _Or): MorePrecedence,
+ (_BoolOp, _OpenP): LessPrecedence,
+ (_BoolOp, _CloseP): MorePrecedence,
+ (_BoolOp, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_BoolOp, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_And, (EndMarker, 'BODY')): MorePrecedence,
+ (_And, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_And, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_And, _Date): LessPrecedence,
+ (_And, _Number): LessPrecedence,
+ (_And, _Str): LessPrecedence,
+ (_And, _Builtin): LessPrecedence,
+ (_And, _Const): LessPrecedence,
+ (_And, _Function): LessPrecedence,
+ (_And, _Var): LessPrecedence,
+ (_And, _Mult): LessPrecedence,
+ (_And, _Plus): LessPrecedence,
+ (_And, _Minus): LessPrecedence,
+ (_And, _Div): LessPrecedence,
+ (_And, _BoolOp): LessPrecedence,
+ (_And, _And): MorePrecedence,
+ (_And, _Not): LessPrecedence,
+ (_And, _Or): LessPrecedence,
+ (_And, _BoolWordOp): LessPrecedence,
+ (_And, _OpenP): LessPrecedence,
+ (_And, _CloseP): MorePrecedence,
+ (_And, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_And, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Not, (EndMarker, 'BODY')): MorePrecedence,
+ (_Not, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Not, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_Not, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Not, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Not, _Date): LessPrecedence,
+ (_Not, _Number): LessPrecedence,
+ (_Not, _Str): LessPrecedence,
+ (_Not, _Builtin): LessPrecedence,
+ (_Not, _Const): LessPrecedence,
+ (_Not, _Function): LessPrecedence,
+ (_Not, _Var): LessPrecedence,
+ (_Not, _Mult): LessPrecedence,
+ (_Not, _Plus): LessPrecedence,
+ (_Not, _Minus): LessPrecedence,
+ (_Not, _Div): LessPrecedence,
+ (_Not, _BoolOp): LessPrecedence,
+ (_Not, _And): MorePrecedence,
+ (_Not, _Not): LessPrecedence,
+ (_Not, _Or): MorePrecedence,
+ (_Not, _BoolWordOp): LessPrecedence,
+ (_Not, _OpenP): LessPrecedence,
+ (_Not, _CloseP): MorePrecedence,
+ (_Not, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Not, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Or, (EndMarker, 'BODY')): MorePrecedence,
+ (_Or, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_Or, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Or, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_Or, _Date): LessPrecedence,
+ (_Or, _Number): LessPrecedence,
+ (_Or, _Str): LessPrecedence,
+ (_Or, _Builtin): LessPrecedence,
+ (_Or, _Const): LessPrecedence,
+ (_Or, _Function): LessPrecedence,
+ (_Or, _Var): LessPrecedence,
+ (_Or, _Mult): LessPrecedence,
+ (_Or, _Plus): LessPrecedence,
+ (_Or, _Minus): LessPrecedence,
+ (_Or, _Div): LessPrecedence,
+ (_Or, _BoolOp): LessPrecedence,
+ (_Or, _And): MorePrecedence,
+ (_Or, _Not): LessPrecedence,
+ (_Or, _Or): MorePrecedence,
+ (_Or, _BoolWordOp): LessPrecedence,
+ (_Or, _OpenP): LessPrecedence,
+ (_Or, _CloseP): MorePrecedence,
+ (_Or, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Or, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_BoolWordOp, (EndMarker, 'BODY')): MorePrecedence,
+ (_BoolWordOp, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_BoolWordOp, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_BoolWordOp, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_BoolWordOp, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_BoolWordOp, _Date): LessPrecedence,
+ (_BoolWordOp, _Number): LessPrecedence,
+ (_BoolWordOp, _Str): LessPrecedence,
+ (_BoolWordOp, _Builtin): LessPrecedence,
+ (_BoolWordOp, _Const): LessPrecedence,
+ (_BoolWordOp, _Function): LessPrecedence,
+ (_BoolWordOp, _Var): LessPrecedence,
+ (_BoolWordOp, _Mult): LessPrecedence,
+ (_BoolWordOp, _Plus): LessPrecedence,
+ (_BoolWordOp, _Minus): LessPrecedence,
+ (_BoolWordOp, _Div): LessPrecedence,
+ (_BoolWordOp, _And): MorePrecedence,
+ (_BoolWordOp, _Or): MorePrecedence,
+ (_BoolWordOp, _OpenP): LessPrecedence,
+ (_BoolWordOp, _CloseP): MorePrecedence,
+ (_BoolWordOp, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_BoolWordOp, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_OpenP, _Date): LessPrecedence,
+ (_OpenP, _Number): LessPrecedence,
+ (_OpenP, _Str): LessPrecedence,
+ (_OpenP, _Builtin): LessPrecedence,
+ (_OpenP, _Const): LessPrecedence,
+ (_OpenP, _Function): LessPrecedence,
+ (_OpenP, _Var): LessPrecedence,
+ (_OpenP, _Mult): LessPrecedence,
+ (_OpenP, _Plus): LessPrecedence,
+ (_OpenP, _Minus): LessPrecedence,
+ (_OpenP, _Div): LessPrecedence,
+ (_OpenP, _BoolOp): LessPrecedence,
+ (_OpenP, _And): LessPrecedence,
+ (_OpenP, _Not): LessPrecedence,
+ (_OpenP, _Or): LessPrecedence,
+ (_OpenP, _BoolWordOp): LessPrecedence,
+ (_OpenP, _OpenP): LessPrecedence,
+ (_OpenP, _CloseP): SamePrecedence,
+ (_OpenP, _Comma): LessPrecedence,
+ (_CloseP, (EndMarker, 'ARITHMETIC_EXPR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'BODY')): MorePrecedence,
+ (_CloseP, (EndMarker, 'BOOL_EXPR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'BOOL_VALUE')): MorePrecedence,
+ (_CloseP, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_CloseP, (EndMarker, 'FACTOR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'ORDER_EXPR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_CloseP, (EndMarker, 'OR_EXPR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'SEQ')): MorePrecedence,
+ (_CloseP, (EndMarker, 'SIMPLE_EXPR')): MorePrecedence,
+ (_CloseP, (EndMarker, 'TERM')): MorePrecedence,
+ (_CloseP, (EndMarker, 'VALUE')): MorePrecedence,
+ (_CloseP, _Asc): MorePrecedence,
+ (_CloseP, _Desc): MorePrecedence,
+ (_CloseP, _Mult): MorePrecedence,
+ (_CloseP, _Plus): MorePrecedence,
+ (_CloseP, _Minus): MorePrecedence,
+ (_CloseP, _Div): MorePrecedence,
+ (_CloseP, _BoolOp): MorePrecedence,
+ (_CloseP, _And): MorePrecedence,
+ (_CloseP, _Or): MorePrecedence,
+ (_CloseP, _BoolWordOp): MorePrecedence,
+ (_CloseP, _CloseP): MorePrecedence,
+ (_CloseP, _Comma): MorePrecedence,
+ (_CloseP, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_CloseP, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ (_Comma, (EndMarker, 'BODY')): MorePrecedence,
+ (_Comma, (EndMarker, 'CLAUSE')): MorePrecedence,
+ (_Comma, (EndMarker, 'COLSEQ')): MorePrecedence,
+ (_Comma, (EndMarker, 'LABELSEQ')): MorePrecedence,
+ (_Comma, (EndMarker, 'ORDER_SEQ')): MorePrecedence,
+ (_Comma, (EndMarker, 'SEQ')): MorePrecedence,
+ (_Comma, _Asc): LessPrecedence,
+ (_Comma, _Desc): LessPrecedence,
+ (_Comma, _Date): LessPrecedence,
+ (_Comma, _Number): LessPrecedence,
+ (_Comma, _Str): LessPrecedence,
+ (_Comma, _Builtin): LessPrecedence,
+ (_Comma, _Const): LessPrecedence,
+ (_Comma, _Function): LessPrecedence,
+ (_Comma, _Var): LessPrecedence,
+ (_Comma, _Mult): LessPrecedence,
+ (_Comma, _Plus): LessPrecedence,
+ (_Comma, _Minus): LessPrecedence,
+ (_Comma, _Div): LessPrecedence,
+ (_Comma, _OpenP): LessPrecedence,
+ (_Comma, _CloseP): MorePrecedence,
+ (_Comma, _Comma): MorePrecedence,
+ (_Comma, (Token.Text.Whitespace, '\n')): MorePrecedence,
+ (_Comma, (Token.Text.Whitespace, ' ')): MorePrecedence,
+ ((Token.Text.Whitespace, '\n'), (EndMarker, 'GVIZQL')): MorePrecedence,
+ ((Token.Text.Whitespace, ' '), (EndMarker, 'BODY')): MorePrecedence,
+ ((Token.Text.Whitespace, ' '), _Format): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _From): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _GroupBy): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Label): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Limit): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Offset): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Options): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _OrderBy): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Pivot): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Select): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), _Where): LessPrecedence,
+ ((Token.Text.Whitespace, ' '), (Token.Text.Whitespace, '\n')): MorePrecedence,
+ ((Token.Text.Whitespace, ' '), (Token.Text.Whitespace, ' ')): MorePrecedence}

trac-dev/gviz/tracgviz/gvizql.py

           'defaultParser'
 __metaclass__ = type
 
+from ast import literal_eval
+from datetime import datetime
 from itertools import islice, izip
+import logging
+import operator
 from pygments.lexer import RegexLexer
 from pygments.filter import Filter
 from pygments.token import *
 from re import compile
 from weakref import proxy
 
+from tracgviz.util.parsing import OperatorPrecedenceParser,  \
+    InvalidParserConfiguration
+
 #------------------------------------------------------
 #   GVizQL clause handlers 
 #------------------------------------------------------
 class GVizQLClauseType(type):
   r"""Keep track of all GVizQL clause handlers installed in the 
   system, syntax order ...
-  
+
   >>> ','.join(ct.get_props('keyw') for ct in GVizQLClauseType.iterparse())
   'select,from,where,group by,pivot,order by,limit,offset,label,format,options'
-  
+
   ... as well as evaluation order.
-  
+
   >>> ','.join(ct.get_props('keyw') for ct in GVizQLClauseType.itereval())
   'from,group by,pivot,where,order by,offset,limit,select,format,options,label'
   """
   SYNTAX_ORDER = list()
   EVAL_ORDER = list()
   PROPS = ('idx_syntax', 'idx_eval', 'keyw')
-  
+
   def __new__(cls, name, bases, suite):
     r"""Keep track of all GVizQL clause handlers installed in the 
     system, as well as evaluation order.
       del suite['__abstract__']
     except KeyError:
       abstract = False
-    
+
     @classmethod
     def get_props(cls, propnm):
       try:
       except KeyError, exc:
         raise ValueError('Unsupported property %s', exc.message)
     suite['get_props'] = get_props
-    
+
     self = super(GVizQLClauseType, cls).__new__(cls, name, bases, suite)
     if not abstract:
       cnm = self.get_props('keyw')
       GVizQLClauseType.EVAL_ORDER.sort(None, \
                                     lambda x: x.get_props('idx_eval'))
     return self
-  
+
   @staticmethod
   def itereval():
     r"""Iterate over GVizQL clause handlers following evaluation order.
     """
     return iter(GVizQLClauseType.EVAL_ORDER)
-  
+
   @staticmethod
   def iterparse():
     r"""Iterate over GVizQL clause handlers following syntax order.
     """
     return iter(GVizQLClauseType.SYNTAX_ORDER)
-  
+
   @staticmethod
   def clauses():
     r"""Retrieved all the keywords identifying different clauses 
   r"""Objects used to define syntax and retrieve items inside a 
   clause. It's also responsible of performing the transformations 
   dictated by this clause on a data set.
-  
+
   Instances of this class have to override the following fields:
     - `_PROPS` :      a static dictionary containing the following keys
+      * `idx_eval`      a number indicating the relative order of 
+                        this clause at evaluation time.
       * `idx_syntax`    a number indicating the relative syntantic 
                         order of this clause.
-      * `idx_eval`      a number indicating the relative order of 
-                        this clause at evaluation time.
       * `keyw`          the keyword introducing (i.e. identifying) 
                         this clause.
     - `transform` :   override this method in order to apply the 
   """
   __metaclass__ = GVizQLClauseType
   __abstract__ = True
-  
-  ERR_MSGS = {
-      'PARSING' : "%(clause)s clause is not supported yet.",
-      'EVAL' :    "Unable to evaluate %(clause)s clause. " \
-                  "Either the whole clause or an specific feature " \
-                  "is not supported yet."
-    }
-  
-  def unsupported(self, at='PARSING', **vals):
+
+  ERR_MSG = "Unable to evaluate %(clause)s clause. " \
+      "Either the whole clause or an specific feature " \
+      "is not supported yet."
+
+  def unsupported(self, **vals):
     r"""Indicate that this clause is not supported yet.
     """
     vals['clause'] = self.get_props('keyw').upper()
-    msg = self.ERR_MSGS.get(at, '') % vals
+    msg = self.ERR_MSG % vals
     raise GVizUnsupportedQueryOp(msg)
-  
+
   def transform(self, schema, data):
     r"""Transform the result set as dictated by the clause included 
     in the GViz QL expression provided by the client. This 
     transformation *SHOULD* be performed by using iterators.
-    
+
     Note: Default behavior is to indicate that the clause is not 
     supported.
     """
-    self.unsupported(at='EVAL')
+    self.unsupported()
+
+  # Internal methods
+
+  @staticmethod
+  def _column_accessor(schema):
+    r"""Functor returning a callable providing access to the values in 
+    a given row of the result set by column name.
+    """
+    schcols = dict([col[0], i] for i, col in enumerate(schema))
+
+    def get_col_value(row, colnm):
+      try:
+        return row[schcols[colnm]]
+      except KeyError:
+        raise GVizRuntimeError("Unknown column " + colnm + ".")
+
+    return get_col_value
+
+  @staticmethod
+  def _schema_accessor(schema):
+    r"""Functor returning a callable providing access to columns schema 
+    by column name.
+    """
+    schcols = dict([col[0], i] for i, col in enumerate(schema))
+
+    def get_col_schema(colnm):
+      try:
+        return schema[schcols[colnm]]
+      except KeyError:
+        raise GVizRuntimeError("Unknown column " + colnm + ".")
+
+    return get_col_schema
+
+  @staticmethod
+  def _resolve_schema(expr, get_col_schema):
+    r"""Determine the new schema obtained after transforming base result set
+    by appying an arithmetic or boolean expression.
+    """
+    return expr['schema'](get_col_schema) if expr['is_schema_callable'] \
+        else expr['schema']
+
+  @staticmethod
+  def _eval_expr(row, expr, get_col_value):
+    r"""Evaluate an arithmetic or boolean expression against a row
+    in the data set. Accessor function might be needed to access row values
+    by column name.
+    """
+    return expr['eval'](row, get_col_value) if expr['is_eval_callable'] \
+        else expr['eval']
 
 class GVizSelectClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 0, 'idx_eval': 7, 'keyw' : 'select'}
   KEYWORDS = ('select',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize SELECT clause handler with the sequence of expressions
+    specified in input GViz QL statement.
     """
-    tkn, val = ctx.stream.next()
-    if tkn is Name.Other and val == '*':
-      self.cols = None
-      tkn, val = ctx.stream.next()
-    elif tkn is Name.Variable:
-      if val.startswith('`'):
-        val = val[1:-1]
-      self.cols = cols = [val]
-      for tkn, val in ctx.stream :
-        if tkn is Punctuation and val == ',' :
-          tkn, val = ctx.stream.next()
-          if tkn is Name.Variable :     # FIXME: Just column names so far
-            if val.startswith('`'):
-              val = val[1:-1]
-            cols.append(val)
-          elif tkn in (Name.Function, Name.Builtin):
-            raise GVizUnsupportedQueryOp("Scalar and aggregate functions " \
-                                          "not supported yet : token %s" % \
-                                          (val,))
-          else:
-            raise GVizInvalidQuery("Syntax error or unsupported " \
-                                    "feature. Unexpected token %s." \
-                                                            % (val,))
-        else:
-          break
-    elif tkn in (Name.Function, Name.Builtin):
-      raise GVizUnsupportedQueryOp("Scalar and aggregate functions " \
-                                    "not supported yet : token %s" % \
-                                    (val,))
-    else:
-      if tkn is Whitespace and val == '\n' :
-        val = '<EOL>'
-      raise GVizInvalidQuery("Syntax error or unsupported " \
-                              "feature. Unexpected token %s." % (val,))
-  
+    if seq == '*':
+      seq = None
+    elif not isinstance(seq, Sequence):
+      seq = Sequence([seq])
+    self.cols_mapping = seq
+    logging.debug("Select list %s", seq)
+    self.cols = [self._resolve_schema(c, lambda colnm: (colnm, None))[0] 
+        for c in self.cols_mapping ] if seq is not None else None
+
   def transform(self, schema, data):
-    r"""Arrange values considering the given column order.
+    r"""Arrange and transform values considering the given expressions list.
     """
-    cols = self.cols
-    if cols is None:
+    cols = self.cols_mapping
+    if not cols:
       return schema, data
     else:
-      idxmap = [None] * len(cols)
-      schcols = dict([col[0], i] for i, col in enumerate(schema))
-      for i, colnm in enumerate(cols):
-        try:
-          idxmap[i] = schcols[colnm]
-        except KeyError, exc:
-          raise GVizInvalidQuery("Unable to evaluate SELECT clause. " \
-                                  "Unknown column %s." % (exc.message,))
-      new_schema = [schema[i] for i in idxmap]
-      new_data = ([row[i] for i in idxmap] for row in data)
+      get_col_value = self._column_accessor(schema)
+      get_col_schema = self._schema_accessor(schema)
+      new_schema = [self._resolve_schema(c, get_col_schema) \
+          for c in self.cols_mapping]
+      new_data = ( [self._eval_expr(row, c, get_col_value) \
+              for c in self.cols_mapping] for row in data )
       return new_schema, new_data
 
 class GVizFromClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 1, 'idx_eval': 0, 'keyw' : 'from'}
   KEYWORDS = ('from',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in FROM clause.
+
+  def __init__(self, name):
+    r"""Always fail with deprecation message.
+
+    FROM clause is deprecated and has been removed from the language.
     """
-    tkn, val = ctx.stream.next()
-    if tkn is Name.Variable :
-      if val.startswith('`'):
-        val = val[1:-1]
-      self.basetable = val
-      ctx.stream.next()
-    else :
-      raise GVizInvalidQuery("Syntax error: Table name expected but" \
-                              " %s found." % (val,))
+    self.basetable = name['schema'](lambda colnm: (colnm, None))[0]
+
   def transform(self, schema, data):
     r"""Notify that base table has not been processed by data source. 
     This is made this way since it may hide a bug in the underlying 
     data source implementation.
-    
-    FROM clause is irrevelevant for transformations. This clause is 
-    available so that the underlying data sources be able to handle 
-    it. This feature will be supported in upcoming versions.
+
+    FROM clause is deprecated and has been removed from the language.
     """
-    raise GVizInvalidQuery("Unable to evaluate FROM clause. " \
-                              "Data source doesn't contain base " \
-                              "table %s." % (self.basetable,))
+    raise GVizInvalidQuery("The from clause has been eliminated" \
+        " from the language.")
 
 class GVizWhereClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 2, 'idx_eval': 3, 'keyw' : 'where'}
   KEYWORDS = ('where',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in WHERE clause.
+
+  def __init__(self, expr):
+    r"""Initialize clause instance with a boolean expression evaluated
+    in order to filter rows in the result set.
     """
-    self.unsupported()
+    if expr['is_schema_callable'] or expr['schema'][1] != 'boolean':
+      raise GVizInvalidQuery("Syntax error: Boolean expression expected " \
+          "in where clause." + 
+          (" Got %s" % (expr['schema'][1])) if not expr['is_schema_callable']
+              else '')
+    self.expr = expr
+    self.filter = self._resolve_schema(expr, lambda colnm: (colnm, None))[0]
+
+  def transform(self, schema, data):
+    r"""Filter rows that do not satisfy target predicate.
+    """
+    get_col_value = self._column_accessor(schema)
+    new_data = ( row for row in data \
+        if bool(self._eval_expr(row, self.expr, get_col_value)) )
+    return (schema, new_data)
 
 class GVizGroupByClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 3, 'idx_eval': 1, 'keyw' : 'group by'}
   KEYWORDS = ('group', 'by')
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in GROUP BY clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with a sequence of expressions specifying
+    how to group multiple rows in the base data set.
+    """
+    if not isinstance(seq, Sequence):
+      seq = Sequence([seq])
+    self.groups_def = seq
+    self.aggregate = [self._resolve_schema(c, lambda colnm: (colnm, None))[0] 
+        for c in self.groups_def ]
+
+  def transform(self, schema, data):
+    r"""Create groups.
     """
     self.unsupported()
 
 class GVizPivotClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 4, 'idx_eval': 2, 'keyw' : 'pivot'}
   KEYWORDS = ('pivot',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with the expressions transforming values into
+    new columns.
+    """
+    if not isinstance(seq, Sequence):
+      seq = Sequence([seq])
+    self.pivot_def = seq
+    self.pivot = [self._resolve_schema(c, lambda colnm: (colnm, None))[0] 
+        for c in self.pivot_def ]
+
+  def transform(self, schema, data):
+    r"""Create new columns from data.
     """
     self.unsupported()
 
 class GVizOrderByClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 5, 'idx_eval': 4, 'keyw' : 'order by'}
   KEYWORDS = ['asc', 'desc', 'order', 'by']
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with expressions used to sort base result set.
+    """
+    if isinstance(seq, tuple):
+      seq = Sequence([seq])
+    elif isinstance(seq, dict):
+      seq = Sequence([(seq, True)])
+    self.order_def = [c if isinstance(c, tuple) else (c, True) for c in seq]
+    self.sort = [(self._resolve_schema(c, lambda colnm: (colnm, None))[0], is_asc) 
+        for c, is_asc in self.order_def ]
+
+  def transform(self, schema, data):
+    r"""Sort rows in base result set by evaluating target expressions.
     """
     self.unsupported()
 
 class GVizLimitClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 6, 'idx_eval': 6, 'keyw' : 'limit'}
   KEYWORDS = ('limit',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, number):
+    r"""Initialize this clause with an integet value
     """
-    tkn, val = ctx.stream.next()
-    if tkn is Number.Integer :
-      self.cnt = int(val)
-      ctx.stream.next()
-    else :
-      raise GVizInvalidQuery("Syntax error: Integer number expected " \
-                              "but %s found." % (val,))
-  
+    self.cnt = number
+
   def transform(self, schema, data):
     r"""Retrieve no more than `cnt` items.
     """
 class GVizOffsetClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 7, 'idx_eval': 5, 'keyw' : 'offset'}
   KEYWORDS = ('offset',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, number):
+    r"""Initialize this clause with an integet value
     """
-    tkn, val = ctx.stream.next()
-    if tkn is Number.Integer :
-      self.skip = int(val)
-      ctx.stream.next()
-    else :
-      raise GVizInvalidQuery("Syntax error: Integer number expected " \
-                              "but %s found." % (val,))
-  
+    self.skip = number
+
   def transform(self, schema, data):
     r"""Skip the number of items determined by `skip` attribute.
     """
 class GVizLabelClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 8, 'idx_eval': 10, 'keyw' : 'label'}
   KEYWORDS = ('label',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with a sequence of formatting expressions
     """
-    self.labels = labels = []
-    tkn, val = Punctuation, ','               # Enter the cycle initially
-    while tkn is Punctuation and val == ',':
-      tkn, val = ctx.stream.next()
-      if tkn is Name.Variable :
-        if val.startswith('`'):
-          val = val[1:-1]
-        colnm = val
-        tkn, val = ctx.stream.next()
-        if tkn in [String.Single, String.Double]:
-          val = val[1:-1]                         # Remove quotes
-          labels.append((colnm, val.encode('utf-8', 'ignore')))
-        else :
-          raise GVizInvalidQuery("Syntax error: String constant " \
-                                "expected but %s found." % (val,))
-        tkn, val = ctx.stream.next()
-      else :
-        raise GVizInvalidQuery("Syntax error: Column name expected " \
-                                "but %s found." % (val,))
-  
+    self.labels = list(seq)
+
   def transform(self, schema, data):
     r"""(Add | modify) the schema in order to (include | update) 
     column labels.
-    
+
     Note: The process is not aborted if a label for a missing column 
           is specified.
     """
 class GVizFormatClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 9, 'idx_eval': 8, 'keyw' : 'format'}
   KEYWORDS = ('format',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with a sequence of formatting expressions
+    """
+    if not isinstance(seq, Sequence):
+      seq = Sequence([seq])
+    self.fmt = seq
+
+  def transform(self, schema, data):
+    r"""Annotate result set with formatted values.
     """
     self.unsupported()
 
 class GVizOptionsClause(GVizQLClauseHandler):
   _PROPS = {'idx_syntax' : 10, 'idx_eval': 9, 'keyw' : 'options'}
   KEYWORDS = ('options',)
-  
-  def __init__(self, ctx):
-    r"""Initialize the expression using the enclosing parsing context
-    (see docs for `GVizQLParsingContext`). Try to parse the items 
-    in the SELECT clause.
+
+  def __init__(self, seq):
+    r"""Initialize this clause with a list of option names.
+    """
+    if not isinstance(seq, Sequence):
+      get_col_schema = lambda _colnm: (_colnm, None)
+      seq = seq['schema'](get_col_schema)[0]
+      seq = Sequence([seq])
+    self.opts = seq
+
+  def transform(self, schema, data):
+    r"""Condition the result set according to options.
     """
     self.unsupported()
 
   """
   GVIZ_QL_KEYWS = [k for ct in GVizQLClauseType.iterparse() \
                         for k in ct.KEYWORDS]
-  GVIZ_QL_OPS = 'and or is not'.split()
+  GVIZ_QL_OPS = 'and,or,is,not,contains,starts with,ends with,matches,' \
+        'like'.split(',')
   GVIZ_QL_FUNCS = 'max min count avg sum'.split()
   GVIZ_QL_CPREF = 'date datetime timeofday timestamp'.split()
   GVIZ_QL_CONST = 'true false null'.split()
             (r'[a-zA-Z]\w*', Name.Variable, '#pop'),
           ],
       }
-  
+
+  from tracgviz.grammar import GVIZ_GRAMMAR_PRECEDENCE, GVIZ_QL_START_STATE, \
+      GVIZ_GRAMMAR_PRODUCTIONS
+
   def __init__(self, *args, **kwds):
     super(GVizQLParser, self).__init__(*args, **kwds)
     self.noisy = True
-  
+    self.parser = OperatorPrecedenceParser()
+    self.parser.start_state = self.GVIZ_QL_START_STATE
+    self.parser.precedence = self.GVIZ_GRAMMAR_PRECEDENCE
+    self.parser.productions_tree = self.GVIZ_GRAMMAR_PRODUCTIONS
+
   def parse(self, tq):
     r"""Parse a GVizQL expression.
-    
+
     @param tq                       the GViz QL expression.
-    @return                         an instance 
+    @return                         an instance of GVizQLExpression 
     @throw GVizInvalidQuery         if a syntax error or other error 
                                     is detected in the input string.
     @throw GVizUnsupportedQueryOp   if the GViz QL query expression 
                                     contains a clause or feature 
                                     that's not supported yet.
     """
-    global GVizUnsupportedQueryOp, GVizInvalidQuery
-    from api import GVizUnsupportedQueryOp as GU, GVizInvalidQuery as GI
-    GVizUnsupportedQueryOp, GVizInvalidQuery = GU, GI
-    
     tkns = iter(self.get_tokens(tq))
+
+    builder = GVizQLExpressionBuilder(self.parser)
     try:
-      tkn, val = tkns.next()
-    except StopIteration:
-      raise GVizInvalidQuery("No token found: empty string ?")
-    else:
-      order = None
-      expr = GVizQLExpression()
-      ch = None
-      try:
-        while True:         # Try to parse the next clause
-          if tkn is Whitespace and val == '\n':
-            break
-          elif tkn is not Keyword.Reserved:   # Check for a valid clause 
-            last = ch.get_props('keyw')
-            raise GVizInvalidQuery("Invalid token %s found %s: " \
-                                    "Clause name expected." % \
-                                        (val, ch and 'after ' + last or ''))
-          clause_type = GVizQLClauseType.CLAUSE_CACHE[val]
-          clause_order = clause_type.get_props('idx_syntax')
-          if not clause_order <= order:
-            order = clause_order
-          else:
-            raise GVizInvalidQuery("Invalid token %s found: " \
-                                    "Unexpected clause." % (val,))
-          ch = clause_type(self._ctx)     # Consume tokens until the 
-                                          # clause is over
-          expr._add_handler(ch)
-          tkn, val = self._ctx._last
-      except StopIteration:             # TODO: Trailing whitespace? (bug ?)
-        pass
-      if not expr._handlers:            # Something was actually parsed ?
-        raise GVizInvalidQuery("No token found: empty string ?")
-      return expr
-  
+      result = self.parser.parse(tkns, on_reduce=builder.dispatch, \
+          on_accept=builder.handle_gvizql)
+    except SyntaxError, exc:
+      raise GVizInvalidQuery(exc)
+    return result
+
   def get_tokens(self, tq):
     try:
       self._ctx = ctx = GVizQLParsingContext()
     finally:
       self.filters = []
       self._ctx = None
-    
+
 class GVizQLParsingContext():
   r"""Used to store global information generated at parsing time. 
   The parser adds the following fields to this object:
-    
+
     - stream : The token stream being processed.
     - parser : The object that's actually parsing the GViz QL expression.
   """
     for attr in 'parser stream'.split():
       setattr(self, attr, None)
     self._last = (None, None)
-  
+
+  OPERATOR_OVERRIDES = {
+      '*' : Operator.Arithmetic,
+      '+' : Operator.Arithmetic,
+      '-' : Operator.Arithmetic,
+      '/' : Operator.Arithmetic,
+      '<=' : Operator.Comparison,
+      '<' : Operator.Comparison,
+      '>' : Operator.Comparison,
+      '>=' : Operator.Comparison,
+      '=' : Operator.Comparison,
+      '!=' : Operator.Comparison,
+      '<>' : Operator.Comparison,
+      'is' : Operator.Word.Comparison,
+      'is not' : Operator.Word.Comparison,
+      'and' : Operator.Word.Boolean,
+      'or' : Operator.Word.Boolean,
+      'not' : Operator.Word.Boolean,
+      'contains' : Operator.Word.Comparison,
+      'starts with' : Operator.Word.Comparison,
+      'ends with' : Operator.Word.Comparison,
+      'matches' : Operator.Word.Comparison,
+      'like' : Operator.Word.Comparison,
+    }
+
   def filter(self, p, stream):
     r""" Store lookahead token.
     """
         if p.noisy :
           raise GVizInvalidQuery("Invalid token %s " % t[1:])
       elif t[0] is not Whitespace:
+
+        # Artificial whitespace between SQL clauses
+        if t[0] in Keyword.Reserved and self._last != (None, None):
+          yield (Whitespace, ' ')
+
         if self._last == (Keyword.Reserved, 'select') and \
             t == (Operator, '*'):
           t = Name.Other, '*'
+        elif t[0] is Name.Variable and t[1] in GVizQLParser.GVIZ_QL_CONST:
+          # FIXME: Constants are sometimes matched as variables . Bizarre !
+          t = (Keyword.Constant, t[1])
+        elif t[0] in Operator and t[1] in self.OPERATOR_OVERRIDES:
+          t = (self.OPERATOR_OVERRIDES[t[1]], t[1])
       elif t[1].endswith('\n'):
         t = (Whitespace, '\n')
       else:
         continue
       self._last = t
       yield t
-    
+
   @property
   def last_token():
     return self._last
-  
+
 class GVizQLExpression:
   r"""Compiled GVizQL expression.
   """
     """
     self._handlers = dict()
     self._attrmap = dict()
+
   def _add_handler(self, ch):
     r"""Add a clause handler to this expression object. Bind the 
     handler's attributes to lazy arguments.
     self._handlers[clause_nm] = ch
     for attrnm in ch.__dict__ :
       self._attrmap[attrnm] = clause_nm
-    
+
   def __getattr__(self, attrnm):
     try:
       return getattr(self._handlers[self._attrmap[attrnm]], attrnm)
     except :
       raise AttributeError("'%s' object has no attribute '%s'" % \
                                 (self.__class__.__name__, attrnm))
-  
+
   def itereval(self):
     r"""Iterate over the clause handlers present in this expression 
     following evaluation precedence.
       ch = self._handlers.get(ct.get_props('keyw'))
       if ch is not None :
         yield ch
-  
+
   def transform(self, schema, data):
     r"""Transform the result set as determined by the GVizQL 
     expression directives and clauses.
   r"""Prepare the data and schema to be supplied to an instance of 
   gviz_api.DataTable as determined by a GVizQL expression. This is 
   accomplished by wrapping the original data with multiple iterators.
-  
+
   @param provider   an instance of `IGVizDataProvider` interface 
                     responsible for providing the base result set 
                     (i.e. primary information) subsequently modified 
     sch = provider.get_data_schema(*sch_args)
     return tq.transform(sch, data)
 
+class Sequence(list):
+  pass
+
+class GVizQLExpressionBuilder:
+  r"""Stub class responsible for handling parser callback invocations 
+  in order to build instances of `GVizQLExpression`.
+  """
+  def __init__(self, parser, scalar_funcs=None, agg_funcs=None):
+    self.parser = parser
+    if scalar_funcs is None:
+      scalar_funcs = self._default_scalar_funcs()
+    if agg_funcs is None:
+      agg_funcs = self._default_aggregate_funcs()
+    self.scalar_funcs = scalar_funcs
+    self.agg_funcs = agg_funcs
+    self.now = None
+
+  @classmethod
+  def _default_scalar_funcs(cls):
+    from tracgviz import scalar
+    return dict([nm, getattr(scalar, nm)] for nm in scalar.__all__)
+
+  @classmethod
+  def _default_aggregate_funcs(cls):
+    from tracgviz import aggregate
+    return dict([nm, getattr(aggregate, nm)] for nm in aggregate.__all__)
+
+  def dispatch(self, prod_id, *args):
+    try:
+      handler = getattr(self, 'handle_' + prod_id)
+    except AttributeError:
+      raise InvalidParserConfiguration(self.parser, 
+          'Unknown production ' + prod_id)
+    else:
+      result = handler(*args)
+      if isinstance(result, dict):
+        result['production'] = prod_id
+      return result
+
+  # Special markers 
+
+  Sequence = Sequence
+
+  @property
+  def SyntaxError(self):
+    return GVizInvalidQuery
+
+  # Grammar production handlers
+
+  def handle_number(self, value):
+    if value[0] in Number.Integer:
+      _value = int(value[1])
+    else:
+      _value = float(value[1])
+    return dict(
+        eval=_value, 
+        schema=(value[1], 'number'), 
+        is_eval_callable=False,
+        is_schema_callable=False
+      )
+
+  def handle_var(self, name):
+    colnm = name[1]
+    if colnm.startswith('`'):
+      colnm = colnm[1:-1]
+    return dict(
+        eval=lambda row, getvalue: getvalue(row, colnm) , 
+        schema=lambda get_col_schema: get_col_schema(colnm),
+        is_eval_callable=True,
+        is_schema_callable=True)
+
+  def handle_str(self, value):
+    return dict(
+        eval=literal_eval(value[1]), 
+        schema=(value[1], 'string'),
+        is_eval_callable=False,
+        is_schema_callable=False)
+
+  def handle_date(self, value):
+    try:
+      kind, _value = value[1].split()
+      _value = literal_eval(_value)
+      f, fmtstr = {
+          'date' : (datetime.date, '%Y-%m-%d'),
+          'timeofday' : (datetime.time, '%H:%M:%S'),
+          'datetime' : (lambda x: x, '%Y-%m-%d %H:%M:%S'),
+        }.get(kind)
+      if not kind:
+        raise self.SyntaxError('Invalid date literal %s' % value[1])
+      _value = datetime.strptime(_value, fmtstr)
+    except ValueError:
+      raise self.SyntaxError('Invalid date literal %s' % value[1])
+    return dict(
+        eval=f(_value), 
+        schema=(value[1], kind), 
+        is_eval_callable=False,
+        is_schema_callable=False)
+
+  def handle_const(self, value):
+    try:
+      _value = {
+          'true' : True,
+          'false' : False,
+          'null' : None
+        }.get(value[1])
+    except KeyError:
+      raise self.SyntaxError('Unexpected constant %s' % (value[1],))
+    return dict(
+        eval=_value, 
+        schema=(value[1], 'boolean' if value[1] != 'null' else None), 
+        is_eval_callable=False,
+        is_schema_callable=False
+      )
+
+  def handle_seq(self, seq, _, expr):
+    _seq = seq[1]
+    _expr = expr[1]
+    if isinstance(_seq, self.Sequence):
+      _seq.append(_expr)
+    else:
+      _seq = self.Sequence([_seq, _expr])
+    return _seq
+
+  def _unsupported(self, *args):
+    raise NotImplementedError('Feature not supported ... yet')
+
+  def handle_bfunc(self, funcnm, _, colnm, __):
+    funcnm = funcnm[1]
+    colnm = colnm[1]
+    col_schema = colnm['schema'](lambda colnm: (colnm, None) )
+    try:
+      f = self.agg_funcs[funcnm]
+    except KeyError:
+      raise LookupError('Unknown aggregation function %s' % (funcnm,))
+    return_type = getattr(f, 'return_type', None)
+    func_label = '%s(%s)' % (funcnm, col_schema[0])
+    return dict(
+        eval=self._unsupported, 
+        schema=(func_label, return_type) if return_type else 
+            lambda get_col_schema: (func_label, get_col_schema(col_schema[0])[1]),
+        is_eval_callable=True,
+        is_schema_callable=not bool(return_type)
+      )
+
+  def handle_func(self, funcnm, _, __):