forget the past.
authorNicolas Chauvat <nicolas.chauvat@logilab.fr>
Mon, 08 May 2006 20:03:41 +0200
changeset 0 d7a978efc65b
child 1 54d3fba9e109
forget the past.
ChangeLog
DEPENDS
MANIFEST.in
README
TODO
__init__.py
__pkginfo__.py
_exceptions.py
analyze.py
compare.py
crql.py
debian/changelog
debian/control
debian/copyright
debian/python-rql-test.dirs
debian/python-rql.dirs
debian/python-rql.docs
debian/python2.3-rql.dirs
debian/python2.3-rql.docs
debian/python2.3-rql.postinst
debian/python2.3-rql.prerm
debian/python2.4-rql.dirs
debian/python2.4-rql.docs
debian/python2.4-rql.postinst
debian/python2.4-rql.prerm
debian/rules
doc/canonisation.txt
doc/makefile
doc/specifications_fr.txt
doc/tutoriel_fr.txt
editextensions.py
fol.py
interfaces.py
makefile
nodes.py
parser.g
parser.py
parser_main.py
rqlgen.py
rqlmodule/Makefile
rqlmodule/README
rqlmodule/boost_module.cc
rqlmodule/node_exceptions.hh
rqlmodule/nodes.cc
rqlmodule/nodes.hh
rqlmodule/rql.cg
rqlmodule/rql_main.cc
rqlmodule/rql_parser.cc
rqlmodule/rql_parser.hh
rqlmodule/rql_scanner.cc
rqlmodule/rql_scanner.hh
rqlmodule/rql_token.cc
rqlmodule/rql_token.hh
rqlmodule/rqlmodule.cc
setup.py
stcheck.py
stmts.py
test/runtests.py
test/test_unify.py
test/unittest_analyze.py
test/unittest_compare.py
test/unittest_editextensions.py
test/unittest_nodes.py
test/unittest_parser.py
test/unittest_rqlgen.py
test/unittest_stcheck.py
test/unittest_utils.py
thirdparty/__init__.py
thirdparty/setup.py
thirdparty/yapps2.py
thirdparty/yappsrt.py
tools/bench_cpprql.py
tools/bench_pyrql.py
tools/data/bench.rql
tools/data/benchuniq.rql
tools/data/test_snip1.rql
tools/data/test_snip2.rql
tools/data/test_snip3.rql
tools/data/test_snip4.rql
tools/data/test_snip5.rql
tools/rql_analyze.py
tools/rql_cmp.py
tools/rql_parse.py
undo.py
utils.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChangeLog	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,54 @@
+ChangeLog for RQL
+=================
+
+  --
+    * fixed syntax tree copy, just call stmt.copy() to have a
+      full deep copy
+    * support for substitute on uid relation in the type analyzer
+      (this implies to give the kwargs dictionary of the query to the 
+      analyzer)
+
+	
+2006-03-28  --  0.4.2
+    * fixed a bug when a variable is related to itself
+    * allow numbers in variable and entity types
+    * C parser (disabled by default)
+
+2006-02-10  --  0.4.1
+    * fix set_distinct so that previous distinct attribute is correctly undoed
+      if necessary
+    * remove a false assertion in remove_selected
+    * remove unnecessary OR from the tree when used with a symetric relation
+	
+2006-01-23  --  0.4.0
+    * fix Constant's type when NOW is used
+    * allow function in ORDERBY expression
+    * refactor some edit extensions
+
+
+2005-07-26  --  0.3.1
+    * close #9629, "Any E WHERE P is Project, P eid E"  foire
+    * fix bug with IN() used in update queries
+
+
+2005-07-06  --  0.3.0
+    * reintroduce analyze restriction from special relations, which may speed
+      up analyzing
+
+
+2005-06-16  --  0.2.0
+    * minor evolutions
+    * added Cpp parser module (not yet activated)
+    * minor performance improvement
+
+2004-09-23  --  0.1.2
+    * minor evolutions
+
+    * bugfixes with constant management (TODAY, etc.)
+
+
+2004-06-10  --  0.1.1
+    * minor evolutions
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDS	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2 @@
+python-logilab-common
+python-constraint (>= 0.2.7)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MANIFEST.in	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,12 @@
+include doc/*.html
+include doc/*.txt
+include doc/makefile
+
+include rqlmodule/*.hh
+include makefile
+include parser.g
+
+include README
+include TODO 
+include ChangeLog
+include DEPENDS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,5 @@
+This package provides base library for the Relationship Query Language
+
+INSTALL
+-------
+python setup.py install
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TODO	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,13 @@
+TODO list for the rql package
+=============================
+
+* retirer les restrictions e_type = [A-Z][a-z_]*
+                           r_type = [a-z_]*
+
+* detecter les erreurs ASAP pour éviter stcheck
+
+* tests unitaires pour sqlgen
+
+* revoir tutoriel
+
+* specification 1.0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/__init__.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,119 @@
+"""RQL implementation independant library.
+
+Copyright (c) 2004-2005 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: __init__.py,v 1.30 2006-05-01 13:01:56 syt Exp $"
+
+import sys
+import threading
+from cStringIO import StringIO
+
+from rql._exceptions import *
+from rql.interfaces import *
+from rql.parser import Hercule, HerculeScanner, print_error, \
+     SyntaxError, NoMoreTokens
+from rql.nodes import Constant
+from rql.stcheck import RQLSTChecker
+from rql.analyze import ETypeResolver
+from rql.compare import compare_tree
+from rql.utils import is_keyword, get_nodes
+
+REQUIRED_TYPES = ['String', 'Float', 'Int', 'Boolean', 'Date']
+
+class RQLHelper:
+    """Helper class for RQL handling
+
+    give access to methods for :
+      - parsing RQL strings
+      - variables type resolving
+      - comparison of two queries
+    """
+    def __init__(self, schema, uid_func_mapping=None, Resolver=ETypeResolver):
+        # chech schema
+        #for e_type in REQUIRED_TYPES:
+        #    if not schema.has_entity(e_type):
+        #        raise MissingType(e_type)
+        # create helpers
+        self._rql_checker = RQLSTChecker(schema)
+        self._rql_analyser = Resolver(schema, uid_func_mapping)
+        self.set_schema(schema)
+        
+    def set_schema(self, schema):
+        self.e_types = e_types = {}
+        for e_type in schema.entities():
+            if is_keyword(e_type) or e_type.capitalize() == 'Any':
+                raise UsesReservedWord(e_type)
+            e_types[e_type] = e_type
+        for r_type in schema.relations():
+            if is_keyword(r_type) or r_type.lower() == 'is':
+                raise UsesReservedWord(r_type)
+        self._rql_checker.schema = schema
+        self._rql_analyser.set_schema(schema)
+        
+    def parse(self, rql_string):
+        """return a syntax tree from an sql string"""
+        tree = parse(rql_string, self.e_types)
+        # check for errors not detectable at parsing time
+        self._rql_checker.visit(tree)
+        # ok, return the tree
+        return tree
+
+    def get_solutions(self, rql_st, uid_func_mapping=None, kwargs=None, debug=False):
+        """return a list of solutions for variables of the syntax tree
+
+        each solution is a dictionary with variable's name as key and
+        variable's type as value
+        """
+        return self._rql_analyser.visit(rql_st, uid_func_mapping, kwargs, debug)
+
+    def compare(self, rql_string1, rql_string2):
+        """compares 2 RQL requests
+        
+        returns true if both requests would return the same results
+        returns false otherwise
+        """
+        return compare_tree(self.parse(rql_string1),
+                            self.parse(rql_string2))
+
+        
+def parse(rql_string, e_types=None, print_errors=True): 
+    """return a syntax tree from an sql string"""   
+    # make sure rql string ends with a semi-colon
+    rql_string = rql_string.strip()
+    if rql_string and not rql_string.endswith(';') :
+        rql_string += ';'
+    # parse the RQL string
+    parser = Hercule(HerculeScanner(rql_string))
+    try:
+        return parser.goal(e_types)
+    except SyntaxError, ex:
+        if not print_errors:
+            raise RQLSyntaxError(ex.msg)
+        # try to get error message from yapps
+        pinput = parser._scanner.input
+        try:
+            out = sys.stdout
+            sys.stdout = stream = StringIO()
+            try:
+                print_error(pinput, ex, parser._scanner)
+            finally:
+                sys.stdout = out
+            raise RQLSyntaxError(stream.getvalue())
+        except ImportError:
+            sys.stdout = out
+            raise RQLSyntaxError('Syntax Error', ex.msg, 'on line',
+                                 1 + pinput.count('\n', 0, ex.pos))            
+    except NoMoreTokens:
+        msg = 'Could not complete parsing; stopped around here: \n%s'
+        raise RQLSyntaxError(msg  % parser._scanner)
+
+pyparse = parse
+
+#try:
+#    from rql.crql import parse
+#except ImportError:
+#    pass
+#    #print "Falling back to python version of the RQL parser!"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/__pkginfo__.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,47 @@
+# pylint: disable-msg=W0622
+# Copyright (c) 2003-2006 LOGILAB S.A. (Paris, FRANCE).
+# http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+rql packaging information
+"""
+
+__revision__ = "$Id: __pkginfo__.py,v 1.20 2006-03-28 10:11:17 syt Exp $"
+
+modname = "rql"
+numversion = [0, 4, 2]
+version = '.'.join([str(num) for num in numversion])
+
+license = 'LCL'
+copyright = '''Copyright (c) 2003-2006 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
+
+author = "Sylvain Thenault"
+author_email = "devel@logilab.fr"
+
+short_desc = "relationship query language (RQL) utilities"
+long_desc = """A library providing the base utilities to handle RQL queries,
+such as a parser, a type inferencer.
+"""
+web = "" #"http://www.logilab.org/projects/rql"
+#ftp = "ftp://ftp.logilab.org/pub/rql"
+
+
+# debianize info
+debian_maintainer = 'Sylvain Thenault'
+debian_maintainer_email = 'sylvain.thenault@logilab.fr'
+pyversions = ['2.3', '2.4']
+
+
+include_dirs = []
+
+from distutils.core import Extension
+ext_modules = [Extension('rql.rqlparse',
+                         ['rqlmodule/rqlmodule.cc',
+                          'rqlmodule/nodes.cc',
+                          'rqlmodule/rql_parser.cc',
+                          'rqlmodule/rql_scanner.cc',
+                          'rqlmodule/rql_token.cc',
+                          ],
+#                         extra_compile_args = ["-O0"],
+                         ),
+               ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_exceptions.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,27 @@
+"""
+ Copyright (c) 2000-2003 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+
+ defines exception used in the rql package
+"""
+
+__revision__ = "$Id: _exceptions.py,v 1.2 2003-11-24 15:30:52 syt Exp $"
+
+class RQLException(Exception):
+    """base exception for exceptions of the rql module"""
+
+
+class MissingType(RQLException):
+    """raised when there is some expected type missing from a schema"""
+
+class UsesReservedWord(RQLException):
+    """raised when the schema uses a reserved word as type or relation"""
+
+class RQLSyntaxError(RQLException):
+    """raised when there is a syntax error in the rql string"""
+
+class TypeResolverException(RQLException):
+    """raised when we are unable to guess variables'type"""
+
+class BadRQLQuery(RQLException):
+    """raised when there is a no sense in the rql query"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/analyze.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,484 @@
+"""
+ Copyright (c) 2004-2005 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+
+Analyze of the RQL syntax tree to get possible types for rql variables
+"""
+
+__revision__ = "$Id: analyze.py,v 1.30 2006-05-01 13:01:56 syt Exp $"
+
+
+from logilab.constraint import Repository, Solver, fd
+
+from rql import TypeResolverException
+from rql import nodes 
+from rql.utils import iget_nodes
+from pprint import pprint
+
+
+class ETypeResolver:
+    """resolve variables types according to the schema
+
+    CSP modelisation :
+    
+      variable    <-> RQL variable
+      domains     <-> different entity's types defined in the schema
+      constraints <-> relations between (RQL) variables
+    """
+    
+    def __init__(self, schema, uid_func_mapping=None):
+        """
+        * schema :
+            schema for entities and relations
+        * uid_attr :
+            string designing the attribute used as Unique IDentifiant 
+        * get_type_from_uid :
+            method the maybe used to get an entity's type given the value of
+            its UID attribute
+        """
+        self.set_schema(schema)
+        # mapping from relation to function taking rhs value as argument
+        # and returning an entity type
+        self.uid_func_mapping = {}
+
+    def set_schema(self, schema):
+        self.schema = schema
+        # default domain for a variable
+        self._base_domain = schema.entities()
+        
+    def visit(self, node, uid_func_mapping=None, kwargs=None, debug=False):
+        # FIXME: not thread safe
+        if uid_func_mapping is not None:
+            self.uid_func_mapping = uid_func_mapping
+        self.kwargs = kwargs
+        # init variables for a visit
+        domains = {}
+        constraints = []
+        
+        # set domain for the all variables
+        for var in node.defined_vars.values():
+            domains[var.name] = fd.FiniteDomain(self._base_domain)
+
+        # add restriction specific to delete and insert 
+        if node.TYPE in ('delete', 'insert'):
+            for e_type, variable in node.main_variables:
+                var = variable.name
+                constraints.append(fd.make_expression(
+                    (var,), '%s == %r' % (var, e_type)))
+            for relation in node.main_relations:
+                self._visit(relation, constraints)
+        # add restriction specific to update
+        elif node.TYPE == 'update':
+            for relation in node.main_relations:
+                self._visit(relation, constraints)
+        
+        restriction = node.get_restriction()
+        if restriction is not None:
+            # get constraints from the restriction subtree
+            self._visit(restriction, constraints)
+        elif node.TYPE == 'select':
+            varnames = [v.name for v in node.get_selected_variables()]
+            # add constraint on real relation types if no restriction
+            types = [e_schema.type
+                     for e_schema in self.schema.entities(schema=1)
+                     if not e_schema.is_final()]
+            constraints.append(fd.make_expression(varnames, '%s in %s ' % (
+                '=='.join(varnames), types)))
+        
+        # debug info
+        if debug > 1:
+            print "- AN1 -"+'-'*80
+            print node
+            print "DOMAINS:"
+            pprint(domains)
+            print "CONSTRAINTS:"
+            pprint(constraints)
+            
+        return self.solve(node, domains, constraints)
+
+
+    def solve(self, node, domains, constraints):
+        # solve the problem and check there is at least one solution
+        r = Repository(domains.keys(), domains, constraints)
+        solver = Solver()
+        sols = solver.solve(r, verbose=0)
+        if not sols:
+            raise TypeResolverException(
+                'Unable to resolve variables types in "%s"!!' % node)
+        return sols
+
+        
+    def _visit(self, node, constraints):
+        """recurse among the tree"""
+        func = getattr(self, 'visit_%s' % node.__class__.__name__.lower())
+        func(node, constraints)
+        #node.accept(self, constraints)
+        for c in node.children:
+            self._visit(c, constraints)
+
+        
+    def visit_relation(self, relation, constraints):
+        """extract constraints for an relation according to it's  type"""
+        r_type = relation.r_type
+        lhs, rhs = relation.get_parts()
+        if r_type == 'is':
+            types = [c.value for c in iget_nodes(rhs, nodes.Constant)]
+            if relation._not:
+                not_types = [t for t in self._base_domain if not t in types]
+                types = not_types
+            constraints.append(fd.make_expression(
+                (lhs.name,), '%s in %s ' % (lhs.name, types)))
+            return
+        elif r_type in self.uid_func_mapping:
+            eids = []
+            for cst in iget_nodes(rhs, nodes.Constant):
+                # if there is one None (NULL) constant type,
+                # we can't use the uid function
+                if cst.type is None:
+                    break
+                if cst.type == 'Substitute':
+                    eid = self.kwargs[cst.value]
+                else:
+                    eid = cst.value
+                eids.append(eid)
+            else:
+                if eids:
+                    types = {}
+                    for eid in eids:
+                        types[self.uid_func_mapping[r_type](eid)] = True
+                    constraints.append(fd.make_expression(
+                        (lhs.name,), '%s in %s ' % (lhs.name, types.keys())))
+                    return           
+        r_schema = self.schema.relation_schema(r_type)
+        lhs_var = lhs.name
+        rhs_vars = [v.name for v in iget_nodes(rhs, nodes.VariableRef)
+                    if not v.name == lhs_var]
+        if rhs_vars:
+            s2 = '=='.join(rhs_vars)
+            res = []
+            for from_type, to_types in r_schema.association_types():
+                res.append('(%s==%r and %s in %r)' % (lhs_var, from_type, s2,
+                                                      to_types))
+            constraints.append(fd.make_expression(
+                [lhs_var] + rhs_vars, ' or '.join(res)))
+        else:
+            constraints.append(fd.make_expression(
+                (lhs_var,), '%s in %r'  % (lhs_var, r_schema.subject_types())))
+
+    def visit_and(self, et, constraints):
+        pass
+    def visit_or(self, ou, constraints):
+        pass        
+    def visit_comparison(self, comparison, constraints):
+        pass
+    def visit_mathexpression(self, mathexpression, constraints):
+        pass
+    def visit_function(self, function, constraints):
+        pass
+    def visit_variableref(self, variableref, constraints):
+        pass
+    def visit_constant(self, constant, constraints):
+        pass
+    def visit_keyword(self, keyword, constraints):
+        pass
+
+
+# ==========================================================
+
+
+
+class UnifyError(Exception):
+    """raised when unification produces an error"""
+
+# XXX: C'est l'algo de NlpTools, on peut le simplifier
+# bcp car on n'a que des traits de type { x: [v1], y:[v2] }
+# on peut en faire une version non destructive en traquant
+# les id() des listes (qui servent de pointeurs)
+# ensuite on peut enlever les deepcopy dans unify_sols
+def feature_unify(f1, f2):
+    f1_real = f1
+    while type(f1_real) == list:
+        f1 = f1_real
+        f1_real = f1_real[0]
+    f2_real = f2
+    while type(f2_real) == list:
+        f2 = f2_real
+        f2_real = f2_real[0]
+    if f1_real == None:
+        if type(f1) == list:
+            f1[0] = f2_real
+            return f1
+        return f2
+    if f2_real == None:
+        if type(f2) == list:
+            f2[0] = f1_real
+            return f2
+        return f1
+    if type(f1_real)!=dict and f1_real == f2_real:
+        if type(f1) == list:
+            f1[0] = f2_real
+            return f2
+        elif type(f2) == list:
+            f2[0] = f1_real
+            return f1
+        return f1
+    if type(f1_real) == dict and type(f2_real) == dict:
+        for k2, v2 in f2_real.items():
+            v1 = f1_real.get(k2, [None])
+            vv = feature_unify(v2, v1)
+            f1_real[k2] = vv
+        return f1_real
+    raise UnifyError
+
+def deepcopy(s):
+    r = {}
+    memo = {}
+    for k, v in s.items():
+        if type(v)==list:
+            seen = memo.setdefault(id(v),[v[0]])
+        r[k] = v
+    return r
+
+def unify_sols( sols1, sols2 ):
+    sols = []
+#    print "Unifying"
+#    print "Sols1", sols1
+#    print "Sols2", sols2
+    for s1 in sols1:
+        for s2 in sols2:
+            sa = deepcopy(s1)
+            sb = deepcopy(s2)
+            try:
+                s = feature_unify( sa, sb )
+                sols.append(s)
+            except UnifyError:
+                pass
+#    print "Result", sols
+    return sols
+
+def feature_get( dct, n ):
+    """Simplified version of feature_set for a feature
+    set containing no subfeatures"""
+    v = dct[n]
+    while type(v)==list:
+        v=v[0]
+    return v
+
+def feature_set( dct, n, val ):
+    """Simplified version of feature_set for a feature
+    set containing no subfeatures"""
+    v = dct[n]
+    if type(v)!=list:
+        dct[n] = val
+    while type(v[0])==list:
+        v=v[0]
+    v[0] = val
+
+
+def flatten_features( f ):
+    for k, v in f.items():
+        while type(v)==list:
+            v = v[0]
+        f[k] = v
+    return f
+
+def fprint( f ):
+    from NlpTools.grammar.unification import feature_pprint_text
+    feature_pprint_text(f)
+
+
+BASE_TYPES_MAP = {
+    'String' : 'String',
+    'Int' : 'Int',
+    'Float' : 'Float',
+    'Boolean' : 'Boolean',
+    'Date' : 'Datetime',
+    'Time' : 'Datetime',
+    'Datetime' : 'Datetime',
+    'Password' : 'String',
+    'Bytes' : 'Bytes',
+    }
+
+
+
+class UnifyingETypeResolver:
+    """resolve variables types according to the schema
+
+    CSP modelisation :
+    
+      variable    <-> RQL variable
+      domains     <-> different entity's types defined in the schema
+      constraints <-> relations between (RQL) variables
+    """
+    
+    def __init__(self, schema, uid_func_mapping=None):
+        """
+        * schema :
+            schema for entities and relations
+        * uid_attr :
+            string designing the attribute used as Unique IDentifiant 
+        * get_type_from_uid :
+            method the maybe used to get an entity's type given the value of
+            its UID attribute
+        """
+        self.schema = schema
+        # mapping from relation to function taking rhs value as argument
+        # and returning an entity type
+        self.uid_func_mapping = {}
+        if uid_func_mapping:
+            self.uid_func_mapping=uid_func_mappin
+        # default domain for a variable
+        self._base_domain = schema.entities()
+        self._types = [e_schema.type
+                       for e_schema in self.schema.entities(schema=1)
+                       if not e_schema.is_final()]
+
+    def visit(self, node, uid_func_mapping=None, debug=False):
+#        print "QUERY", node
+        if uid_func_mapping:
+            self.uid_func_mapping=uid_func_mapping
+
+        sols = node.accept(self)
+        # XXX: make sure sols are reported only once
+        sols = [ flatten_features(f) for f in sols ]
+        if not sols:
+            raise TypeResolverException(
+                'Unable to resolve variables types in "%s"!!'%node)
+        return sols
+    
+    def visit_children(self, node):
+        sols1 = [{}]
+        for n in node.children:
+            sols2 = n.accept(self)
+            sols1 = unify_sols( sols1, sols2 )
+        return sols1
+
+
+    def visit_insert_or_delete(self, node):
+        t = {}
+        for etype, variable in node.main_variables:
+            t[variable.name] = etype
+        sols = [t]
+        for relation in node.main_relations:
+            sols2 = relation.accept(self)
+            sols = unify_sols( sols, sols2 )
+        return sols
+            
+    def visit_delete(self, node):
+        return self.visit_insert_or_delete( node )
+
+    def visit_select(self, node):
+        sols = self.visit_children(node)
+        for n in node.selected:
+            sols2 = n.accept(self)
+            for s in sols2:
+                del s['type']
+            sols = unify_sols( sols, sols2 )
+
+        # add non-final types for non resolved vars
+        extra = []
+        for s in sols:
+            for k in s:
+                v = feature_get( s, k )
+                if v is None:
+                    for t in self._types:
+                        extra.append( { k : t } )
+        if extra:
+            sols = unify_sols( sols, extra )
+        return sols
+
+    def visit_insert(self, node ):
+        return self.visit_insert_or_delete( node )
+
+    def visit_relation(self, relation ):
+        r_type = relation.r_type
+#        print "Relation", r_type
+        lhs, rhs = relation.get_parts()
+        expr_sols = rhs.accept(self)
+        if r_type == 'is' and not relation._not:
+            for s in expr_sols:
+                typ = s['type']
+                s[lhs.name] = typ
+                del s['type']
+            return expr_sols
+        elif r_type == 'is' and relation._not:
+            all_types = [ { lhs.name: t } for t in self._base_domain]
+            sols = []
+            not_types = [ s['type'] for s in expr_sols ]
+            for s in all_types:
+                if s[lhs.name] not in not_types:
+                    sols.append(s)
+            return sols
+                
+        
+        r_schema = self.schema.relation_schema(r_type)
+#        print "Schema", r_schema
+        l = []
+        typ = [None]
+        vlhs = [{'type' : typ, lhs.name : typ }]
+        for from_type, to_types in r_schema.association_types():
+            for to_type in to_types:
+                # a little base type pre-unification
+                to_type = BASE_TYPES_MAP.get(to_type,to_type)
+                s = {
+                    'type' : [to_type],
+                    lhs.name : [from_type],
+                    }
+                l.append(s)
+        sols = unify_sols( l, expr_sols )
+        for s in sols:
+            del s['type']
+        return sols
+
+    def visit_comparison(self, comparison):
+        if len(comparison)==0:
+            return [{}]
+        sols = comparison[0].accept(self)
+        return sols
+
+    def visit_function(self, function):
+        # XXX : todo function typing
+        return [{ 'type':[None]}]
+
+    def visit_variableref(self, variableref):
+        var = variableref.name
+        typ = [None]
+        sols = [{ 'type' : typ, var : typ }]
+        return sols
+
+    def visit_constant(self, constant):
+        _typ = constant.type
+        if _typ == 'etype':
+            _typ = constant.value
+        elif _typ == 'Substitute':
+            return [{}]
+        return [{ 'type' : _typ }]
+
+    def visit_keyword(self, keyword):
+        return [{}]
+    def visit_group(self, group):
+        return [{}]
+    def visit_sort(self, sort):
+        return [{}]
+    
+    def visit_mathexpression(self, mathexpression):
+        lhs, rhs = mathexpression
+        sols1 = lhs.accept( self )
+        sols2 = rhs.accept( self )
+        sols = unify_sols( sols1, sols2 )
+        return sols
+
+    def visit_and(self, et):
+        sols1 = et[0].accept(self)
+        for n in et[1:]:
+            sols2 = n.accept(self)
+            sols1 = unify_sols( sols1, sols2 )
+        return sols1
+    
+    def visit_or(self, ou):
+        sols = []
+        for n in ou:
+            sols += n.accept(self)
+        return sols
+    
+#ETypeResolver = UnifyingETypeResolver
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compare.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,199 @@
+""" Copyright (c) 2000-2003 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: compare.py,v 1.7 2004-03-26 07:16:27 syt Exp $"
+
+from rql.nodes import VariableRef, Variable, Function, Relation, Comparison
+from rql.utils import get_nodes
+
+def compare_tree(request1, request2):
+    """compares 2 RQL requests
+
+    Returns true if both requests would return the same results
+    Returns false otherwise
+    """
+    return make_canon_dict(request1) == make_canon_dict(request2)
+
+def make_canon_dict(rql_tree, verbose=0):
+    """returns a canonical representation of the request as a dictionnary
+    """
+    allvars = {}
+    canon = {
+        'all_variables' : allvars,
+        'selected' : [],
+        'restriction' : {},
+        }
+        
+    canon = RQLCanonizer().visit(rql_tree, canon)
+    
+    # forge variable name
+    for var, name_parts in allvars.values():
+        name_parts.sort()
+        var.name = ':'.join(name_parts)
+    sort(canon)
+    if verbose:
+        print 'CANON FOR', rql_tree
+        from pprint import pprint 
+        pprint(canon)
+    return canon
+
+def sort(canon_dict):
+    """remove the all_variables entry and sort other entries in place"""
+    del canon_dict['all_variables']
+    canon_dict['selection'].sort()
+    for values in canon_dict['restriction'].values():
+        values.sort()
+        
+
+class SkipChildren(Exception):
+    """signal indicating to ignore the current child"""
+
+class RQLCanonizer:
+    """build a dictionnary which represents a RQL syntax tree
+    """
+    
+    def visit(self, node, canon):
+        try:
+            node.accept(self, canon)
+        except SkipChildren:
+            return canon
+        for c in node.children:
+            self.visit(c, canon)
+        return canon
+
+    def visit_select(self, select, canon):
+        allvars = canon['all_variables']
+        for var in select.defined_vars.values():
+            allvars[var] = (Variable(var.name), [])
+        canon['selection'] = l = []
+        selected = select.selected
+        for i in range(len(selected)):
+            node = selected[i]
+            if isinstance(node, VariableRef):
+                node = node.variable
+                allvars[node][1].append(str(i))
+                l.append(allvars[node][0])
+            else:  # Function
+                l.append(node)
+                for var in get_nodes(node, VariableRef):
+                    var.parent.replace(var, allvars[var.variable][0])
+                    
+    def visit_group(self, group, canon):
+        canon['group'] = group
+        
+    def visit_sort(self, sort, canon):
+        canon['sort'] = sort
+        
+    def visit_sortterm(self, sortterm, canon):
+        pass
+ 
+    def visit_and(self, et, canon):
+        pass
+    
+    def visit_or(self, ou, canon):
+        canon_dict = {}
+        keys = []
+        for expr in get_nodes(ou, Relation):
+            key = '%s%s' % (expr.r_type, expr._not)
+            canon_dict.setdefault(key, []).append(expr)
+            keys.append(key)
+        keys.sort()
+        r_type = ':'.join(keys)
+        r_list = canon['restriction'].setdefault(r_type, [])
+        done = {}
+        for key in keys:
+            if done.has_key(key):
+                continue
+            done[key] = None
+            for expr in canon_dict[key]:
+                self.manage_relation(expr, canon, r_list)
+        raise SkipChildren()
+    
+    def manage_relation(self, relation, canon, r_list):
+        lhs, rhs = relation.get_parts()
+        # handle special case of the IN function
+        func = rhs.children[0]
+        if isinstance(func, Function) and func.name == 'IN':
+            if not relation._not:
+                base_key = '%s%s' % (relation.r_type, relation._not)
+                if not canon['restriction'][base_key]:
+                    del canon['restriction'][base_key]
+                key = ':'.join([base_key] * len(func.children))
+                r_list = canon['restriction'].setdefault(key, [])
+            for e in func.children:
+                eq_expr = Relation(relation.r_type, relation._not)
+                eq_expr.append(lhs)
+                eq_expr.append(Comparison('=', e))
+                self.manage_relation(eq_expr, canon, r_list)
+                # restaure parent attribute to avoid problem later
+                e.parent = func
+                lhs.parent = relation
+            return
+        # build a canonical representation for this relation
+        lhs_expr_reminder = make_lhs_reminder(lhs, canon)
+        rhs_expr_reminder = make_rhs_reminder(rhs, canon)
+        reminder = (lhs_expr_reminder, rhs_expr_reminder)
+        # avoid duplicate
+        if reminder in r_list:
+            return
+        r_list.append(reminder)
+        # make a string which represents this relation (we'll use it later
+        # to build variables' name)
+        expr_reminder = relation.r_type
+        lhs_vars = get_nodes(lhs, VariableRef)
+        if not lhs_vars:
+            expr_reminder = "%s_%s" % (lhs, expr_reminder)
+        rhs_vars = get_nodes(rhs, VariableRef)
+        if not rhs_vars:
+            expr_reminder = "%s_%s" % (expr_reminder, rhs)
+            
+        for var in lhs_vars + rhs_vars:
+            var = var.variable
+            canon['all_variables'][var][1].append(expr_reminder)
+
+        
+    def visit_relation(self, relation, canon):
+        key = '%s%s' % (relation.r_type, relation._not)
+        r_list = canon['restriction'].setdefault(key, [])
+        self.manage_relation(relation, canon, r_list)
+            
+        
+    def visit_comparison(self, comparison, canon):
+        """do nothing for this node type"""
+    
+    def visit_mathexpression(self, mathexpression, canon):
+        """do nothing for this node type"""
+    
+    def visit_function(self, function, canon):
+        """do nothing for this node type"""
+    
+    def visit_variableref(self, varref, canon):
+        varref.parent.replace(varref,
+                              canon['all_variables'][varref.variable][0])
+        
+    def visit_constant(self, constante, canon):
+        """do nothing for this node type"""
+    
+    
+
+def make_lhs_reminder(lhs, canon):
+    """return a reminder for a relation's left hand side (i.e a VariableRef
+    object)
+    """
+    try:
+        lhs = canon['all_variables'][lhs.variable][0]
+    except (KeyError, IndexError):
+        pass
+    return ('=', lhs)
+
+def make_rhs_reminder(rhs, canon):
+    """return a reminder for a relation's right hand side (i.e a Comparison
+    object)
+    """
+    child = rhs.children[0]
+    try:
+        child = canon['all_variables'][child.variable][0]
+    except AttributeError:
+        pass
+    return (rhs.operator, child)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crql.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,47 @@
+"""RQL implementation independant library.
+
+This module provides an interface to the C version
+of the parser
+
+Copyright (c) 2004-2005 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: crql.py,v 1.2 2006-02-13 17:27:39 ludal Exp $"
+
+
+
+FACTORY = {}
+
+import rql.stmts as stmts
+import rql.nodes as nodes
+from rqlparse import parse as _parse
+import rql._exceptions as _exceptions
+
+stmt_classes = [
+    "Select",
+    "Delete",
+    "Insert",
+    "Update",
+]
+node_classes = [
+    "AND", "OR", "Relation", "Comparison", "Function",
+    "Constant", "MathExpression", "VariableRef", "Variable", "Group",
+    "Sort", "SortTerm",
+    ]
+
+error_classes = [ "BadRQLQuery", "RQLSyntaxError" ]
+def loadsymb( module, symbols):
+    for symbol in symbols:
+        FACTORY[symbol] = getattr(module, symbol)
+
+
+loadsymb( stmts, stmt_classes )
+loadsymb( nodes, node_classes )
+loadsymb( _exceptions, error_classes )
+
+
+def parse( rql_string, e_types=None, print_errors=True ):
+    if rql_string and not rql_string.endswith(';') :
+        rql_string += ';'
+    return _parse( rql_string, FACTORY, e_types, print_errors )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/changelog	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,73 @@
+rql (0.4.2-3) unstable; urgency=low
+
+  * fix postrm and prerm script
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Wed, 29 Mar 2006 18:37:19 +0200
+
+rql (0.4.2-2) unstable; urgency=low
+
+  * fix dependancies on python-constraint
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Wed, 29 Mar 2006 18:20:27 +0200
+
+rql (0.4.2-1) unstable; urgency=low
+
+  * new upstream release including C extensions, so get back to pythonX.X packages...
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Tue, 28 Mar 2006 12:10:34 +0200
+
+rql (0.4.1-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Fri, 10 Feb 2006 11:05:48 +0100
+
+rql (0.4.0-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Mon, 23 Jan 2006 11:19:30 +0100
+
+rql (0.3.1-2) unstable; urgency=low
+
+  * reorganization to install into site-python, removing the need for 
+    pythonX.X- packages
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Tue, 10 Jan 2006 17:42:53 +0100
+
+rql (0.3.1-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Adrien Di Mascio <Adrien.DiMascio@logilab.fr>  Thu, 28 Jul 2005 17:25:16 +0200
+
+rql (0.3.0-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Wed,  6 Jul 2005 13:57:09 +0200
+
+rql (0.2.0-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Arthur Lutz <arthur.lutz@logilab.fr>  Fri, 17 Jun 2005 17:11:02 +0200
+
+rql (0.1.2-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Adrien Di Mascio <Adrien.DiMascio@logilab.fr>  Thu, 23 Sep 2004 14:17:33 +0200
+
+rql (0.1.1-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Arthur Lutz <arthur.lutz@logilab.fr>  Thu, 10 Jun 2004 16:19:58 +0200
+
+rql (0.1.0-1) unstable; urgency=low
+
+  * initial public release
+
+ -- Sylvain Thenault <sylvain.thenault@logilab.fr>  Tue, 20 Apr 2004 13:34:28 +0200
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/control	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,42 @@
+Source: rql
+Section: python
+Priority: optional
+Maintainer: Sylvain Thenault <sylvain.thenault@logilab.fr> 
+Build-Depends: debhelper (>= 4.0.0), python2.3-dev, python2.4-dev
+Standards-Version: 3.6.2
+
+Package: python-rql
+Architecture: all
+Depends: python (>= 2.3), python (<< 2.4), python2.3-rql (>= ${Source-Version}), python-logilab-common, python-constraint (>= 0.3.0-2)
+Description: relationship query language (RQL) utilities [dummy package]
+ A library providing the base utilities to handle RQL queries,
+ such as a parser, a type inferencer.
+ .
+ This package is an empty dummy package that always depends on a package built
+ for Debian's default Python version.
+
+Package: python-rql-test
+Architecture: all
+Depends: python-rql (>= ${Source-Version}), python-logilab-common
+Description: python-rql's test files
+ This package contains test files shared by the python-rql package. It
+ isn't necessary to install this package unless you want to execute or
+ look at the tests.
+
+Package: python2.3-rql
+Architecture: any
+Depends: python2.3, python-logilab-common, python-constraint (>= 0.3.0-2)
+Description: relationship query language (RQL) utilities [built for python2.3]
+ A library providing the base utilities to handle RQL queries,
+ such as a parser, a type inferencer.
+ .
+ This package is built with Python 2.3.
+
+Package: python2.4-rql
+Architecture: any
+Depends: python2.4, python-logilab-common, python-constraint (>= 0.3.0-2)
+Description: relationship query language (RQL) utilities [built for python2.4]
+ A library providing the base utilities to handle RQL queries,
+ such as a parser, a type inferencer.
+ .
+ This package is built with Python 2.4.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/copyright	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,21 @@
+This package was debianized by Sylvain Thenault <sylvain.thenault@logilab.fr>  Sat, 13 Apr 2002 19:05:23 +0200.
+
+Upstream Author: 
+
+  Sylvain Thenault <devel@logilab.fr>
+
+Copyright:
+
+Copyright (c) 2003-2006 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+
+
+Logilab Closed source License. This code is *NOT* open-source. Usage of this
+code is subject to a licence agreement. If you want to use it, you should
+contact logilab's sales service at commercial@logilab.fr
+
+
+Yapps 2.0 - yet another python parser system
+Amit J Patel, January 1999
+See http://theory.stanford.edu/~amitp/Yapps/ for documentation and updates
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python-rql-test.dirs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2 @@
+usr/share/doc/python-rql
+usr/share/doc/python-rql/test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python-rql.dirs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,1 @@
+usr/share/doc/python-rql
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python-rql.docs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,5 @@
+doc/tutoriel_fr.html
+doc/specifications_fr.html
+doc/tutoriel_fr.txt
+doc/specifications_fr.txt
+doc/canonisation.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.3-rql.dirs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2 @@
+usr/lib/python2.3/site-packages
+usr/lib/python2.3/site-packages/rql
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.3-rql.docs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,5 @@
+doc/tutoriel_fr.html
+doc/specifications_fr.html
+doc/tutoriel_fr.txt
+doc/specifications_fr.txt
+doc/canonisation.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.3-rql.postinst	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,23 @@
+#! /bin/sh -e
+#
+
+
+# precompile python files
+VERSION=2.3
+PACKAGEDIR=/usr/lib/python2.3/site-packages/rql
+case "$1" in
+    configure|abort-upgrade|abort-remove|abort-deconfigure)
+	python$VERSION -O /usr/lib/python$VERSION/compileall.py -q $PACKAGEDIR
+	python$VERSION /usr/lib/python$VERSION/compileall.py -q $PACKAGEDIR
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.3-rql.prerm	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,14 @@
+#! /bin/sh -e
+#
+
+# remove .pyc and .pyo files
+dpkg --listfiles python2.3-rql |
+	awk '$0~/\.py$/ {print $0"c\n" $0"o"}' |
+	xargs rm -f >&2
+
+
+
+#DEBHELPER#
+
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.4-rql.dirs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2 @@
+usr/lib/python2.4/site-packages
+usr/lib/python2.4/site-packages/rql
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.4-rql.docs	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,5 @@
+doc/tutoriel_fr.html
+doc/specifications_fr.html
+doc/tutoriel_fr.txt
+doc/specifications_fr.txt
+doc/canonisation.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.4-rql.postinst	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,23 @@
+#! /bin/sh -e
+#
+
+
+# precompile python files
+VERSION=2.4
+PACKAGEDIR=/usr/lib/python2.4/site-packages/rql
+case "$1" in
+    configure|abort-upgrade|abort-remove|abort-deconfigure)
+	python$VERSION -O /usr/lib/python$VERSION/compileall.py -q $PACKAGEDIR
+	python$VERSION /usr/lib/python$VERSION/compileall.py -q $PACKAGEDIR
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/python2.4-rql.prerm	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,12 @@
+#! /bin/sh -e
+#
+
+# remove .pyc and .pyo files
+dpkg --listfiles python2.4-rql |
+	awk '$0~/\.py$/ {print $0"c\n" $0"o"}' |
+	xargs rm -f >&2
+
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debian/rules	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,87 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+#
+# adapted by Logilab for automatic generation by debianize
+# (part of the devtools project, http://www.logilab.org/projects/devtools)
+#
+# Copyright (c) 2003-2005 LOGILAB S.A. (Paris, FRANCE).
+# http://www.logilab.fr/ -- mailto:contact@logilab.fr
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=4
+
+PYVERSIONS=2.3 2.4
+
+build: build-stamp
+build-stamp: 
+	dh_testdir
+	for v in $(PYVERSIONS) ; do \
+		python$$v setup.py -q build ; \
+	done
+	touch build-stamp
+
+clean: 
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+	rm -rf build
+	find . -name "*.pyc" | xargs rm -f
+	rm -f changelog.gz
+	dh_clean
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs
+	python2.3 setup.py -q install_lib --no-compile --install-dir=debian/python2.3-rql/usr/lib/python2.3/site-packages
+	python2.3 setup.py -q install_headers --install-dir=debian/python2.3-rql/usr/include/
+	# remove test directory (installed in in the doc directory)
+	rm -rf debian/python2.3-rql/usr/lib/python2.3/site-packages/rql/test
+	python2.4 setup.py -q install_lib --no-compile --install-dir=debian/python2.4-rql/usr/lib/python2.4/site-packages
+	python2.4 setup.py -q install_headers --install-dir=debian/python2.4-rql/usr/include/
+	# remove test directory (installed in in the doc directory)
+	rm -rf debian/python2.4-rql/usr/lib/python2.4/site-packages/rql/test
+	# install tests
+	(cd test && find . -type f -not \( -path '*/CVS/*' -or -name '*.pyc' \) -exec install -D --mode=644 {} ../debian/python-rql-test/usr/share/doc/python-rql/test/{} \;)
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+	dh_testdir 
+	dh_testroot 
+	dh_install -i
+	gzip -9 -c ChangeLog > changelog.gz
+	dh_installchangelogs -i
+	dh_installexamples -i
+	dh_installdocs -i README TODO changelog.gz
+	dh_installman -i
+	dh_link -i
+	dh_compress -i -X.py -X.ini -X.xml -Xtest
+	dh_fixperms -i
+	dh_installdeb -i
+	dh_gencontrol -i 
+	dh_md5sums -i
+	dh_builddeb -i
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir 
+	dh_testroot 
+	dh_install -a
+	dh_strip -a
+	dh_link -a
+	dh_compress -a -X.py -X.ini -X.xml -Xtest
+	dh_fixperms -a
+	dh_installdeb -a
+	dh_gencontrol -a
+	dh_md5sums -a
+	dh_builddeb -a
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary binary-indep binary-arch
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/canonisation.txt	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,175 @@
+from ginco.rql.node_lib import Variable
+
+def sort(canon_dict):
+    canon_dict['all_variables'].sort()
+    for l in canon_dict['restriction'].values():
+        l.sort()
+
+-------------------------------------------------------------------------------
+Any N, N2 where N is Note, N2 is Note, N ecrit_par P1, P1 nom 'jphc', N2 ecrit_par P2, P2 nom 'ocy' ;
+Any Y, X  where X is Note, Y is Note,  X ecrit_par P1, P1 nom 'ocy',  Y ecrit_par P2,  P2 nom 'jphc' ;
+
+
+N = Variable('N')
+N2 = Variable('N2')
+P1 = Variable('P1')
+P2 = Variable('P2')
+
+canon1 = {
+ 'all_variables': [N, N2, P1, P2],
+ 'selected' : [N, N2],
+ 'restriction' : {'is' :        [(N, 'Note'), (N2, 'Note')],
+                  'ecrit_par' : [(N, P1), (N2, P2)],
+                  'nom' :       [(P1, 'jphc'), (P2, 'ocy')]
+                 }
+}
+
+N.name  = 'is_Note:ecrit_par:1' # 1 car c'est la première variable séléctionnée
+N2.name = 'is_Note:ecrit_par:2' # deviner pourquoi 2 ...
+P1.name = 'ecrit_par_jphc'
+P2.name = 'ecrit_par_ocy'
+sort(canon1)
+
+Y = Variable('Y')
+X = Variable('X')
+P1 = Variable('P1')
+P2 = Variable('P2')
+
+canon2 = {
+ 'all_variables': [X, Y, P1, P2],
+ 'selected' : [Y, X],
+ 'restriction' : {'is' :        [(X, 'Note'), (Y, 'Note')],
+                  'ecrit_par' : [(X, P1), (Y, P2)],
+                  'nom' :       [(P1, 'ocy'), (P2, 'jphc')]
+                 }
+}
+
+Y.name  = 'is_Note:ecrit_par:1'
+X.name = 'is_Note:ecrit_par:2'
+P1.name = 'ecrit_par_ocy'
+P2.name = 'ecrit_par_jphc'
+sort(canon2)
+
+
+canon2 == canon1
+
+
+
+-------------------------------------------------------------------------------
+Note N WHERE N ecrit_le D, N ecrit_par P, P nom 'jphc', D day > (today-10);
+Note K WHERE K ecrit_le D, K ecrit_par Y, D day > (today-10), Y nom 'jphc';
+
+N = Variable('N')
+D = Variable('D')
+P = Variable('P')
+canon1 = {
+ 'all_variables': [N, D, P],
+ 'selected' : [N],
+ 'restriction' : {'is' :        [(N, 'Note')],
+                  'day':        [(D, '> (today-10)')],
+                  'ecrit_le' :  [(N, D)],
+                  'ecrit_par' : [(N, P)],
+                  'nom' :       [(P, 'jphc')]
+                 }
+}
+N.name = 'is_Note:ecrit_le:ecrit_par:1'
+D.name = 'ecrit_le:day_> (today-10)'
+P.name = 'ecrit_par:nom_jphc'
+sort(canon1)
+
+
+K = Variable('K')
+D = Variable('D')
+Y = Variable('Y')
+canon2 = {
+ 'all_variables': [K, D, Y],
+ 'selected' : [K],
+ 'restriction' : {'is' :        [(K, 'Note')],
+                  'day':        [(D, '> (today-10)')],
+                  'ecrit_le' :  [(K, D)],
+                  'ecrit_par' : [(K, Y)],
+                  'nom' :       [(Y, 'jphc')]
+                 }
+}
+K.name = 'is_Note:ecrit_le:ecrit_par:1'
+D.name = 'ecrit_le:day_> (today-10)'
+Y.name = 'ecrit_par:nom_jphc'
+sort(canon2)
+
+canon1 == canon2
+
+
+
+-------------------------------------------------------------------------------
+Note N WHERE N ecrit_le D, D day > (today -10), N ecrit_par P, P nom 'jphc' or P nom 'ludal';
+Note K WHERE K ecrit_le D, K ecrit_par Y, D day > (today -10), Y nom in ('jphc', 'ludal');
+
+
+N = Variable('N')
+D = Variable('D')
+P = Variable('P')
+canon1 = {
+ 'all_variables': [N, D, P],
+ 'selected' : [N],
+ 'restriction' : {'is' :        [(N, 'Note')],
+                  'day':        [(D, '> (today-10)')],
+                  'ecrit_le' :  [(N, D)],
+                  'ecrit_par' : [(N, P)],
+                  'nom' :       [(P, 'jphc'), (P, 'ludal')]
+                 }
+}
+N.name = 'is_Note:ecrit_le:ecrit_par:1'
+D.name = 'ecrit_le:day_> (today-10)'
+P.name = 'ecrit_par:nom_jphc'
+sort(canon1)
+
+
+K = Variable('K')
+D = Variable('D')
+Y = Variable('Y')
+canon2 = {
+ 'all_variables': [K, D, Y],
+ 'selected' : [K],
+ 'restriction' : {'is' :        [(K, 'Note')],
+                  'day':        [(D, '> (today-10)')],
+                  'ecrit_le' :  [(K, D)],
+                  'ecrit_par' : [(K, Y)],
+                  'nom' :       [(Y, 'jphc'), (Y, 'ludal')]
+                 }
+}
+K.name = 'is_Note:ecrit_le:ecrit_par:1'
+D.name = 'ecrit_le:day_> (today-10)'
+Y.name = 'ecrit_par:nom_jphc'
+sort(canon2)
+
+canon1 == canon2
+
+
+
+
+*******************************************************************************
+NE MARCHE PAS:
+
+* les expressions RQL
+Note N WHERE N ecrit_le D, D day > (today -10), N ecrit_par P, P nom 'jphc' or P nom 'ludal';
+et
+Note N WHERE N ecrit_le D, D day > (today -10), N ecrit_par P, P nom 'jphc', P nom 'ludal';
+
+
+Note N WHERE N ecrit_le D, D day > (today -10), N ecrit_par P, P nom 'jphc' or P prenom 'ludal';
+et
+Note N WHERE N ecrit_le D, D day > (today -10), N ecrit_par P, P nom 'jphc', P prenom 'ludal';
+
+seront considérées comme identiques avec ce modèle.
+
+
+-->
+ 'restriction' : {'is' :        [(K, 'Note')],
+                  'day':        [(D, '> (today-10)')],
+                  'ecrit_le' :  [(K, D)],
+                  'ecrit_par' : [(K, Y)],
+                  'nom_nom' :       [(Y, 'jphc', Y, 'ludal')]
+                 }
+
+* risque de collision dans les noms de variables non sélectionnées (un
+  exemple ?).
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/makefile	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,18 @@
+MKHTML=mkdoc
+MKHTML_OPT=--doctype book --param division.toc.section.depth=1  --target html --stylesheet single-file
+
+SRC=.
+
+
+all: specifications_fr.html tutoriel_fr.html
+
+
+specifications_fr.html: ${SRC}/specifications_fr.txt
+	${MKHTML} ${MKHTML_OPT} ${SRC}/specifications_fr.txt
+
+tutoriel_fr.html :${SRC}/tutoriel_fr.txt
+	${MKHTML} ${MKHTML_OPT} ${SRC}/tutoriel_fr.txt
+
+
+clean:
+	rm -f *.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/specifications_fr.txt	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,491 @@
+=================================================
+Spécification "Relation Query Language" (Hercule)
+=================================================
+
+:Author: Sylvain Thénault
+:Organization: Logilab
+:Version: $Revision: 1.10 $
+:Date: $Date: 2004-05-18 15:04:13 $
+
+.. contents::
+
+
+
+Introduction
+============
+
+Objectifs de RQL
+----------------
+
+L'objectif est d'avoir un langage mettant l'accent sur le parcours de
+relations. A ce titre les attributs seront donc considérés comme des cas
+particuliers de relations (au niveau de l'implémentation, l'utilisateur du
+langage ne devant quasiment pas voir de différence entre un attribut et une
+relation).
+
+
+Comparaison avec des langages existants
+---------------------------------------
+
+SQL
+```
+RQL s'inspire des fonctionnalités de SQL mais se veut à un plus haut niveau
+(l'implémentation actuelle de RQL génère du SQL). Pour cela il se limite au
+parcours de relations et introduit des variables. L'utilisateur n'a pas besoin
+de connaitre le modèle SQL sous-jacent, mais uniquement le schéma Ginco
+définissant l'application.
+
+Versa
+`````
+Faudrait que je regarde plus en détail, mais voilà déja quelques idées pour
+l'instant...  Versa_ est le langage ressemblant le plus à ce que nous voulions
+faire, mais le modèle de donnée sous-jacent étant du RDF, il y a un certain
+nombre de choses tels que les namespaces ou la manipulation des types RDF qui
+ne nous intéressent pas. Niveau fonctionnalité, Versa_ est très complet
+notamment grâce à de nombreuses fonctions de conversion et de manipulations
+des types de base, dont il faudra peut-être s'inspirer à un moment ou à
+l'autre.  Enfin, La syntaxe est un peu ésotérique.
+
+Voir aussi
+``````````
+RDFQL_
+
+
+Les différents types de requêtes
+--------------------------------
+
+Recherche
+  Ce type de requête permet d'extraire des entités ou des attributs d'entités.
+
+Insertion d'entités
+  Ce type de requête permet d'insérer de nouvelles entités dans la base. On
+  permettra également la création directe de relations sur les entités
+  nouvellement créées.
+
+Mise à jour d'entités, création de relations
+  Ce type de requête permet de mettre à jours des entités existantes dans la base,
+  ou de créer des relations entres des entités existantes.
+
+Suppression d'entités ou de relation
+  Ce type de requête permet de supprimer des entités et relations existantes dans
+  la base.
+
+
+
+Exemples
+========
+
+(voir le tutoriel pour plus d'exemples)
+
+Recherche
+---------
+
+- *recherche de l'objet ayant l'identifiant 53*
+  ::
+
+       Any X WHERE 
+       X eid 53 
+
+- *recherche des documents de type bande dessinée, appartenant à syt et disponible*
+  ::
+
+       Document X WHERE 
+       X occurence_of F, F class C, C name 'Bande dessinée',
+       X owned_by U, U login 'syt',
+       X available true
+
+- *recherche des personnes travaillant pour eurocopter intêressé par la formation*
+  ::
+
+       Personne P WHERE
+       P travaille_pour S, S nom 'Eurocopter',
+       P interesse_par T, T nom 'formation'
+
+- *recherche des notes de moins de 10 jours écrite par jphc ou ocy*
+  ::
+
+       Note N WHERE
+       N ecrit_le D, D day > (today -10), 
+       N ecrit_par P, P nom 'jphc' or P nom 'ocy'
+
+- *recherche des personnes interessées par la formation ou habitant à Paris*
+  ::
+
+       Personne P WHERE
+       (P interesse_par T, T nom 'formation') or
+       (P ville 'Paris')
+
+- *Le nom et le prénom de toutes les personnes, triés*
+  ::
+
+       Any N, P WHERE
+       X is 'Personne', X nom N, X prenom P
+
+  On remarquera que la selection de plusieurs entités force généralement
+  l'utilisation de "Any", car la spécification de type s'applique sinon
+  à toutes les variables séléctionnées. On aurait pu écrire ici 
+  ::
+
+       String N, P WHERE
+       X is 'Personne', X nom N, X prenom P
+
+
+Insertion d'entités
+-------------------
+
+- *insertion d'une nouvelle personne nommée 'bidule'*
+  ::
+
+       INSERT Personne X: X nom 'bidule'
+
+- *insertion d'une nouvelle personne nommée 'bidule', d'une autre nommée 'chouette' et d'une relation 'ami' entre eux*
+  ::
+
+       INSERT Personne X, Personne Y: X nom 'bidule', Y nom 'chouette', X ami Y
+
+- *insertion d'une nouvelle personne nommée 'bidule' et d'une relation 'ami' avec une personne existante nommée 'chouette'*
+  ::
+
+       INSERT Person X: X nom 'bidule', X ami Y WHERE Y nom 'chouette'
+
+
+Mise à jour d'entités, création de relations
+--------------------------------------------
+
+- *renommage de la personne nommée 'bidule' en 'toto', avec modification du prénom*
+  ::
+
+       SET X nom 'toto', X prenom 'original' WHERE X is 'Person', X nom 'bidule'
+
+- *insertion d'une relation de type 'connait' entre les objets reliés par la relation de type 'ami'*
+  ::
+
+       SET X know Y WHERE X ami Y
+
+
+Suppression d'entités ou de relations
+-------------------------------------
+
+- *supression de la personne nommé 'toto'*
+  ::
+
+       DELETE Person X WHERE X nom 'toto'
+
+- *suppression de toutes les relations de type 'ami' partant de la personne nommée 'toto'*
+  ::
+
+       DELETE X ami Y WHERE X is 'Person', X nom 'toto'
+
+
+
+Définition du langage
+=====================
+
+Mots clés réservés
+------------------
+Les mots clés ne sont pas sensibles à la casse. 
+
+::
+
+    DISTINCT, INSERT, SET, DELETE,
+    WHERE, AND, OR, NOT
+    IN, LIKE,
+    TRUE, FALSE, NULL, TODAY,
+    GROUPBY, ORDERBY, ASC, DESC
+
+
+Typage
+------
+
+Au niveau de RQL, on ne fait pas de distinction entre entités et attributs. La
+valeur d'un attribut est considérée comme une entité d'un type particulier (voir
+ci-dessous), lié à une (vrai) entité par une relation du nom de l'attribut.
+
+Il existe un type spécial **Any**, revenant à ne pas spécifier de type.
+
+On peut contraindre les types possibles pour une variable à l'aide de la
+relation spéciale **is**.
+
+Le (les) types possible(s) pour chaque variable est déduit du schema en
+fonction des contraintes exprimées ci-dessus et à l'aide des relations entre
+chaque variable.
+
+Types de bases
+``````````````
+
+Les types de bases supportés sont les chaines (entre doubles ou simples quotes),
+les nombres entiers ou flottant (le séparateur étant le '.'), les dates et les
+booleens. On s'attend donc à recevoir un schema dans lequel les types String,
+Int, Float, Date et Boolean sont définis.
+
+
+Opérateurs
+----------
+
+Opérateurs logiques
+```````````````````
+::
+
+    AND, OR, ','
+
+"," est équivalent à "AND" mais avec la plus petite priorité parmi les
+opérateurs logiques (voir `Priorité des opérateurs`_).
+
+Opérateurs mathématiques
+````````````````````````
+::
+
+    +, -, *, /
+
+Opérateurs de comparaison
+`````````````````````````
+::
+
+    <, <=, >=, >, ~=, IN, LIKE
+
+"LIKE" est équivalent à "~="
+
+Priorité des opérateurs
+```````````````````````
+
+1. '*', '/'
+
+2. '+', '-'
+
+3. 'and'
+
+4. 'or'
+
+5. ','
+
+
+Fonctions
+---------
+
+Fonctions d'aggrégat
+````````````````````
+::
+
+    COUNT, MIN, MAX, AVG, SUM
+
+Fonctions sur les chaines
+`````````````````````````
+::
+
+    UPPER, LOWER
+
+
+Grammaire BNF
+-------------
+Les éléments terminaux sont en majuscules, les non-terminaux en minuscule. La
+valeur des éléments terminaux (entre quotes) correspond à une expression
+régulière Python.
+:: 
+
+    statement ::= (select | delete | insert | update) ';'
+
+
+    # select specific rules
+    select ::= 'DISTINCT'? E_TYPE selected_terms restriction? group? sort?
+
+    selected_terms ::= expression (',' expression)*
+
+    group       ::= 'GROUPBY' VARIABLE (',' VARIABLE)*
+
+    sort        ::= 'ORDERBY' sort_term (',' sort_term)*
+
+    sort_term   ::= VARIABLE sort_method? 
+
+    sort_method ::= 'ASC' | 'DESC'
+
+
+    # delete specific rules
+    delete ::= 'DELETE' (variables_declaration | relations_declaration) restriction?
+
+
+    # insert specific rules
+    insert ::= 'INSERT' variables_declaration (':' relations_declaration)? restriction?
+
+
+    # update specific rules
+    update ::= 'SET' relations_declaration restriction
+
+
+    # common rules
+    variables_declaration ::= E_TYPE VARIABLE (',' E_TYPE VARIABLE)*
+
+    relations_declaration ::= simple_relation (',' simple_relation)*
+
+    simple_relation ::= VARIABLE R_TYPE expression
+
+    restriction ::= 'WHERE' relations
+
+    relations   ::= relation (LOGIC_OP relation)*
+                  | '(' relations ')'
+
+    relation ::= 'NOT'? VARIABLE R_TYPE COMP_OP? expression 
+               | 'NOT'? VARIABLE R_TYPE 'IN' '(' expression (',' expression)* ')'
+    
+    expression ::= var_or_func_or_const (MATH_OP var_or_func_or_const)*
+                 | '(' expression ')'
+
+    var_or_func_or_const ::= VARIABLE | function | constant
+
+    function ::= FUNCTION '(' expression (',' expression)* ')'
+
+    constant ::= KEYWORD | STRING | FLOAT | INT
+
+    # tokens
+    LOGIC_OP ::= ',' | 'OR' | 'AND'
+    MATH_OP  ::= '+' | '-' | '/' | '*'
+    COMP_OP  ::= '>' | '>=' | '=' | '<=' | '<' | '~=' | 'LIKE' 
+
+    FUNCTION ::= 'MIN' | 'MAX' | 'SUM' | 'AVG' | 'COUNT' | 'UPPER' | 'LOWER'
+
+    VARIABLE ::= '[A-Z][A-Z0-9]*'
+    E_TYPE   ::= '[A-Z]\w*'
+    R_TYPE   ::= '[a-z_]+'
+
+    KEYWORD  ::= 'TRUE' | 'FALSE' | 'NULL' | 'TODAY'
+    STRING   ::= "'([^'\]|\\.)*'" | '"([^\"]|\\.)*\"'
+    FLOAT    ::= '\d+\.\d*'
+    INT      ::= '\d+'
+
+
+Remarques
+---------
+
+Tri et groupes
+``````````````
+
+- pour les requêtes groupées (i.e. avec une clause GROUPBY), toutes les
+  variables sélectionnée doivent être groupées
+
+- pour les requête ordonnées (i.e. avec une clause ORDERBY), toutes les
+  variables ordonnéees doivent être sélectionnées
+
+- pour grouper ou/et trier sur les attributs on peut faire : "X,L user U, U
+  login L GROUPBY L,X ORDERBY L"
+
+- si la méthode de tri (SORT_METHOD) n'est pas précisé, alors le tri est
+  ascendant.
+
+Négation
+````````
+
+une requête du type "Document X where not X owned_by U" revient à dire "les
+documents n'ayant pas de relation 'owned_by'". La variable U ne doit être
+utilisée à aucun autre endroit.
+
+
+
+Implémentation
+==============
+
+Représentation interne (arbre syntaxique)
+-----------------------------------------
+
+L'arbre de recherche ne contient pas les variables sélectionnées (i.e. on n'y 
+trouve que ce qui suit le "WHERE").
+
+L'arbre d'insertion ne contient pas les variables insérée ni les relations 
+définies sur ces variables (i.e. on n'y trouve que ce qui suit le
+"WHERE").
+
+L'arbre de suppression ne contient pas les variables ou relations supprimées 
+(i.e. on n'y trouve que ce qui suit le "WHERE").
+
+L'arbre de màj ne contient pas les variables ou relations mises à jour
+(i.e. on n'y trouve que ce qui suit le "WHERE").
+
+::
+
+    Select         ((Relation|And|Or)?, Group?, Sort?)
+    Insert         (Relation|And|Or)?
+    Delete         (Relation|And|Or)?
+    Update         (Relation|And|Or)?
+
+    And            ((Relation|And|Or), (Relation|And|Or))
+    Or             ((Relation|And|Or), (Relation|And|Or))
+
+    Relation       ((VariableRef, Comparison))
+
+    Comparison     ((Function|MathExpression|Keyword|Constant|VariableRef)+)
+
+    Function       (())
+    MathExpression ((MathExpression|Keyword|Constant|VariableRef), (MathExpression|Keyword|Constant|VariableRef))
+
+    Group          (VariableRef+)
+    Sort           (SortTerm+)
+    SortTerm       (VariableRef+)
+
+    VariableRef ()
+    Variable    ()
+    Keyword     ()
+    Constant    ()
+
+
+Remarques
+---------
+
+- l'implémentation actuelle ne supporte pas de lier deux relations ayant comme
+  type de relation 'is' avec un OR. Je ne pense pas que la négation ne
+  soit supportée non plus sur ce type de relation (à confirmer).
+
+- les relations définissant les variables doivent être à gauche de celles les
+  utilisant. Par exemple ::
+
+    Point P where P abs X, P ord Y, P value X+Y
+
+  est valide, mais ::
+
+    Point P where P abs X, P value X+Y, P ord Y
+
+  ne l'est pas.
+
+
+
+Conclusion
+==========
+
+Limitations
+-----------
+
+Il manque pour l'instant:
+
+- COALESCE
+
+- restriction sur les groupes (HAVING)
+
+et certainement d'autres choses...
+
+Un inconvénient est que pour utiliser ce langage il faut bien connaitre le
+schema utilisé (avec les vrais noms de relations et d'entités, pas ceux affichés
+dans l'interface utilisateur). D'un autre coté, on peut pas vraiment contourner
+cela, et c'est le boulot d'une interface utilisateur de caché le RQL.
+
+
+A réfléchir
+-----------
+
+Il serait pratique de pouvoir exprimer dans le schema des correspondances de
+relations::
+
+    Document class Type <-> Document occurence_of Fiche class Type
+    Fiche class Type    <-> Fiche collection Collection class Type
+    
+Ainsi 1. devient::
+
+    Document X where 
+    X class C, C name 'Bande dessinée',
+    X owned_by U, U login 'syt',
+    X available true
+
+Je ne suis cependant pas sûr qu'il faille gérer ça au niveau de RQL...
+
+Il faudrait aussi une relation spéciale 'anonyme'.
+
+
+
+.. _Versa: http://uche.ogbuji.net/tech/rdf/versa/
+.. _RDFQL: http://www.w3.org/TandS/QL/QL98/pp/rdfquery.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutoriel_fr.txt	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,240 @@
+============================================
+Tutoriel "Relation Query Language" (Hercule)
+============================================
+
+
+Apprenons RQL par la pratique...
+
+
+
+Schema
+------
+Nous supposerons dans la suite de ce document que le schéma de
+l'application Ginco est le suivant. Les différentes entités
+disponibles sont :
+
+:Personne:
+
+::
+
+	nom    varchar(64) NOT NULL
+	prenom varchar(64)
+	sexe   char(1) DEFAULT 'M' 
+	promo  choice('bon','pasbon')
+	titre  varchar(128)
+	adel   varchar(128)
+	web    varchar(128)
+	tel    integer
+	datenaiss date
+
+
+:Societe:
+
+::
+
+	nom  varchar(64)
+	web varchar(128)
+	tel  varchar(15)
+	adr  varchar(128)
+	cp   varchar(12)
+	ville varchar(32)
+
+
+:Affaire:
+
+::
+
+	sujet varchar(128)
+	ref   varchar(12) 
+
+
+:Note:
+
+::
+
+	diem date
+	type char(1)
+	para varchar(512)
+
+
+Et les relations entre elles:
+
+::
+
+	Person travaille_pour Societe
+	Person evaluee_par Note
+	Societe evaluee_par Note
+	Person concerne_par Note
+	Person concerne_par Affaire
+	Societe concerne_par Affaire
+
+
+Toutes les entités ont un attribut supplémentaire 'eid', permettant
+d'identifier chaque instance de manière unique.
+
+De plus si les métadonnées sont utilisées, vous disposez pour chaque
+type d'entité des relations "creation_date", "modification_date" dont
+l'objet est une entité de type Dates (il y a un "s" pour ne pas avoir
+de conflit avec le type de base "date"), ainsi que de la relation
+"owned_by" dont l'objet est une entité de type Ginco_user. Les schemas
+standards de ces types d'entités sont les suivants :
+
+:Dates:
+
+::
+
+	day date
+
+
+:Ginco_user:
+
+::
+
+	login  	  varchar(64) not null
+	firstname varchar(64)
+	surname   varchar(64)
+	password  password
+	role      choice('admin','user','anonymous') default 'user'
+	email  	  varchar(128)
+	web    	  varchar(128)
+	birthday  date
+
+Enfin, il existe la relation spéciale "is" permettant de spécifier le
+type d'une variable. 
+
+
+L'essentiel
+-----------
+.0 *Toutes les personnes*
+
+::
+   
+   Personne X ;
+   ou
+   Any X WHERE X is 'Personne' ;
+
+
+.1 *La societé nommé Logilab*
+
+::
+
+   Societe S WHERE S nom 'Logilab' ;
+
+
+.2 *Tous les objets ayant un attribut nom commençant par 'Log'*
+
+::
+
+   Any S WHERE S nom LIKE 'Log%' ;
+   ou 
+   Any S WHERE S nom ~= 'Log%' ;
+
+Cette requête peut renvoyer des objets de type personne et de type
+société.
+
+
+.3 *Toutes les personnes travaillant pour la société nommé Logilab*
+   
+::
+   Personne P WHERE P travaille_pour S, S nom "Logilab" ;
+   ou
+   Personne P WHERE P travaille_pour S AND S nom "Logilab" ;
+   ou
+   Personne P WHERE P travaille_pour "Logilab" ;
+
+La dernière forme fonctionne car "nom" est le premier attribut des
+entités de type "Société"
+
+
+.4 *Les societés nommées Caesium ou Logilab*
+
+::
+
+   Societe S WHERE S nom IN ('Logilab','Caesium') ;
+   ou
+   Societe S WHERE S nom 'Logilab' OR S nom 'Caesium' ;
+
+
+.5 *Toutes les societés sauf celles nommées Caesium ou Logilab*
+
+::
+
+   Societe S WHERE NOT S nom IN ('Logilab','Caesium') ;
+   ou
+   Societe S WHERE NOT S nom 'Logilab' AND NOT S nom 'Caesium' ;
+
+
+.6 *Les objets évalués par la note d'identifiant 43*
+
+::
+
+   Any X WHERE X evaluee_par N, N eid 43 ;
+
+
+.7 *Toutes les personnes triés par date de naissance dans l'ordre antechronologique*
+
+::
+   
+   Personne D,X WHERE X datenaiss D ORDERBY D DESC ;
+
+On note qu'il faut définir une variable et la séléctionner pour s'en
+servir pour le tri. 
+
+
+.8 *Toutes les personnes groupées par leur société*
+
+::
+   
+   Personne X WHERE X travaille_pour S GROUPBY S,X ;
+
+On note qu'il faut définir une variable pour s'en servir pour le
+groupage. De plus les variables séléctionnée doivent être groupée
+(mais les variables groupées ne doivent pas forcément être sélectionnées).
+
+
+   
+Exemples avancés
+----------------
+.0 *Toutes les personnes dont le champ nom n'est pas spécifié (i.e NULL)*
+
+::
+
+   Personne P WHERE P nom NULL ;
+
+
+.1 *Toutes les personnes ne travaillant pour aucune société*
+
+::
+
+   Personne P WHERE NOT p travaille_pour S ;
+
+
+.2 *Toutes les sociétés où la personne nommée toto ne travaille pas*
+
+::
+
+   Societe S WHERE NOT P travaille_pour S , P nom 'toto' ;
+   ou
+   Societe S WHERE NOT 'toto' travaille_pour S ;
+
+
+.3 *Toutes les entités ayant été modifiées entre aujourd'hui et hier*
+
+::
+
+   Any X WHERE X modification_date <= today, X modification_date >= today - 1
+
+
+.4 *Toutes les notes n'ayant pas de type et à effectuer dans les 7 jours, triées par date*
+
+::
+
+   Any N, D where N is "Note", N type NULL, N diem D, N diem >= today,
+   N diem < today + 7 ORDERBY D
+
+
+.5 *Les personnes ayant un homonyme (sans doublons)*
+
+::
+
+   Personne X,Y where X nom NX, Y nom NX, X eid XE, Y eid > XE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/editextensions.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,308 @@
+"""some rql extensions for manipulating syntax trees
+
+Copyright (c) 2004-2006 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: editextensions.py,v 1.12 2006-05-02 12:25:39 syt Exp $"
+
+from rql.stmts import Select
+from rql.nodes import Constant, Variable, VariableRef, Comparison, AND, \
+     Sort, SortTerm, Relation
+from rql.utils import get_nodes
+from rql.undo import *
+
+orig_init = Select.__init__
+def __init__(self, *args, **kwargs):
+    """override Select.__init__ to add an undo manager and others necessary
+    variables
+    """
+    orig_init(self, *args, **kwargs)
+    self.undo_manager = SelectionManager(self)
+    self.memorizing = 0
+    # used to prevent from memorizing when undoing !
+    self.undoing = False
+Select.__init__ = __init__
+
+def save_state(self):
+    """save the current tree"""
+    self.undo_manager.push_state()
+    self.memorizing += 1
+Select.save_state = save_state
+
+def recover(self):
+    """reverts the tree as it was when save_state() was last called"""
+    self.memorizing -= 1
+    assert self.memorizing >= 0
+    self.undo_manager.recover()    
+Select.recover = recover
+
+            
+# variable manipulation methods ###############################################
+
+orig_make_variable = Select.make_variable
+def make_variable(self, e_type=None):
+    """override Select.make_variable to memorize variable creation"""
+    var = orig_make_variable(self, e_type)
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(MakeVarOperation(var))
+    return var
+Select.make_variable = make_variable
+
+def undefine_variable(self, var):
+    """undefine the given variable and remove all relations where it appears"""
+    check_relations(self)
+    if hasattr(var, 'variable'):
+        var = var.variable
+    # remove relations where this variable is referenced
+    for varref in var.references():
+        rel = varref.relation()
+        if rel is not None:
+            self.remove_node(rel)
+            continue
+        if varref.parent is None: # selected variable
+            self.remove_selected(varref)
+        elif varref.parent.TYPE == 'sortterm':
+            self.remove_sort_term(varref.parent)
+        elif varref.parent.TYPE == 'group':
+            self.remove_group_variable(varref)
+        else:
+            self.remove_node(varref)
+    # effective undefine operation
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(UndefineVarOperation(var))
+    del self.defined_vars[var.name]
+    check_relations(self)
+Select.undefine_variable =  undefine_variable
+
+def remove_selected(self, var):
+    """deletes var from selection variable"""
+    # XXX it may be a function
+    #assert isinstance(var, VariableRef)
+    index = var_index(self.selected, var)
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(UnselectVarOperation(var, index))
+    var = self.selected.pop(index)
+    var.unregister_reference()
+    check_relations(self)
+Select.remove_selected = remove_selected
+
+def add_selected(self, var, index=None):
+    """override Select.add_selected to memoize modification when needed"""
+    var = variable_ref(var)
+    var.register_reference()
+    if index is not None:
+        self.selected.insert(index, var)
+    else:
+        self.selected.append(var)
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(SelectVarOperation(var))
+    check_relations(self)
+Select.add_selected = add_selected
+
+# basic operations #############################################################
+
+def add_restriction(self, relation):
+    """override Select.add_restriction to memorize modification when needed"""
+    assert isinstance(relation, Relation)
+    r = self.get_restriction()
+    if r is not None:
+        new_node = AND(relation, r)
+        self.replace(r, new_node)
+        if self.memorizing and not self.undoing:
+            self.undo_manager.add_operation(ReplaceNodeOperation(r, new_node))
+    else:
+        self.insert(0, relation)
+        if self.memorizing and not self.undoing:
+            self.undo_manager.add_operation(AddNodeOperation(relation))
+    # register variable references in the added subtree
+    for varref in get_nodes(relation, VariableRef):
+        varref.register_reference()
+    check_relations(self)
+Select.add_restriction = add_restriction
+
+def remove_node(self, node):
+    """remove the given node from the tree"""
+    # unregister variable references in the removed subtree
+    for varref in get_nodes(node, VariableRef):
+        varref.unregister_reference()
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(RemoveNodeOperation(node))
+    node.parent.remove(node)
+    check_relations(self)
+Select.remove_node = remove_node
+
+def add_sortvar(self, var, asc=True):
+    """add var in 'orderby' constraints
+    asc is a boolean indicating the sort order (ascendent or descendent)
+    """
+    var = variable_ref(var)
+    var.register_reference()
+    term = SortTerm(var, asc)
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(AddSortOperation(term))
+    sort_terms = self.get_sortterms()
+    if sort_terms is None:
+        sort_terms = Sort()
+        self.append(sort_terms)
+    sort_terms.append(term)
+Select.add_sortvar = add_sortvar
+
+def set_distinct(self, value):
+    """mark DISTINCT query"""
+    if self.memorizing and not self.undoing:
+        self.undo_manager.add_operation(SetDistinctOperation(self.distinct))
+    self.distinct = value
+    
+Select.set_distinct = set_distinct
+
+# shortcus methods ############################################################
+def remove_sort_terms(self):
+    """remove a sort term and the sort node if necessary"""
+    sortterms = self.get_sortterms()
+    if sortterms:
+        self.remove_node(sortterms)
+Select.remove_sort_terms = remove_sort_terms
+
+def remove_sort_term(self, term):
+    """remove a sort term and the sort node if necessary"""
+    sortterms = self.get_sortterms()
+    assert term in sortterms
+    if len(sortterms) == 1:
+        self.remove_node(sortterms)
+    else:
+        self.remove_node(term)        
+Select.remove_sort_term = remove_sort_term
+
+def remove_group_variable(self, var):
+    """remove the group variable and the group node if necessary"""
+    groups = self.get_groups()
+    assert var in groups
+    if len(groups) == 1:
+        self.remove_node(groups)
+    else:
+        self.remove_node(var)
+Select.remove_group_variable = remove_group_variable
+
+def add_eid_restriction(self, var, eid): 
+    """builds a restriction node to express '<var> eid <eid>'"""
+    self.add_restriction(make_relation(var, 'eid', (eid, 'Int'), Constant))
+Select.add_eid_restriction = add_eid_restriction
+
+def add_constant_restriction(self, var, r_type, value, v_type=None): 
+    """builds a restriction node to express '<var> <r_type><constant value>'"""
+    if v_type is None:
+        if isinstance(value, int):
+            v_type = 'Int'
+        # FIXME : other cases
+        else:
+            v_type = 'String'
+    self.add_restriction(make_relation(var, r_type, (value, v_type), Constant))
+Select.add_constant_restriction = add_constant_restriction
+
+def add_relation(self, lhs_var, r_type, rhs_var): 
+    """builds a restriction node to express '<var> eid <eid>'"""
+    self.add_restriction(make_relation(lhs_var, r_type, (rhs_var, 1),
+                                       VariableRef))
+Select.add_relation = add_relation
+
+
+# utilities functions #########################################################
+
+def make_relation(var, rel, rhs_args, rhs_class):
+    """build an relation equivalent to '<var> rel = <cst>'"""
+    comp_cst = Comparison("=")
+    comp_cst.append(rhs_class(*rhs_args))
+    exp = Relation(rel)
+    if hasattr(var, 'variable'):
+        var = var.variable
+    exp.append(VariableRef(var, noautoref=1))
+    exp.append(comp_cst)
+    return exp
+
+def switch_selection(rqlst, new_var, old_var):
+    """the select variable switch from old_var (VariableRef instance) to
+    new_var (Variable instance)
+    """
+    rqlst.remove_selected(old_var)
+    rqlst.add_selected(new_var, 0)
+
+def add_main_restriction(rqlst, new_type, r_type, direction):
+    """the result_tree must represent the same restriction as 'rqlst', plus :
+       - 'new_varname' IS <new_type>
+       - 'old_main_var' <r_type> 'new_varname' 
+    """
+    new_var = rqlst.make_variable(new_type)
+    # new_var IS new_type
+    rqlst.add_restriction(make_relation(new_var, 'is', (new_type, 'etype'),
+                                        Constant))
+    # new_var REL old_var (ou l'inverse)
+    old_var = rqlst.selected[0]
+    if direction == 'subject':
+        rel_rest = make_relation(old_var.variable, r_type, (new_var, 1),
+                                 VariableRef)
+    else:
+        rel_rest = make_relation(new_var, r_type, (old_var.variable, 1),
+                                 VariableRef)
+    rqlst.add_restriction(rel_rest)
+    return new_var
+
+
+def remove_has_text_relation(node):
+    """remove has_text relation"""
+    for rel in get_nodes(node, Relation):
+        if rel.r_type == 'has_text':
+            node.remove_node(rel)
+            return
+        
+def get_variable_refs(node):
+    """get the list of variable references in the subtree """
+    return get_nodes(node, VariableRef)
+
+def get_relations(node):
+    """returns a list of the Relation nodes of the subtree"""
+    return get_nodes(node, Relation)
+
+def get_vars_relations(node):
+    """returns a dict with 'var_names' as keys, and the list of relations which
+    concern them
+    """
+    exp_concerns = {}
+    for exp in get_relations(node):
+        for vref in get_variable_refs(exp):
+            exp_concerns.setdefault(vref.name, []).append(exp)
+    return exp_concerns
+
+def variable_ref(var):
+    """get a VariableRef"""
+    if isinstance(var, Variable):
+        return VariableRef(var, noautoref=1)
+    assert isinstance(var, VariableRef)
+    return var    
+
+def var_index(list, var):
+    """get variable index in the list using identity (Variable and VariableRef
+    define __cmp__
+    """
+    for i in xrange(len(list)):
+        if list[i] is var:
+            return i
+    raise IndexError()
+
+def check_relations(node):
+    """test function"""
+    varrefs = get_nodes(node, VariableRef) + list(node.get_selected_variables())
+    for n in getattr(node, 'main_relations', ()):
+        varrefs += get_nodes(n, VariableRef)
+    refs = {}
+    for var in node.defined_vars.values():
+        for varref in var.references():
+            # be careful, Variable and VariableRef define __cmp__
+            if not [v for v in varrefs if v is varref]:
+                raise AssertionError('buggy reference %r in %r (actual var: %r)' %
+                                         (varref, node, var))
+            refs[id(varref)] = 1
+    for varref in varrefs:
+        if not refs.has_key(id(varref)):
+            raise AssertionError('unreferenced varref %r' % varref)
+    return True
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fol.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,248 @@
+
+
+"""
+x in (A,B,C,D)
+y in (A,B,C)
+(x == A and y == B) or (x == B and y == C)
+
+sols = (v1:Set1,v2:Set2,...)
+
+sola(v1,v2) | solb(v2,v3) = (v1:Set1,v2:Set2a|Set2b,v3:Set3)
+sola(v1,v2) & solb(v2,v3) = (v1:Set1,v2:Set2a&Set2b,v3:Set3)
+
+
+
+N1 or N2 : sols = [ s1 for s1 in N1.sols() ] + [ s2 for s2 in N2.sols() ]
+
+N1 and N2 : sols = [ s1&s2 for s1 in N1.sols() for s2 in N2.sols() if s1&s2 not empty ]
+
+V in Set : sols = (V:Set)
+
+"""
+
+def intersect_sol( s1, s2 ):
+    sol = s1.copy()
+    sol.update(s2)
+    
+    for n,v in s1.items():
+        if sol[n]!=v:
+            return {}
+    return sol
+
+def empty_sol( s ):
+    for set in s.values():
+        if not set:
+            return False
+
+
+class SolBase(object):
+    def and_sols(self, sols1, sols2 ):
+        sols = []
+        for s1 in sols1:
+            for s2 in sols2:
+                s = intersect_sol(s1,s2)
+                if s:
+                    sols.append( s )
+        return sols
+
+    def or_sols(self, sols1, sols2 ):
+        sols = sols1[:]
+        for s in sols2:
+            if s not in sols:
+                sols.append(s)
+        return sols
+        
+
+    def __and__(self, x ):
+        return SolAnd(self,x)
+
+    def __or__(self, x):
+        return SolOr(self,x)
+
+    def __invert__(self):
+        return SolNot(self)
+
+    def __call__(self,domains):
+        return self.sols(domains)
+
+
+    def variables(self, upd=None):
+        """Returns a dict whose keys are variables used
+        by this formula. if upd is provided it is used
+        instead of an empty dict and it keeps already existing
+        variables intact"""
+        raise NotImplementedError
+
+class SolNot(SolBase):
+    def __init__(self,s):
+        self.sol = s
+
+    def sols(self,domains):
+        return self.sol.not_sols(domains)
+
+
+    def __str__(self):
+        return "not ("+str(self.sol)+")"
+
+    def variables(self, upd=None):
+        return self.sol.variables(upd)
+
+import bisect
+
+class SolAnd(SolBase):
+    def __init__(self, s1, s2 ):
+        self.sol = []
+        self.cost= []
+        # optimize (a and b) and c into and(a,b,c)
+        if isinstance(s1,SolAnd):
+            for s in s1.sol:
+                self.insert( s )
+        else:
+            self.insert(s1)
+        # optimize a and (b and c) into and(a,b,c)
+        if isinstance(s2,SolAnd):
+            for s in s2.sol:
+                self.insert( s )
+        else:
+            self.insert(s2)
+
+    def insert(self,sol):
+        N = len(sol.variables())
+        idx = bisect.bisect_left(self.cost,N)
+        self.cost.insert(idx, N)
+        self.sol.insert(idx, sol)
+        
+    def sols(self,domains):
+        sols = self.sol[0](domains)
+        for s in self.sol[1:]:
+#            domains = restrain(domains,sols)
+            S = s(domains)
+            sols = self.and_sols( sols, S )
+        return sols
+
+    def not_sols(self,domains):
+        sols1 = self.s1.not_sols(domains)
+        sols2 = self.s2.not_sols(domains)
+        return self.or_sols(sols1,sols2)
+
+    def __str__(self):
+        rsols = [str(s) for s in self.sol ]
+        return "(" + " and ".join(rsols) + ")"
+
+    def variables(self, upd=None):
+        if upd is None:
+            upd = {}
+        for s in self.sol:
+            s.variables(upd)
+        return upd
+
+class SolOr(SolBase):
+    def __init__(self, s1, s2 ):
+        self.s1 = s1
+        self.s2 = s2
+
+    def sols(self,domains):
+        sols1 = self.s1.sols(domains)
+        sols2 = self.s2.sols(domains)
+        return self.or_sols( sols1, sols2 )
+
+    def not_sols(self,domains):
+        sols1 = self.s1.not_sols(domains)
+        sols2 = self.s2.not_sols(domains)
+        return self.and_sols(sols1,sols2)
+
+    def __str__(self):
+        return "(" + str(self.s1) + " or " + str(self.s2) + ")"
+
+    def variables(self, upd=None):
+        if upd is None:
+            upd = {}
+        for s in (self.s1,self.s2):
+            s.variables(upd)
+        return upd
+
+class SolRelation(SolBase):
+    """Boolean relation between variables"""
+    def __init__(self, *variables):
+        self._variables = list(variables)
+
+    def variables(self, upd=None):
+        if upd is None:
+            upd = {}
+        for v in self._variables:
+            upd[v.var] = 0
+        return upd
+
+
+class SolVar(SolRelation):
+    """Simple unary relation True if var in set"""
+    def __init__(self,V,s):
+        self.var = V
+        self.set = s
+
+    def variables(self, upd=None):
+        if upd is None:
+            upd = {}
+        upd[self.var] = 0
+        return upd
+
+    def sols(self,domains):        
+        return [ { self.var : v } for v in self.set if v in domains[self.var] ]
+
+    def not_sols(self,domains):
+        return [ { self.var : v } for v in domains[self.var] if v not in self.set ]
+
+    def __str__(self):
+        return str(self.var) + " in " + str(self.set)
+
+    def __eq__(self,v):
+        return SolEq(self, v)
+
+class SolEq(SolRelation):
+    """Simple equality between variables"""
+    def sols(self,domains):
+        d = {}
+        # intersect domains
+        for var in self._variables:
+            for sol in var.sols(domains):
+                for v, val in sol.items():
+                    c = d.setdefault(val,0)
+                    d[val]=c+1
+        count = len(self._variables)
+        result = []
+        for k,v in d.items():
+            if v==count:
+                r = {}
+                for var in self._variables:
+                    r[var.var] = k
+                result.append( r )
+        return result
+
+    def not_sols(self,domains):
+        raise NotImplementedError
+    
+    def __str__(self):
+        return "==".join( [v.var for v in self._variables] )
+    
+    def __eq__(self,v):
+        if isinstance(v, SolVar):
+            self._variables.append(v)
+        elif isinstance(v, SolEq):
+            self._variables+=v._variables
+        else:
+            raise RuntimeError("Invalid model")
+        return self
+        
+if __name__ == "__main__":
+    D = {
+        'x' : range(5),
+        'y' : range(6),
+        'z' : range(4)
+        }
+    X = SolVar('x', [1,2,3] )
+    Y = SolVar('y', [4,5,6] )
+    Z = SolVar('z', [2,3] )
+    w0 = (X & Y) | Z
+    w1 = X & Y & ( X==Z )
+    print w0, w0.sols(D)
+    print w1, w1.sols(D)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interfaces.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,67 @@
+"""interfaces used by the rql package
+
+ Copyright (c) 2003-2004 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = '$Id: interfaces.py,v 1.7 2004-03-11 13:54:32 syt Exp $'
+
+from logilab.common.interface import Interface
+
+class ISchema(Interface):
+    """RQL expects some base types to exists: String, Float, Int, Boolean, Date
+    and a base relation : is
+    """
+    
+    def has_entity(self, e_type):
+        """return true if the given type is defined in the schema
+        """
+        
+    def has_relation(self, r_type):
+        """return true if the given relation's type is defined in the schema
+        """
+    
+    def entities(self, schema=None):
+        """return the list of possible types
+        
+        If schema is not None, return a list of schemas instead of types.
+        """
+
+    def relations(self, schema=None):
+        """return the list of possible relations
+        
+        If schema is not None, return a list of schemas instead of relation's
+        types.
+        """
+
+    def relation_schema(self, r_type):
+        """return the relation schema for the given relation type
+        """
+        
+
+class IRelationSchema(Interface):
+    """interface for Relation schema (a relation is a named oriented link
+    between two entities)
+    """
+    def association_types(self):
+        """return a list of (from_type, [to_types]) defining between which types
+        this relation may exists
+        """
+        
+    def subject_types(self):
+        """return a list of types which can be subject of this relation
+        """
+        
+    def object_types(self):
+        """return a list of types which can be object of this relation
+        """
+
+class IEntitySchema(Interface):
+    """interface for Entity schema
+    """
+    
+    def is_final(self):
+        """return true if the entity is a final entity (ie cannot be used
+        as subject of a relation)
+        """
+        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,8 @@
+YAPPS=python thirdparty/yapps2.py
+
+parser.py: parser.g parser_main.py
+	${YAPPS} parser.g
+	sed "s/from yappsrt import/from thirdparty.yappsrt import/" parser.py > tmp.py
+	sed "s/__main__/old__main__/" tmp.py > parser.py
+	rm tmp.py
+	cat parser_main.py >> parser.py
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nodes.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,561 @@
+"""Copyright (c) 2004-2006 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+ 
+This module defines all the nodes we can find in a RQL Syntax tree, except
+root nodes, defined in the stmts module.
+"""
+
+__revision__ = "$Id: nodes.py,v 1.33 2006-05-02 12:25:39 syt Exp $"
+
+from logilab.common import cached
+from logilab.common.tree import VNode as Node, BinaryNode, ListNode, \
+     post_order_list
+from logilab.common.visitor import VisitedMixIn
+
+from rql.utils import F_TYPES, quote, uquote
+
+def get_visit_name(self):
+    """
+    return the visit name for the mixed class. When calling 'accept', the
+    method <'visit_' + name returned by this method> will be called on the
+    visitor
+    """
+    return self.__class__.__name__.lower()
+Node.get_visit_name = get_visit_name
+BinaryNode.get_visit_name = get_visit_name
+ListNode.get_visit_name = get_visit_name
+
+# base objects ################################################################
+
+class HSMixin(object):
+    """mixin class for classes which may be the lhs or rhs of an expression
+    """    
+    def relation(self):
+        """return the parent relation where self occurs or None"""
+        parent = self.parent
+        while parent is not None and not parent.TYPE == 'relation':
+            parent = parent.parent
+        return parent
+    #relation = cached(relation)
+    
+    def is_variable(self):
+        """check if this node contains a reference to one ore more variables"""
+        for c in post_order_list(self):
+            if isinstance(c, VariableRef):
+                return 1
+        return 0
+    
+    def __str__(self):
+        return self.as_string(None)
+
+
+# add a new "copy" method to the Node base class
+def deepcopy(self, stmt):
+    """create and return a copy of this node and its descendant
+
+    stmt is the root node, which should be use to get new variables
+    """
+    new = self.__class__(*self.initargs(stmt))
+    for child in self.children:
+        new.append(child.copy(stmt))
+    return new
+Node.copy = deepcopy
+
+def initargs(self, stmt):
+    """return list of arguments to give to __init__ to clone this node
+    
+    I don't use __getinitargs__ because I'm not sure it should interfer with
+    copy/pickle
+    """
+    return ()
+Node.initargs = initargs
+
+# RQL base nodes ##############################################################
+
+
+class AND(BinaryNode):
+    """a logical AND node (binary)
+    """
+    TYPE = 'and'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_and( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_and( self, *args, **kwargs )
+    
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return '%s, %s' % (self.children[0].as_string(encoding),
+                           self.children[1].as_string(encoding))
+    def __repr__(self):
+        return '%s AND %s' % (repr(self.children[0]),
+                             repr(self.children[1]))
+
+    
+class OR(BinaryNode):
+    """a logical OR node (binary)
+    """
+    TYPE = 'or'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_or( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_or( self, *args, **kwargs )
+    
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return '%s OR %s' % (self.children[0].as_string(encoding),
+                             self.children[1].as_string(encoding))
+    def __repr__(self):
+        return '%s OR %s' % (repr(self.children[0]),
+                             repr(self.children[1]))
+
+    
+class Relation(Node):
+    """a single RQL relation
+    """
+    TYPE = 'relation'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_relation( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_relation( self, *args, **kwargs )
+    
+    def __init__(self, r_type, _not=0):
+        Node.__init__(self)
+        self.r_type = r_type.encode()
+        self._not = _not
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return self.r_type, self._not
+    
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        try:
+            if not self._not:
+                return '%s %s %s' % (self.children[0].as_string(encoding),
+                                     self.r_type,
+                                     self.children[1].as_string(encoding))
+            return 'not %s %s %s' % (self.children[0].as_string(encoding),
+                                     self.r_type,
+                                     self.children[1].as_string(encoding))
+        except IndexError:
+            return repr(self)
+
+    def __repr__(self, indent=0):
+        try:
+            if not self._not:
+                return '%sRelation(%r %s %r)' % (' '*indent, self.children[0],
+                                                 self.r_type, self.children[1])
+            return '%sRelation(not %r %s %r)' % (' '*indent, self.children[0],
+                                                 self.r_type, self.children[1])
+        except IndexError:
+            return '%sRelation(%s)' % (' '*indent, self.r_type)
+            
+    def __str__(self):
+        return self.as_string('ascii')
+            
+       
+    def get_parts(self):
+        """return the left hand side and the right hand side of this relation
+        """
+        lhs = self.children[0]
+        rhs = self.children[1]
+        return lhs, rhs
+
+    def get_variable_parts(self):
+        """return the left hand side and the right hand side of this relation,
+        ignoring comparison
+        """
+        lhs = self.children[0]
+        rhs = self.children[1].children[0]
+        return lhs, rhs
+
+    
+class Comparison(HSMixin, Node):
+    """handle comparisons:
+
+     <, <=, =, >=, > and LIKE operator have a unique children.    
+    """
+    TYPE = 'comparison'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_comparison( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_comparison( self, *args, **kwargs )
+
+    def __init__(self, operator, value=None):
+        Node.__init__(self)
+        if operator == '~=':
+            operator = 'LIKE'
+        elif operator == '=' and isinstance(value, Constant) and \
+                 value.type is None:
+            operator = 'IS'            
+        assert operator in ('<', '<=', '=', '>=', '>', 'LIKE', 'IS')
+        self.operator = operator
+        if value is not None:
+            self.append(value)
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (self.operator,)
+    
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        if len(self.children)==0:
+            return self.operator
+        if self.operator in ('=', 'IS'):
+            return self.children[0].as_string(encoding)
+        else:
+            return '%s %s' % (self.operator.encode(),
+                              self.children[0].as_string(encoding))
+
+    def __repr__(self, indent=0):
+        return '%s%s %s' % (' '*indent, self.operator,
+                            ', '.join([repr(c) for c in self.children]))
+
+    
+
+class MathExpression(HSMixin, BinaryNode):
+    """+, -, *, /
+    """
+    TYPE = 'mathexpression'
+
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_mathexpression( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_mathexpression( self, *args, **kwargs )
+
+    def __init__(self, operator, lhs=None, rhs=None):
+        BinaryNode.__init__(self, lhs, rhs)
+        self.operator = operator
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (self.operator,)
+                
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return '(%s %s %s)' % (self.children[0].as_string(encoding),
+                               self.operator.encode(),
+                               self.children[1].as_string(encoding))
+
+    def __repr__(self, indent=0):
+        return '(%r %s %r)' % (self.children[0], self.operator,
+                               self.children[1])
+
+    def __cmp__(self, other):
+        if isinstance(other, MathExpression):
+            if self.operator == other.operator:
+                return cmp(self.children, other.children)
+        return 1
+
+
+class Function(HSMixin, Node):
+    """Class used to deal with aggregat functions (sum, min, max, count, avg)
+    and latter upper(), lower() and other RQL transformations functions
+    """
+    
+    TYPE = 'function'
+
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_function( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_function( self, *args, **kwargs )
+
+    def __init__(self, name):
+        Node.__init__(self)
+        self.name = name.strip().upper().encode()
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (self.name,)
+
+    def get_type(self):
+        """return the type of object returned by this function if known"""
+        try:
+            return F_TYPES[self.name]
+        except KeyError:
+            # FIXME: e_type defined by the sql generator
+            return self.children[0].e_type
+        
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return '%s(%s)' % (self.name, ', '.join([c.as_string(encoding)
+                                                 for c in self.children]))
+
+    def __repr__(self, indent=0):
+        return '%s%s(%s)' % (' '*indent, self.name,
+                             ', '.join([repr(c) for c in self.children]))
+
+    def __cmp__(self, other):
+        if isinstance(other, Function):
+            if self.name == other.name:
+                return cmp(self.children, other.children)
+        return 1
+
+
+
+class Constant(HSMixin,Node):
+    """see String, Int, TRUE, FALSE, TODAY, NULL
+    """
+    TYPE = 'constant'
+
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_constant( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_constant( self, *args, **kwargs )
+    
+    def __init__(self, value, c_type):
+        assert c_type in (None, 'Date', 'Datetime', 'Boolean', 'Float', 'Int',
+                          'String', 'Substitute', 'etype'), "Error got c_type="+repr(c_type)
+        Node.__init__(self)
+        self.value = value
+        self.type = c_type
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (self.value, self.type)
+
+    def is_variable(self):
+        """check if this node contains a reference to one ore more variables"""
+        return 0
+        
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string (an unicode string is
+        returned if encoding is None)
+        """
+        if self.type is None or self.type == 'Date':
+            return self.value
+        if self.type == 'etype':
+            return self.value.encode()
+        if self.type == 'Boolean':
+            return self.value
+        if isinstance(self.value, unicode):
+            if encoding is not None:
+                return quote(self.value.encode(encoding))
+            return uquote(self.value)
+        return repr(self.value)
+        
+    def __repr__(self, indent=0):
+        return '%s%s' % (' '*indent, self.as_string(None))
+
+    def __cmp__(self, other):
+        if isinstance(other, Constant) and self.type == other.type:
+            return cmp(self.value, other.value)
+        return 1
+
+
+class VariableRef(HSMixin, Node):
+    """a reference to a variable in the syntax tree
+    """
+    TYPE = 'variableref'
+
+    __slots__ = ('variable', 'name')
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_variableref( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_variableref( self, *args, **kwargs )
+
+    def __init__(self, variable, noautoref=None):
+        Node.__init__(self)
+        self.variable = variable
+        self.name = variable.name#.encode()
+        if noautoref is None:
+            self.register_reference()
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (stmt.get_variable(self.name),)
+        
+    def register_reference(self):
+        self.variable.register_reference(self)
+
+    def unregister_reference(self):
+        self.variable.unregister_reference(self)
+
+    def is_variable(self):
+        """check if this node contains a reference to one ore more variables"""
+        return 1
+
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return self.name
+    
+    def __repr__(self, indent=0):
+        return '%sVarRef(%#X) to %r' % (' '*indent, id(self), self.variable)
+
+    def __cmp__(self, other):
+        if isinstance(other, VariableRef):
+            return cmp(self.name, other.name)
+        return 1
+    
+    def __hash__(self):
+        return self.name.__hash__()
+
+
+class Variable(object):
+    """
+    a variable definition (should not be directly added to the syntax tree, use
+    VariableRef !)
+    """
+    TYPE = 'variable'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_variable( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_variable( self, *args, **kwargs )
+        
+    def __init__(self, name):
+        self.name = name.strip().encode()
+        # reference to the selection
+        self.root = None
+        # link to VariableReference objects in the syntax tree
+        self._references = []
+
+    def register_reference(self, varref):
+        """add a reference to this variable"""
+        assert not [v for v in self._references if v is varref]
+        self._references.append(varref)
+        
+    def unregister_reference(self, varref):
+        """remove a reference to this variable"""
+        for i in range(len(self._references)):
+            if self._references[i] is varref:
+                self._references.pop(i)
+                break
+        assert not [v for v in self._references if v is varref]
+
+    def references(self):
+        """return all references on this variable"""
+        return tuple(self._references)
+            
+    def linked_variable(self):
+        """return the lhs variable of the left most expression where this
+        variable appears.
+        """
+        for reference in self.references():
+            rel = reference.relation()
+            if rel is not None:
+                return rel.get_parts()[0]
+
+    def as_string(self, encoding=None):
+        """return the tree as an encoded rql string"""
+        return self.name
+    
+    def __repr__(self, indent=0):
+        return '%s%s(%#X)' % (' '*indent, self.name, id(self))
+
+    def __str__(self):
+        return self.name
+
+    def __cmp__(self, other):
+        if isinstance(other, Variable):
+            return cmp(self.name, other.name)
+        return 1
+    
+    def __hash__(self):
+        return self.name.__hash__()
+
+    
+# group and sort nodes ########################################################
+
+class Group(ListNode): 
+    """a group (GROUPBY) node
+    """
+    TYPE = 'group'
+
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_group( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_group( self, *args, **kwargs )
+
+    def __cmp__(self, other):
+        if isinstance(other, Group) and len(self) == len(other):
+            for i in range(len(self)):
+                if cmp(self[i], other[i]):
+                    return 1
+            return 0
+        return 1
+
+    def __repr__(self):
+        for child in self.children:
+            s.append(repr(child))
+        return 'GROUPBY %s' % ', '.join(s)
+    
+class Sort(ListNode):
+    """a sort (ORDERBY) node
+    """
+    TYPE = 'sort'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_sort( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_sort( self, *args, **kwargs )
+
+    def __cmp__(self, other):
+        if isinstance(other, Sort) and len(self) == len(other):
+            for i in range(len(self)):
+                if cmp(self[i], other[i]):
+                    return 1
+            return 0
+        return 1
+
+    def __repr__(self):
+        for child in self.children:
+            s.append(repr(child))
+        return 'ORDERBY %s' % ', '.join(s)
+    
+
+class SortTerm(HSMixin, Node):
+    """a sort term bind a variable to the boolean <asc>
+    if <asc> ascendant sort
+    else descendant sort
+    """
+    TYPE = 'sortterm'
+    
+    def accept(self, visitor, *args, **kwargs):
+        return visitor.visit_sortterm( self, *args, **kwargs )
+    
+    def leave(self, visitor, *args, **kwargs):
+        return visitor.leave_sortterm( self, *args, **kwargs )
+
+    def __init__(self, variable, asc=1, copy=None):
+        Node.__init__(self)
+        self.asc = asc
+        self.var = variable
+        if copy is None:
+            self.append(variable)
+
+    def initargs(self, stmt):
+        """return list of arguments to give to __init__ to clone this node"""
+        return (self.var.copy(stmt), self.asc)
+    
+    def __repr__(self, indent=0):
+        if self.asc:
+            return '%r' % self.var
+        return '%r DESC' % self.var
+
+    def __str__(self):
+        if self.asc:
+            return '%s' % self.var
+        return '%s DESC' % self.var
+
+    def __cmp__(self, other):
+        if isinstance(other, SortTerm):
+            if self.asc == other.asc:
+                return cmp(self.var, other.var)
+        return 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser.g	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,258 @@
+"""yapps input grammar for RQL.
+
+Copyright (c) 2002-2005 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: parser.g,v 1.17 2006-03-27 18:10:12 syt Exp $"
+
+
+from rql.stmts import Select, Delete, Insert, Update
+from rql.nodes import *
+
+_OR = OR
+_AND = AND
+
+
+def unquote(string):
+    """Remove quotes from a string."""
+    if string.startswith('"'):
+        return string[1:-1].replace('\\\\', '\\').replace('\\"', '"')
+    elif string.startswith("'"):
+        return string[1:-1].replace('\\\\', '\\').replace("\\'", "'")
+%%
+
+parser Hercule:
+
+    ignore:            r'\s+'
+    # C-like comments
+    ignore:            r'/\*(?:[^*]|\*(?!/))*\*/'
+
+    token DELETE:      r'(?i)DELETE'
+    token SET:         r'(?i)SET'
+    token INSERT:      r'(?i)INSERT'
+    token DISTINCT:    r'(?i)DISTINCT'
+    token WHERE:       r'(?i)WHERE'
+    token OR:          r'(?i)OR'
+    token AND:         r'(?i)AND'
+    token NOT:         r'(?i)NOT'
+    token GROUPBY:     r'(?i)GROUPBY'
+    token ORDERBY:     r'(?i)ORDERBY'
+    token SORT_ASC:    r'(?i)ASC'
+    token SORT_DESC:   r'(?i)DESC'
+    token LIMIT:       r'(?i)LIMIT'
+    token OFFSET:      r'(?i)OFFSET'
+    token BOOLEAN:     r'(?i)TRUE|FALSE'
+    token DATE:        r'(?i)TODAY'
+    token DATETIME:    r'(?i)NOW'
+    token NULL:        r'(?i)NULL'
+    token CMP_OP:      r'(?i)<=|<|>=|>|~=|=|LIKE'
+    token ADD_OP:      r'\+|-'
+    token MUL_OP:      r'\*|/'
+    token FUNCTION:    r'[A-Za-z]+\s*(?=\()'
+    token R_TYPE:      r'[a-z][a-z0-9_]+'
+    token E_TYPE:      r'[A-Z][a-z]+[a-z0-9]*'
+    token VARIABLE:    r'[A-Z][A-Z0-9_]*'
+
+    token STRING:      r"'([^\'\\]|\\.)*'|\"([^\\\"\\]|\\.)*\""
+    token FLOAT:       r'\d+\.\d*'
+    token INT:         r'\d+'
+    token SUBSTITUTE:  r'%\([A-Za-z_0-9]+\)s'
+
+
+# Grammar entry ###############################################################
+#
+# abbreviations :
+#
+#  rel -> relation
+#  decl -> declaration
+#  expr -> expression
+#  restr -> restriction
+#  var -> variable
+#  func -> function
+#  const -> constant
+#  cmp -> comparison
+
+rule goal<<T>>: DELETE _delete<<Delete(T)>> ';' {{ return _delete }}
+
+              | INSERT _insert<<Insert(T)>> ';' {{ return _insert }}
+ 
+              | SET update<<Update(T)>> ';'     {{ return update }}
+
+              | select<<Select(T)>> ';'         {{ return select }}
+
+
+# Deletion  ###################################################################
+
+rule _delete<<V>>: rels_decl<<V>> restr<<V>> {{ return V }}
+
+                 | vars_decl<<V>> restr<<V>>    {{ return V }}
+
+
+# Insertion  ##################################################################
+
+rule _insert<<V>>: vars_decl<<V>> insert_rels<<V>> {{ return V }}
+                    
+
+rule insert_rels<<V>>: ":" rels_decl<<V>> restr<<V>> {{ return V }}
+
+                     |
+
+
+# Update  #####################################################################
+
+rule update<<V>>: rels_decl<<V>> restr<<V>> {{ return V }}
+
+
+# Selection  ##################################################################
+
+rule select<<V>>: DISTINCT select_base<<V>> {{ V.distinct = True ; return V }}
+
+                | select_base<<V>>          {{ return V }}
+
+
+rule select_base<<V>>: E_TYPE selected_terms<<V>> restr<<V>> 
+                       group<<V>> sort<<V>> 
+                       limit_offset<<V>>  {{ V.set_statement_type(E_TYPE) ; return V }}
+
+
+rule selected_terms<<V>>: added_expr<<V>> (   {{ V.append_selected(added_expr) }}
+                            ',' added_expr<<V>>
+                            )*                    {{ V.append_selected(added_expr) }}
+
+
+
+# Groups and sorts ############################################################
+
+rule group<<V>>: GROUPBY        {{ G = Group() }}
+                   var<<V>> (   {{ G.append(var) }}
+                   ',' var<<V>>
+                   )*           {{ G.append(var) ; V.append(G) }}
+
+                 |
+
+
+rule sort<<V>>: ORDERBY              {{ S = Sort() }}
+                  sort_term<<V>> (   {{ S.append(sort_term) }}
+                  ',' sort_term<<V>>
+                  )*                 {{ S.append(sort_term) ; V.append(S) }}
+
+                |
+
+
+rule sort_term<<V>>: added_expr<<V>> sort_meth {{ return SortTerm(added_expr, sort_meth) }}
+
+
+rule sort_meth: SORT_DESC {{ return 0 }}
+
+              | SORT_ASC  {{ return 1 }}
+
+              |           {{ return 1 # default to SORT_ASC }}
+
+
+# Limit and offset ############################################################
+
+rule limit_offset<<V>> :  limit<<V>> offset<<V>>
+		  
+rule limit<<V>> : LIMIT INT {{ V.limit = int(INT) }} 
+                |
+
+
+rule offset<<V>> : OFFSET INT {{ V.offset = int(INT) }}
+  		         | 
+
+
+# Restriction statements ######################################################
+
+rule restr<<V>>: WHERE rels<<V>> {{ V.append(rels) }}
+
+               | 
+
+
+rule rels<<V>>: ored_rels<<V>>    {{ lhs = ored_rels }}
+                ( ',' ored_rels<<V>> {{ lhs = AND(lhs, ored_rels) }}
+                )*                 {{ return lhs }}
+
+
+rule ored_rels<<V>>: anded_rels<<V>>  {{ lhs = anded_rels }}
+                     ( OR anded_rels<<V>> {{ lhs = _OR(lhs,anded_rels) }}
+                     )*                 {{ return lhs }}
+
+
+rule anded_rels<<V>>: rel<<V>>         {{ lhs = rel }}
+                         (  AND rel<<V>> {{ lhs = _AND(lhs,rel) }}
+                             )*         {{ return lhs }}
+
+
+rule rel<<V>>: NOT base_rel<<V>>     {{ base_rel._not = 1; return base_rel }} 
+
+               | base_rel<<V>>         {{ return base_rel }}
+
+               | r"\(" rels<<V>> r"\)" {{ return rels }}
+
+
+rule base_rel<<V>>: var<<V>> R_TYPE {{ e = Relation(R_TYPE) ; e.append(var) }} 
+                    expr<<V>>       {{ e.append(expr) ; return e }}
+
+
+# common statements ###########################################################
+
+rule vars_decl<<V>>: E_TYPE var<<V>> (     {{ V.add_main_variable(E_TYPE, var) }}
+                     ',' E_TYPE var<<V>>)* {{ V.add_main_variable(E_TYPE, var) }}
+
+
+rule rels_decl<<V>>: simple_rel<<V>> (     {{ V.add_main_relation(simple_rel) }}
+                     ',' simple_rel<<V>>)* {{ V.add_main_relation(simple_rel) }}
+
+
+rule simple_rel<<V>>: var<<V>> R_TYPE    {{ e = Relation(R_TYPE) ; e.append(var) }} 
+                      added_expr<<V>>    {{ e.append(added_expr) ; return e }}
+
+
+rule expr<<V>>: CMP_OP added_expr<<V>> {{ return Comparison(CMP_OP.upper(), added_expr) }}
+
+                | added_expr<<V>>      {{ return Comparison('=', added_expr) }}
+
+
+rule added_expr<<V>>: muled_expr<<V>>       {{ lhs = muled_expr }}
+                        ( ADD_OP muled_expr<<V>> {{ lhs = MathExpression( ADD_OP, lhs, muled_expr ) }}
+                        )*                       {{ return lhs }}
+
+
+rule muled_expr<<V>>: base_expr<<V>>       {{ lhs = base_expr }}
+                       ( MUL_OP base_expr<<V>> {{ lhs = MathExpression( MUL_OP, lhs, base_expr) }}
+                        )*                      {{ return lhs }}
+
+
+rule base_expr<<V>>: const                         {{ return const }}
+
+                     | var<<V>>                      {{ return var }} 
+
+                     | e_type<<V>>                   {{ return e_type }} 
+
+                     | func<<V>>                   {{ return func }}
+
+                     | r"\(" added_expr<<V>> r"\)" {{ return added_expr }}
+
+
+rule func<<V>>: FUNCTION r"\("              {{ F = Function(FUNCTION) }}
+                  added_expr<<V>> (         {{ F.append(added_expr) }}
+                  ',' added_expr<<V>>             
+                  )*                          {{ F.append(added_expr) }}
+                  r"\)"                       {{ return F }} 
+
+
+rule var<<V>>: VARIABLE {{ return VariableRef(V.get_variable(VARIABLE)) }} 
+
+rule e_type<<V>>: E_TYPE {{ return V.get_type(E_TYPE) }} 
+
+
+rule const: NULL      {{ return Constant('NULL', None) }}
+          | DATE      {{ return Constant(DATE.upper(), 'Date') }}
+          | DATETIME  {{ return Constant(DATETIME.upper(), 'Datetime') }}
+          | BOOLEAN   {{ return Constant(BOOLEAN.lower(), 'Boolean') }}
+          | FLOAT     {{ return Constant(float(FLOAT), 'Float') }}
+          | INT       {{ return Constant(int(INT), 'Int') }}
+          | STRING    {{ return Constant(unquote(STRING), 'String') }}
+          | SUBSTITUTE {{ return Constant(SUBSTITUTE[2:-2], 'Substitute') }}
+                       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,433 @@
+"""yapps input grammar for RQL.
+
+Copyright (c) 2002-2005 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: parser.py,v 1.17 2006-03-27 18:10:12 syt Exp $"
+
+
+from rql.stmts import Select, Delete, Insert, Update
+from rql.nodes import *
+
+_OR = OR
+_AND = AND
+
+
+def unquote(string):
+    """Remove quotes from a string."""
+    if string.startswith('"'):
+        return string[1:-1].replace('\\\\', '\\').replace('\\"', '"')
+    elif string.startswith("'"):
+        return string[1:-1].replace('\\\\', '\\').replace("\\'", "'")
+
+from string import *
+import re
+from thirdparty.yappsrt import *
+
+class HerculeScanner(Scanner):
+    patterns = [
+        ('r"\\)"', re.compile('\\)')),
+        ('r"\\("', re.compile('\\(')),
+        ("','", re.compile(',')),
+        ('":"', re.compile(':')),
+        ("';'", re.compile(';')),
+        ('\\s+', re.compile('\\s+')),
+        ('/\\*(?:[^*]|\\*(?!/))*\\*/', re.compile('/\\*(?:[^*]|\\*(?!/))*\\*/')),
+        ('DELETE', re.compile('(?i)DELETE')),
+        ('SET', re.compile('(?i)SET')),
+        ('INSERT', re.compile('(?i)INSERT')),
+        ('DISTINCT', re.compile('(?i)DISTINCT')),
+        ('WHERE', re.compile('(?i)WHERE')),
+        ('OR', re.compile('(?i)OR')),
+        ('AND', re.compile('(?i)AND')),
+        ('NOT', re.compile('(?i)NOT')),
+        ('GROUPBY', re.compile('(?i)GROUPBY')),
+        ('ORDERBY', re.compile('(?i)ORDERBY')),
+        ('SORT_ASC', re.compile('(?i)ASC')),
+        ('SORT_DESC', re.compile('(?i)DESC')),
+        ('LIMIT', re.compile('(?i)LIMIT')),
+        ('OFFSET', re.compile('(?i)OFFSET')),
+        ('BOOLEAN', re.compile('(?i)TRUE|FALSE')),
+        ('DATE', re.compile('(?i)TODAY')),
+        ('DATETIME', re.compile('(?i)NOW')),
+        ('NULL', re.compile('(?i)NULL')),
+        ('CMP_OP', re.compile('(?i)<=|<|>=|>|~=|=|LIKE')),
+        ('ADD_OP', re.compile('\\+|-')),
+        ('MUL_OP', re.compile('\\*|/')),
+        ('FUNCTION', re.compile('[A-Za-z]+\\s*(?=\\()')),
+        ('R_TYPE', re.compile('[a-z][a-z0-9_]+')),
+        ('E_TYPE', re.compile('[A-Z][a-z]+[a-z0-9]*')),
+        ('VARIABLE', re.compile('[A-Z][A-Z0-9_]*')),
+        ('STRING', re.compile('\'([^\\\'\\\\]|\\\\.)*\'|\\"([^\\\\\\"\\\\]|\\\\.)*\\"')),
+        ('FLOAT', re.compile('\\d+\\.\\d*')),
+        ('INT', re.compile('\\d+')),
+        ('SUBSTITUTE', re.compile('%\\([A-Za-z_0-9]+\\)s')),
+    ]
+    def __init__(self, str):
+        Scanner.__init__(self,None,['\\s+', '/\\*(?:[^*]|\\*(?!/))*\\*/'],str)
+
+class Hercule(Parser):
+    def goal(self, T):
+        _token_ = self._peek('DELETE', 'INSERT', 'SET', 'DISTINCT', 'E_TYPE')
+        if _token_ == 'DELETE':
+            DELETE = self._scan('DELETE')
+            _delete = self._delete(Delete(T))
+            self._scan("';'")
+            return _delete
+        elif _token_ == 'INSERT':
+            INSERT = self._scan('INSERT')
+            _insert = self._insert(Insert(T))
+            self._scan("';'")
+            return _insert
+        elif _token_ == 'SET':
+            SET = self._scan('SET')
+            update = self.update(Update(T))
+            self._scan("';'")
+            return update
+        else: # in ['DISTINCT', 'E_TYPE']
+            select = self.select(Select(T))
+            self._scan("';'")
+            return select
+
+    def _delete(self, V):
+        _token_ = self._peek('E_TYPE', 'VARIABLE')
+        if _token_ == 'VARIABLE':
+            rels_decl = self.rels_decl(V)
+            restr = self.restr(V)
+            return V
+        else: # == 'E_TYPE'
+            vars_decl = self.vars_decl(V)
+            restr = self.restr(V)
+            return V
+
+    def _insert(self, V):
+        vars_decl = self.vars_decl(V)
+        insert_rels = self.insert_rels(V)
+        return V
+
+    def insert_rels(self, V):
+        _token_ = self._peek('":"', "';'")
+        if _token_ == '":"':
+            self._scan('":"')
+            rels_decl = self.rels_decl(V)
+            restr = self.restr(V)
+            return V
+        else: # == "';'"
+            pass
+
+    def update(self, V):
+        rels_decl = self.rels_decl(V)
+        restr = self.restr(V)
+        return V
+
+    def select(self, V):
+        _token_ = self._peek('DISTINCT', 'E_TYPE')
+        if _token_ == 'DISTINCT':
+            DISTINCT = self._scan('DISTINCT')
+            select_base = self.select_base(V)
+            V.distinct = True ; return V
+        else: # == 'E_TYPE'
+            select_base = self.select_base(V)
+            return V
+
+    def select_base(self, V):
+        E_TYPE = self._scan('E_TYPE')
+        selected_terms = self.selected_terms(V)
+        restr = self.restr(V)
+        group = self.group(V)
+        sort = self.sort(V)
+        limit_offset = self.limit_offset(V)
+        V.set_statement_type(E_TYPE) ; return V
+
+    def selected_terms(self, V):
+        added_expr = self.added_expr(V)
+        while self._peek("','", 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'WHERE', 'GROUPBY', 'ORDERBY', "';'", 'LIMIT', 'OFFSET', 'AND', 'OR') == "','":
+            V.append_selected(added_expr)
+            self._scan("','")
+            added_expr = self.added_expr(V)
+        V.append_selected(added_expr)
+
+    def group(self, V):
+        _token_ = self._peek('GROUPBY', 'ORDERBY', 'LIMIT', 'OFFSET', "';'")
+        if _token_ == 'GROUPBY':
+            GROUPBY = self._scan('GROUPBY')
+            G = Group()
+            var = self.var(V)
+            while self._peek("','", 'R_TYPE', 'ORDERBY', 'WHERE', '":"', 'MUL_OP', 'LIMIT', 'OFFSET', 'GROUPBY', "';'", 'ADD_OP', 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'AND', 'OR') == "','":
+                G.append(var)
+                self._scan("','")
+                var = self.var(V)
+            G.append(var) ; V.append(G)
+        else: # in ['ORDERBY', 'LIMIT', 'OFFSET', "';'"]
+            pass
+
+    def sort(self, V):
+        _token_ = self._peek('ORDERBY', 'LIMIT', 'OFFSET', "';'")
+        if _token_ == 'ORDERBY':
+            ORDERBY = self._scan('ORDERBY')
+            S = Sort()
+            sort_term = self.sort_term(V)
+            while self._peek("','", 'LIMIT', 'OFFSET', "';'") == "','":
+                S.append(sort_term)
+                self._scan("','")
+                sort_term = self.sort_term(V)
+            S.append(sort_term) ; V.append(S)
+        else: # in ['LIMIT', 'OFFSET', "';'"]
+            pass
+
+    def sort_term(self, V):
+        added_expr = self.added_expr(V)
+        sort_meth = self.sort_meth()
+        return SortTerm(added_expr, sort_meth)
+
+    def sort_meth(self):
+        _token_ = self._peek('SORT_DESC', 'SORT_ASC', "','", 'LIMIT', 'OFFSET', "';'")
+        if _token_ == 'SORT_DESC':
+            SORT_DESC = self._scan('SORT_DESC')
+            return 0
+        elif _token_ == 'SORT_ASC':
+            SORT_ASC = self._scan('SORT_ASC')
+            return 1
+        else: # in ["','", 'LIMIT', 'OFFSET', "';'"]
+            return 1 # default to SORT_ASC
+
+    def limit_offset(self, V):
+        limit = self.limit(V)
+        offset = self.offset(V)
+
+    def limit(self, V):
+        _token_ = self._peek('LIMIT', 'OFFSET', "';'")
+        if _token_ == 'LIMIT':
+            LIMIT = self._scan('LIMIT')
+            INT = self._scan('INT')
+            V.limit = int(INT)
+        else: # in ['OFFSET', "';'"]
+            pass
+
+    def offset(self, V):
+        _token_ = self._peek('OFFSET', "';'")
+        if _token_ == 'OFFSET':
+            OFFSET = self._scan('OFFSET')
+            INT = self._scan('INT')
+            V.offset = int(INT)
+        else: # == "';'"
+            pass
+
+    def restr(self, V):
+        _token_ = self._peek('WHERE', 'GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET')
+        if _token_ == 'WHERE':
+            WHERE = self._scan('WHERE')
+            rels = self.rels(V)
+            V.append(rels)
+        else: # in ['GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET']
+            pass
+
+    def rels(self, V):
+        ored_rels = self.ored_rels(V)
+        lhs = ored_rels
+        while self._peek("','", 'r"\\)"', 'GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET') == "','":
+            self._scan("','")
+            ored_rels = self.ored_rels(V)
+            lhs = AND(lhs, ored_rels)
+        return lhs
+
+    def ored_rels(self, V):
+        anded_rels = self.anded_rels(V)
+        lhs = anded_rels
+        while self._peek('OR', "','", 'r"\\)"', 'GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET') == 'OR':
+            OR = self._scan('OR')
+            anded_rels = self.anded_rels(V)
+            lhs = _OR(lhs,anded_rels)
+        return lhs
+
+    def anded_rels(self, V):
+        rel = self.rel(V)
+        lhs = rel
+        while self._peek('AND', 'OR', "','", 'r"\\)"', 'GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET') == 'AND':
+            AND = self._scan('AND')
+            rel = self.rel(V)
+            lhs = _AND(lhs,rel)
+        return lhs
+
+    def rel(self, V):
+        _token_ = self._peek('NOT', 'r"\\("', 'VARIABLE')
+        if _token_ == 'NOT':
+            NOT = self._scan('NOT')
+            base_rel = self.base_rel(V)
+            base_rel._not = 1; return base_rel
+        elif _token_ == 'VARIABLE':
+            base_rel = self.base_rel(V)
+            return base_rel
+        else: # == 'r"\\("'
+            self._scan('r"\\("')
+            rels = self.rels(V)
+            self._scan('r"\\)"')
+            return rels
+
+    def base_rel(self, V):
+        var = self.var(V)
+        R_TYPE = self._scan('R_TYPE')
+        e = Relation(R_TYPE) ; e.append(var)
+        expr = self.expr(V)
+        e.append(expr) ; return e
+
+    def vars_decl(self, V):
+        E_TYPE = self._scan('E_TYPE')
+        var = self.var(V)
+        while self._peek("','", 'R_TYPE', 'WHERE', '":"', 'GROUPBY', "';'", 'MUL_OP', 'ORDERBY', 'LIMIT', 'OFFSET', 'ADD_OP', 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'AND', 'OR') == "','":
+            V.add_main_variable(E_TYPE, var)
+            self._scan("','")
+            E_TYPE = self._scan('E_TYPE')
+            var = self.var(V)
+        V.add_main_variable(E_TYPE, var)
+
+    def rels_decl(self, V):
+        simple_rel = self.simple_rel(V)
+        while self._peek("','", 'WHERE', 'GROUPBY', "';'", 'ORDERBY', 'LIMIT', 'OFFSET') == "','":
+            V.add_main_relation(simple_rel)
+            self._scan("','")
+            simple_rel = self.simple_rel(V)
+        V.add_main_relation(simple_rel)
+
+    def simple_rel(self, V):
+        var = self.var(V)
+        R_TYPE = self._scan('R_TYPE')
+        e = Relation(R_TYPE) ; e.append(var)
+        added_expr = self.added_expr(V)
+        e.append(added_expr) ; return e
+
+    def expr(self, V):
+        _token_ = self._peek('CMP_OP', 'r"\\("', 'NULL', 'DATE', 'DATETIME', 'BOOLEAN', 'FLOAT', 'INT', 'STRING', 'SUBSTITUTE', 'VARIABLE', 'E_TYPE', 'FUNCTION')
+        if _token_ == 'CMP_OP':
+            CMP_OP = self._scan('CMP_OP')
+            added_expr = self.added_expr(V)
+            return Comparison(CMP_OP.upper(), added_expr)
+        else: 
+            added_expr = self.added_expr(V)
+            return Comparison('=', added_expr)
+
+    def added_expr(self, V):
+        muled_expr = self.muled_expr(V)
+        lhs = muled_expr
+        while self._peek('ADD_OP', "','", 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'WHERE', 'GROUPBY', 'ORDERBY', "';'", 'LIMIT', 'OFFSET', 'AND', 'OR') == 'ADD_OP':
+            ADD_OP = self._scan('ADD_OP')
+            muled_expr = self.muled_expr(V)
+            lhs = MathExpression( ADD_OP, lhs, muled_expr )
+        return lhs
+
+    def muled_expr(self, V):
+        base_expr = self.base_expr(V)
+        lhs = base_expr
+        while self._peek('MUL_OP', 'ADD_OP', "','", 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'WHERE', 'GROUPBY', 'ORDERBY', "';'", 'LIMIT', 'OFFSET', 'AND', 'OR') == 'MUL_OP':
+            MUL_OP = self._scan('MUL_OP')
+            base_expr = self.base_expr(V)
+            lhs = MathExpression( MUL_OP, lhs, base_expr)
+        return lhs
+
+    def base_expr(self, V):
+        _token_ = self._peek('r"\\("', 'NULL', 'DATE', 'DATETIME', 'BOOLEAN', 'FLOAT', 'INT', 'STRING', 'SUBSTITUTE', 'VARIABLE', 'E_TYPE', 'FUNCTION')
+        if _token_ not in ['r"\\("', 'VARIABLE', 'E_TYPE', 'FUNCTION']:
+            const = self.const()
+            return const
+        elif _token_ == 'VARIABLE':
+            var = self.var(V)
+            return var
+        elif _token_ == 'E_TYPE':
+            e_type = self.e_type(V)
+            return e_type
+        elif _token_ == 'FUNCTION':
+            func = self.func(V)
+            return func
+        else: # == 'r"\\("'
+            self._scan('r"\\("')
+            added_expr = self.added_expr(V)
+            self._scan('r"\\)"')
+            return added_expr
+
+    def func(self, V):
+        FUNCTION = self._scan('FUNCTION')
+        self._scan('r"\\("')
+        F = Function(FUNCTION)
+        added_expr = self.added_expr(V)
+        while self._peek("','", 'r"\\)"', 'SORT_DESC', 'SORT_ASC', 'WHERE', 'GROUPBY', 'ORDERBY', "';'", 'LIMIT', 'OFFSET', 'AND', 'OR') == "','":
+            F.append(added_expr)
+            self._scan("','")
+            added_expr = self.added_expr(V)
+        F.append(added_expr)
+        self._scan('r"\\)"')
+        return F
+
+    def var(self, V):
+        VARIABLE = self._scan('VARIABLE')
+        return VariableRef(V.get_variable(VARIABLE))
+
+    def e_type(self, V):
+        E_TYPE = self._scan('E_TYPE')
+        return V.get_type(E_TYPE)
+
+    def const(self):
+        _token_ = self._peek('NULL', 'DATE', 'DATETIME', 'BOOLEAN', 'FLOAT', 'INT', 'STRING', 'SUBSTITUTE')
+        if _token_ == 'NULL':
+            NULL = self._scan('NULL')
+            return Constant('NULL', None)
+        elif _token_ == 'DATE':
+            DATE = self._scan('DATE')
+            return Constant(DATE.upper(), 'Date')
+        elif _token_ == 'DATETIME':
+            DATETIME = self._scan('DATETIME')
+            return Constant(DATETIME.upper(), 'Datetime')
+        elif _token_ == 'BOOLEAN':
+            BOOLEAN = self._scan('BOOLEAN')
+            return Constant(BOOLEAN.lower(), 'Boolean')
+        elif _token_ == 'FLOAT':
+            FLOAT = self._scan('FLOAT')
+            return Constant(float(FLOAT), 'Float')
+        elif _token_ == 'INT':
+            INT = self._scan('INT')
+            return Constant(int(INT), 'Int')
+        elif _token_ == 'STRING':
+            STRING = self._scan('STRING')
+            return Constant(unquote(STRING), 'String')
+        else: # == 'SUBSTITUTE'
+            SUBSTITUTE = self._scan('SUBSTITUTE')
+            return Constant(SUBSTITUTE[2:-2], 'Substitute')
+
+
+def parse(rule, text):
+    P = Hercule(HerculeScanner(text))
+    return wrap_error_reporter(P, rule)
+
+if __name__=='old__main__':
+    from sys import argv, stdin
+    if len(argv) >= 2:
+        if len(argv) >= 3:
+            f = open(argv[2],'r')
+        else:
+            f = stdin
+        print parse(argv[1], f.read())
+    else: print 'Args:  <rule> [<filename>]'
+""" Copyright (c) 2000-2003 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: parser.py,v 1.17 2006-03-27 18:10:12 syt Exp $"
+
+
+if __name__ == '__main__':
+    from sys import argv
+    
+    parser = Hercule(HerculeScanner(argv[1]))
+    e_types = {}
+    # parse the RQL string
+    try:
+        tree = parser.goal(e_types)
+        print '-'*80
+        print tree
+        print '-'*80
+        print repr(tree)
+        print e_types
+    except SyntaxError, s:
+        # try to get error message from yapps
+        data = parser._scanner.input
+        print_error(data, s, parser._scanner)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser_main.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,24 @@
+""" Copyright (c) 2000-2003 LOGILAB S.A. (Paris, FRANCE).
+ http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: parser_main.py,v 1.3 2005-06-09 00:02:37 ludal Exp $"
+
+
+if __name__ == '__main__':
+    from sys import argv
+    
+    parser = Hercule(HerculeScanner(argv[1]))
+    e_types = {}
+    # parse the RQL string
+    try:
+        tree = parser.goal(e_types)
+        print '-'*80
+        print tree
+        print '-'*80
+        print repr(tree)
+        print e_types
+    except SyntaxError, s:
+        # try to get error message from yapps
+        data = parser._scanner.input
+        print_error(data, s, parser._scanner)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlgen.py	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,203 @@
+"""Generation of RQL string
+
+Copyright (c) 2003-2004 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__revision__ = "$Id: rqlgen.py,v 1.5 2005-02-25 21:34:14 nico Exp $"
+
+NOT = 1
+
+
+class RQLGenerator(object):
+    """
+    Helper class to generate RQL strings
+    """
+
+
+    def select(self, e_type, nupplets=(), groups=(), sorts=()) :
+        """
+        return a RQL selection query
+        
+        * type is the desired entity's type (maybe 'Any')
+        * nupplets is a list of 4-uples
+            (subject, relation, object, not)
+          where :
+           * <subject> and <object> maybe a string designing a variable or a
+             constant. The special variable X represents the searched set of
+             entities
+           * <relation> is the statement axis
+           * <not> is a boolean indicating it should be a negative statement
+             (0 -> positive statement, 1 -> negative statement). You may omit
+             this parameter, it default to 0.
+        * groups is a list of variables to use in groups
+        * sorts is a list of sort term. A sort term is a string designing a
+          variable and optionnaly the sort order ('ASC' or 'DESC'). If the
+          sort order is omitted default to 'ASC'
+
+
+        examples :
+        
+        >>> s = RQLGenerator()
+        >>> s.select('Any', (('X', 'eid', 14),) )
+        'Any X\\nWHERE X eid 14'
+        >>> s.select('Person',
+        ...          ( ('X','work_for','S'), ('S','name','"Logilab"'),
+        ...            ('X','firstname','F'), ('X','surname','S') ),
+        ...          sorts=('F ASC', 'S DESC')
+        ...          )
+        'Person X\\nWHERE X work_for S , S name "Logilab" , X firstname F , X surname S\\nSORTBY F ASC, S DESC'
+        """
+        result = [e_type + ' X']
+        if nupplets:
+            result.append(self.where(nupplets))
+        if groups:
+            result.append(self.groupby(groups))
+        if sorts:
+            result.append(self.sortby(sorts))
+        return '\n'.join(result)
+
+                
+    def where(self, nupplets):
+        """ return a where statement
+        
+        * nupplets is a list of 4-uples
+            (subject, relation, object, not)
+          where :
+           * <subject> and <object> maybe a string designing a variable or a
+             constant. The special variable X represents the searched set of
+             entities
+           * <relation> is the statement axis
+           * <not> is a boolean indicating it should be a negative statement
+             (0 -> positive statement, 1 -> negative statement). You may omit
+             this parameter, it default to 0.
+
+
+        examples :
+                     
+        >>> s = RQLGenerator()
+        >>> s.where( (('X', 'eid', 14),) )
+        'WHERE X eid 14'
+        >>> s.where( ( ('X','work_for','S'), ('S','name','"Logilab"'), 
+        ...            ('X','firstname','F'), ('X','surname','S') ) )
+        'WHERE X work_for S , S name "Logilab" , X firstname F , X surname S'
+        """
+        result = ['WHERE']
+        total = len(nupplets)
+        for i in range(total):
+            nupplet = nupplets[i]
+            if len(nupplet) == 4 and nupplet[3] == NOT:
+                result.append('NOT')
+            result.append(str(nupplet[0]))
+            result.append(str(nupplet[1]))
+            result.append(str(nupplet[2]))
+            if i < total - 1:
+                result.append(',')
+        return ' '.join(result)
+
+        
+    def groupby(self, groups):
+        """ return a group by statement
+        
+        * groups is a list of variables to use in groups
+
+
+        example :
+        
+        >>> s = RQLGenerator()
+        >>> s.groupby(('F', 'S'))
+        'GROUPBY F, S'
+        """
+        return 'GROUPBY %s' % ', '.join(groups)
+
+    
+    def sortby(self, sorts):
+        """ return a sort by statement
+        
+        * sorts is a list of sort term. A sort term is a string designing a
+          variable and optionnaly the sort order ('ASC' or 'DESC'). If the
+          sort order is omitted default to 'ASC'
+
+
+        example :
+
+        >>> s = RQLGenerator()
+        >>> s.sortby(('F ASC', 'S DESC'))
+        'SORTBY F ASC, S DESC'
+        """
+        return 'SORTBY %s' % ', '.join(sorts)
+
+
+    def insert(self, e_type, attributes):
+        """ returns an insert statement
+
+        * e_type is the entity type to insert
+
+        * attributes is a list of tuples (attr_name, attr_value)
+
+        example :
+
+        >>> s = RQLGenerator()
+        >>> s.insert('Person', (('firstname', "Clark"), ('lastname', "Kent")))
+        'INSERT Person X: X firstname "Clark", X lastname "Kent"'
+        """
+        restrictions = ['X %s "%s"' % (attr_name, attr_value)
+                        for attr_name, attr_value in attributes] # .items()]
+        return 'INSERT %s X: %s' % (e_type, ', '.join(restrictions))
+
+
+    def delete(self, e_type, attributes):
+        """ returns a delete statement
+
+        * e_type is the entity type to delete
+
+        * attributes is a list of tuples (attr_name, attr_value)
+
+        example :
+
+        >>> s = RQLGenerator()
+        >>> s.delete('Person', (('firstname', "Clark"), ('lastname', "Kent")))
+        'DELETE Person X where X firstname "Clark", X lastname "Kent"'
+        """
+        restrictions = ['X %s "%s"' % (attr_name, attr_value)
+                        for attr_name, attr_value in attributes] # .items()]
+        return 'DELETE %s X where %s' % (e_type, ', '.join(restrictions))
+
+
+    def update(self, e_type, old_descr, new_descr):
+        """ returns a set statement
+
+        * e_type is the entity type to update
+
+        * old_descr is a list of tuples (attr_name, attr_value)
+          that identifies the entity to update
+
+        * new_descr is a list of tuples (attr_name, attr_value)
+          that defines the attributes to update
+
+        example :
+
+        >>> s = RQLGenerator()
+        >>> s.update('Person', (('firstname', "Clark"), ('lastname', "Kent")),
+        ...         (('job', "superhero"), ('nickname', "superman")))
+        'SET X job "superhero", X nickname "superman" WHERE X is "Person", X firstname "Clark", X lastname "Kent"'
+        """
+        old_restrictions = ['X is "%s"' % e_type]
+        old_restrictions += ['X %s "%s"' % (attr_name, attr_value)
+                             for attr_name, attr_value in old_descr]
+        new_restrictions = ['X %s "%s"' % (attr_name, attr_value)
+                            for attr_name, attr_value in new_descr]
+        return 'SET %s WHERE %s' % (', '.join(new_restrictions),
+                                    ', '.join(old_restrictions))
+    
+RQLGENERATOR = RQLGenerator()
+
+def _test():
+    """
+    Launch doctest
+    """
+    import doctest, sys
+    return doctest.testmod(sys.modules[__name__])
+
+if __name__ == "__main__":
+    _test()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/Makefile	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,47 @@
+
+CFLAGS=-g -Wall
+LDFLAGS=
+PYFLAGS=-I/usr/include/python2.3
+BOOSTLDFLAGS=-lboost_python -lpython2.3
+
+PARSEROBJ=rql_token.o rql_parser.o rql_scanner.o
+
+
+rqlparse.so: rql_token.o rql_parser.o rql_scanner.o nodes.o rqlmodule.o
+	${CXX} --shared -lpython2.3 ${PYFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^
+
+rqlboostparser.so: rql_token.o rql_parser.o rql_scanner.o nodes.o boost_module.cc
+	${CXX} --shared ${BOOSTLDFLAGS} ${PYFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^
+
+rqlmodule.o: rqlmodule.cc
+	${CXX} ${CFLAGS} ${LDFLAGS} $(PYFLAGS) -c -o $@ $^
+
+rqlparse: rql_main.o rql_token.o rql_parser.o rql_scanner.o nodes.o
+	${CXX} ${CFLAGS} ${LDFLAGS} -o $@ $^
+
+rql_main.o: rql_main.cc rql_parser.hh rql_token.hh rql_scanner.hh
+	${CXX} ${CFLAGS} -c -o $@ $<
+
+nodes.o: nodes.cc nodes.hh
+	${CXX} ${CFLAGS} -c -o $@ $<
+
+rql_token.o: rql_token.cc rql_token.hh nodes.hh
+	${CXX} ${CFLAGS} -c -o $@ $<
+
+rql_parser.o: rql_parser.cc rql_parser.hh nodes.hh
+	${CXX} ${CFLAGS} -c -o $@ $<
+
+rql_scanner.o: rql_scanner.cc rql_scanner.hh nodes.hh
+	${CXX} ${CFLAGS} -c -o $@ $<
+
+rql_scanner.cc rql_token.cc rql_parser.cc rql_scanner.hh rql_token.h rql_parser.hh: rql.cg
+	cppcc rql.cg
+
+.PHONY: clean
+
+clean:
+	-rm -f *.o
+	-rm -f *~
+# dependencies
+nodes.cc: nodes.hh node_exceptions.hh
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/README	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,6 @@
+
+le parser est généré par un outil qui s'appelle cppcc
+http://cppcc.sourceforge.net/
+
+faut en faire un paquet Debian...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/boost_module.cc	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,72 @@
+
+
+#include <Python.h>
+#include <boost/python.hpp>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <list>
+#include <exception>
+#include "rql_parser.hh"
+#include "nodes.hh"
+using namespace boost::python;
+using namespace cppcc;
+
+static void translate_scan( const cppcc::ScanException& exc )
+{
+	PyErr_SetString( PyExc_RuntimeError, exc.what() );	
+}
+static void translate_parse( const cppcc::ParseException& exc )
+{
+	PyErr_SetString( PyExc_RuntimeError, exc.what() );	
+}
+
+void my_set_types( RQLExpression& expr, dict d )
+{
+    TypeDict td;
+    object keys = d.keys();
+    int len = extract<int>(keys.attr("__len__")() );
+    for(int i=0;i<len;++i) {
+	td.add_type( extract<const char*>(keys[i]) );
+    }
+    expr.set_types( td );
+}
+
+BOOST_PYTHON_MODULE(rqlparser)
+{
+
+
+    class_<RQLNode>("Node")
+	.def("get_children",&RQLNode::get_children, return_internal_reference<1>() )
+	.def("append", &RQLNode::append )
+	.def("visit", &RQLNode::visit )
+	;
+    class_< nodes_list_t >("NodeList")
+	.def("__iter__", iterator< nodes_list_t >());
+
+    class_<RQLVisitor>("RQLVisitor") ;
+    class_<BinaryOp, bases<RQLNode> >("BinaryOp", no_init);
+    class_<ExprNode, bases<RQLNode> >("ExprNode", no_init);
+    class_<VarNode, bases<RQLNode> >("VarNode", no_init )
+	.add_property("name", make_function( &VarNode::getname, return_value_policy<copy_const_reference>() ) )
+	;
+
+    class_<StmtNode,bases<RQLNode> >("stmt", no_init)
+	.def("add_main_variable", &StmtNode::add_main_variable )
+	.def("add_main_relation", &StmtNode::add_main_relation )
+	.def("get_variable", &StmtNode::get_variable, return_internal_reference<1>() )
+	.def("get_type", &StmtNode::get_type, return_internal_reference<1>() )
+	
+	;
+
+    register_exception_translator<cppcc::ScanException>(&translate_scan);
+    register_exception_translator<cppcc::ParseException>(&translate_parse);
+    
+    class_<RQLExpression>("RQLExpression")
+	.def("parse",(int (RQLExpression::*)(const std::string&))&RQLExpression::parse )
+	.def("root", &RQLExpression::RootNode, return_internal_reference<1>() )
+	.def("set_types", my_set_types )
+	.def("show_types", &RQLExpression::show_types )
+	;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/node_exceptions.hh	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,36 @@
+/* -*- mode:c++ -*- */
+
+#ifndef __NODE_EXCEPTIONS_HH__
+#define __NODE_EXCEPTIONS_HH__
+
+#include "rql_parser.hh"
+
+class UnknownTypeException : public cppcc::ParseException
+{
+  public:
+    
+    UnknownTypeException (const std::string &type_ ) :
+      message("Unknown type:")
+    {
+	message += type_;
+    }
+    
+    ~UnknownTypeException () throw ()
+    {}
+    
+    virtual operator std::string () const
+    {
+      return message;
+    }
+    
+    virtual const char* what () throw ()
+    {
+      return message.c_str();
+    }
+    
+  private:
+  
+    std::string message;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/nodes.cc	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,462 @@
+
+
+#include "nodes.hh"
+#include <iostream>
+#include <string>
+#include <assert.h>
+#include "rql_scanner.hh"
+#include "rql_parser.hh"
+#include "node_exceptions.hh"
+#include <cctype>
+
+using namespace std;
+
+std::string unquote( std::string& str )
+{
+    std::string s;
+    std::string::iterator it;
+    bool one_slash = false;
+    char c;
+    c = str[0];
+    s.assign(str, 1, str.size()-2 );
+    it = s.begin();
+
+    while(it!=s.end()) {
+	if (one_slash) {
+	    one_slash = false;
+	    if (*it=='\\') {
+		it = s.erase(it);
+		continue;
+	    }
+	    if (*it==c) {
+		--it;
+		it = s.erase(it);
+	    }
+	} else if (*it=='\\') {
+	    one_slash = true;
+	}
+	++it;
+    }
+    return s;
+}
+
+bool is_r_type( std::string& str )
+{
+    std::string::iterator it;
+    for (it=str.begin();it!=str.end();++it) {
+	if (*it=='_')
+	    continue;
+	if (!islower(*it))
+	    return false;
+    }
+    return true;
+}
+bool is_e_type( std::string& str )
+{
+    std::string::iterator it;
+    it = str.begin();
+    if (!isupper(*it))
+	return false;
+    ++it;
+    for (;it!=str.end();++it) {
+	if (!islower(*it))
+	    return false;
+    }
+    return true;
+}
+
+bool is_funcname( std::string& str )
+{
+    std::string::iterator it;
+    for (it=str.begin();it!=str.end();++it) {
+	if (false)
+	    return false;
+    }
+    return true;
+}
+
+bool is_var( std::string& str )
+{
+    std::string::iterator it;
+    it = str.begin();
+    if (!isupper(*it)) {
+	return false;
+    }
+    ++it;
+    for (;it!=str.end();++it) {
+	if (isdigit(*it))
+	    continue;
+	if (*it == '_')
+	    continue;
+	if (!isupper(*it))
+	    return false;
+    }
+    return true;
+}
+
+/* display nodes */
+void RQLNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "RQLNode(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void RQLNode::display_children( ostream& sout, int level )
+{
+    if (m_children.size()>1) {
+	nodes_list_t::iterator i=m_children.begin();
+	int idx = 0;
+	do {
+	    sout << "arg" << idx <<"=";
+	    (*i)->display( sout, level );
+	    ++i;
+	    ++idx;
+	    if (i!=m_children.end() )
+		sout << "," << endl;
+	} while (i!=m_children.end() );
+    } else if (m_children.size()==1) {
+	(*m_children.begin())->display( sout, 0 );
+    }
+}
+
+void Constant::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "Constant(";
+    sout << type << ", ";
+    if (type=="INT") {
+	sout << intval;
+    } else if (type=="FLOAT") {
+	sout << floatval;
+    } else {
+	sout << strval;
+    }
+    sout << ")";
+    assert(m_children.size()==0);
+}
+
+void BinaryOp::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "BinaryOp(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void ExprNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "ExprNode(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void VarNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "VarNode(" << name << ")";
+    assert(m_children.size()==0);
+    sout << ")";
+}
+
+/* XXX
+void TypeNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "TypeNode(" << name << ")";
+    assert(m_children.size()==0);
+    sout << ")";
+}
+*/
+
+void StmtNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "StmtNode(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void RelNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "RelNode( not=" << _not << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void OrNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "OrNode( not=" << _not << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void AndNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "AndNode( not=" << _not << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void RelationNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "RelationNode( not=" << _not << ", type=" << rtype << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void ComparisonNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "ComparisonNode( " << cmp_op << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void GroupNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "GroupNode(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void SortNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "SortNode(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+void SortTermNode::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "SortTermNode( order=" << ordering << ",";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+
+/* XXX
+void VariableRef::display( ostream& sout, int level )
+{
+    string indent( level, ' ' );
+    sout << indent << "VariableRef(";
+    display_children( sout, level+1 );
+    sout << ")";
+}
+*/
+
+ostream& operator<<( ostream& sout, RQLNode& node )
+{
+    node.display( sout );
+    return sout;
+}
+
+void StmtNode::add_main_variable( string& etype, VarNode* v )
+{
+    main_variables.push_back( var_pair_t(etype,v) );
+}
+
+void StmtNode::add_main_relation( RelationNode* v )
+{
+    main_relations.push_back( v );
+}
+
+VarNode* StmtNode::get_variable( const string& varname )
+{
+    VarNode* var;
+/*    var = varmap[varname];
+    if (!var) {
+	var = new VarNode( varname );
+	varmap[varname] = var;
+    }
+*/
+    var = new VarNode( varname );
+    return var;
+}
+
+ExprNode* StmtNode::get_type( const string& typname )
+{
+    if (typedict) {
+	if (!typedict->has_type( typname ))
+	    throw UnknownTypeException(typname);
+    }
+    return new Constant( "etype", typname );
+}
+
+/* Visitor callbacks */
+#if 0
+#define VISITDBG()  std::cout << typeid(*this).name() << std::endl
+#else
+#define VISITDBG()
+#endif
+
+void RQLNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitRQLNode( this );
+}
+
+void BinaryOp::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitBinaryOp( this );
+}
+
+void ExprNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitExpr( this );
+}
+
+void VarNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitVar( this );
+}
+
+void Constant::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitConstant( this );
+}
+
+void FuncNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitFunc( this );
+}
+
+void MathExpression::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitMathExpression( this );
+}
+
+void StmtNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitStmt( this );
+}
+
+void SelectStmt::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitSelect( this );
+}
+void InsertStmt::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitInsert( this );
+}
+void DeleteStmt::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitDelete( this );
+}
+void UpdateStmt::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitUpdate( this );
+}
+void SortTermNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitSortTerm( this );
+}
+void SortNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitSort( this );
+}
+void GroupNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitGroup( this );
+}
+void RelNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitRel( this );
+}
+void AndNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitAnd( this );
+}
+void OrNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitOr( this );
+}
+void RelationNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitRelation( this );
+}
+void ComparisonNode::visit(RQLVisitor* visitor)
+{
+    VISITDBG();
+    visitor->visitComparison( this );
+}
+
+/* Node types */
+
+
+
+/* DisplayVisitor */
+
+
+void DisplayVisitor::visitConstant( Constant* node )
+{
+    node->display( out, 0 );
+}
+
+
+void DisplayVisitor::defaultVisit( RQLNode* node ) {
+    out << typeid(*node).name() << "[" << (void*)node << "](";
+    nodes_list_t::iterator it=node->get_children().begin();
+    while(it!=node->get_children().end())
+    {
+	(*it)->visit( this );
+	++it;
+	if (it!=node->get_children().end()) {
+	    out<<",";
+	}
+    }
+    out << ")";
+}
+
+
+int RQLExpression::parse( const std::string& input )
+{
+    std::istringstream istr( input );
+
+    cppcc::RqlParser s( &istr );
+    if (root) delete root;
+    root = s.Goal( &types );
+    return 0;
+}
+
+int RQLExpression::parse( std::istream& stream )
+{
+    cppcc::RqlParser s( &stream );
+    if (root) delete root;
+    root = s.Goal( &types );
+    return 0;
+}
+
+void RQLExpression::show_types()
+{
+    std::cout << "Types:" << std::endl;
+    for( string_set_t::iterator i=types.typeset.begin();i!=types.typeset.end();++i ) {
+	std::cout << *i << std::endl;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/nodes.hh	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,358 @@
+/* -*- mode:c++ -*- */
+
+#ifndef __NODES_HPP__
+#define __NODES_HPP__
+
+
+//#include <Python.h>
+#include <map>
+#include <string>
+#include <list>
+#include <iostream>
+#include <set>
+#include <typeinfo>
+
+
+class RQLVisitor;
+class RelationNode;
+class RQLNode;
+class VarNode;
+
+typedef std::set<std::string> string_set_t;
+typedef std::list<RQLNode*> nodes_list_t;
+typedef std::map<std::string,VarNode*> var_map_t;
+typedef std::pair<std::string,VarNode*> var_pair_t;
+typedef std::list< var_pair_t > var_list_t;
+typedef std::list< RelationNode* > rel_list_t;
+
+#define DEBUG 0
+
+std::string unquote( std::string& str );
+
+bool is_r_type( std::string& str );
+bool is_e_type( std::string& str );
+bool is_funcname( std::string& str );
+bool is_var( std::string& str );
+
+
+class TypeDict {
+public:
+    void add_type( const char* str ) { typeset.insert( std::string(str) ); }
+
+    bool has_type( const std::string& type_name ) {
+	string_set_t::iterator it = typeset.find( type_name );
+	if (it == typeset.end()) {
+	    return false;
+	}
+	return true;
+    }
+
+    string_set_t typeset;
+};
+
+
+class RQLNode {
+public:
+    RQLNode() {
+#if DEBUG
+    std::cout<< typeid(this).name() << "(" << (void*)this << ")" << std::endl;
+#endif
+    }
+    virtual ~RQLNode() {
+#if DEBUG
+	std::cout<< "~" << typeid(this).name() << "(" << (void*)this << ")" << "{";
+#endif
+	for( nodes_list_t::iterator it=m_children.begin(); it!=m_children.end(); ++it ) {
+	    delete *it;
+	}	 
+#if DEBUG
+	std::cout<< "}" << std::endl;
+#endif
+    }
+        
+    nodes_list_t& get_children() { return m_children; }
+
+    virtual void visit( RQLVisitor* visitor );
+
+    void append( RQLNode* node ) { m_children.push_back( node ); }
+
+    virtual void display( std::ostream& sout, int level=0 );
+    void display_children( std::ostream& sout, int level );
+
+    friend class RQLVisitor;
+protected:
+    nodes_list_t  m_children;
+
+};
+
+
+std::ostream& operator<<( std::ostream& sout, RQLNode& node );
+
+class EType {
+};
+
+
+class BinaryOp : public RQLNode {
+public:
+    BinaryOp() {}
+    BinaryOp( RQLNode* lhs, RQLNode* rhs ) { append(lhs); append(rhs); }
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+
+
+
+class ExprNode : public RQLNode {
+public:
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class VarNode : public ExprNode {
+public:
+    VarNode( const std::string& _name ):name(_name) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+    const std::string& getname() const { return name; }
+    std::string name;
+};
+
+/*
+class TypeNode : public ExprNode {
+public:
+    TypeNode( const std::string& _name ):name(_name) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    std::string name;
+};
+*/
+
+class Constant : public ExprNode {
+public:
+    Constant( const std::string& _type, const std::string& _val ):type(_type),strval(_val) {}
+    Constant( const std::string& _type, int _val ):type(_type),intval(_val) {}
+    Constant( const std::string& _type, double _val ):type(_type),floatval(_val) {}
+
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+
+    std::string type;
+    std::string strval;
+    int intval;
+    double floatval;
+};
+
+class FuncNode : public ExprNode {
+public:
+    FuncNode( const std::string& _name ):name(_name) {}
+    virtual void visit( RQLVisitor* visitor );
+    std::string name;
+};
+
+/*
+class VariableRef : public RQLNode {
+public:
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+*/
+
+class MathExpression : public ExprNode {
+public:
+    MathExpression( std::string _op, ExprNode* lhs, ExprNode* rhs ):op(_op)
+    {
+	append(lhs);
+	append(rhs);
+    }
+    virtual void visit( RQLVisitor* visitor );
+    std::string op;
+};
+
+class StmtNode : public RQLNode {
+public:
+    StmtNode( TypeDict* dct):typedict(dct) {}
+    void add_main_variable( std::string& etype, VarNode* v );
+    void add_main_relation( RelationNode* v );
+
+    VarNode* get_variable( const std::string& varname );
+    ExprNode* get_type( const std::string& typname );
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+
+
+    var_map_t varmap;
+    var_list_t main_variables;
+    rel_list_t main_relations;
+    
+    std::streampos stmt_start, stmt_end;
+    TypeDict* typedict;
+};
+
+class SelectStmt : public StmtNode {
+public:
+    SelectStmt( TypeDict * dct ):StmtNode(dct),distinct(false),limit(-1),offset(0) {}
+    ~SelectStmt() {
+	for( nodes_list_t::iterator it=selected.begin(); it!=selected.end(); ++it ) {
+	    delete *it;
+	}	
+    }
+    void set_statement_type( const std::string& type ) { statement_type = type; }
+    void append_selected( RQLNode* node ) { selected.push_back( node ); }
+    void set_limit( int _limit ) { limit = _limit; }
+    void set_offset( int _offset ) { offset = _offset; }
+    virtual void visit( RQLVisitor* visitor );
+    bool distinct;
+    int limit, offset;
+    std::string statement_type;
+    nodes_list_t selected;
+};
+
+class InsertStmt : public StmtNode {
+public:
+    InsertStmt( TypeDict * dct ):StmtNode(dct) {}
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class UpdateStmt : public StmtNode {
+public:
+    UpdateStmt( TypeDict * dct ):StmtNode(dct) {}
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class DeleteStmt : public StmtNode {
+public:
+    DeleteStmt( TypeDict * dct ):StmtNode(dct) {}
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class SortTermNode : public RQLNode {
+public:
+    SortTermNode( ExprNode* e, bool _ordering ):expr(e),ordering(_ordering) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+    ExprNode* expr;
+    bool ordering;
+};
+
+class SortNode : public RQLNode {
+public:
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class GroupNode : public RQLNode {
+public:
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+
+};
+
+
+class RelNode : public BinaryOp {
+public:
+    RelNode():BinaryOp(),_not(false) {}
+    RelNode( RelNode* lhs, RelNode* rhs ):BinaryOp(lhs,rhs),_not(false) {}
+
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+    bool _not;
+};
+
+class OrNode : public RelNode {
+public:
+    OrNode( RelNode* lhs, RelNode* rhs ):RelNode(lhs,rhs) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class AndNode : public RelNode {
+public:
+    AndNode( RelNode* lhs, RelNode* rhs ):RelNode(lhs,rhs) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+};
+
+class RelationNode : public RelNode {
+public:
+    RelationNode( const std::string& _rtype ):rtype(_rtype) {}
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+
+    std::string rtype;
+};
+
+class ComparisonNode : public ExprNode {
+public:
+    ComparisonNode( const std::string _cmp_op, ExprNode* rhs):cmp_op(_cmp_op)
+    {
+	append(rhs);
+    }
+    virtual void display( std::ostream& sout, int level=0 );
+    virtual void visit( RQLVisitor* visitor );
+    std::string cmp_op;
+};
+
+class RQLVisitor {
+public:
+    virtual ~RQLVisitor() {}
+    virtual void visitRQLNode( RQLNode* node ) { defaultVisit(node); }
+    virtual void visitBinaryOp( BinaryOp* node ) { defaultVisit(node); }
+    virtual void visitExpr( ExprNode* node ) { defaultVisit(node); }
+    virtual void visitVar( VarNode* node ) { defaultVisit(node); }
+    virtual void visitConstant( Constant* node ) { defaultVisit(node); }
+    virtual void visitFunc( FuncNode* node ) { defaultVisit(node); }
+    virtual void visitMathExpression( MathExpression* node ) { defaultVisit(node); }
+    virtual void visitStmt( StmtNode* node ) { defaultVisit(node); }
+    virtual void visitSelect( SelectStmt* node ) { defaultVisit(node); }
+    virtual void visitInsert( InsertStmt* node ) { defaultVisit(node); }
+    virtual void visitDelete( DeleteStmt* node ) { defaultVisit(node); }
+    virtual void visitUpdate( UpdateStmt* node ) { defaultVisit(node); }
+    virtual void visitSortTerm( SortTermNode* node ) { defaultVisit(node); }
+    virtual void visitSort( SortNode* node ) { defaultVisit(node); }
+    virtual void visitGroup( GroupNode* node ) { defaultVisit(node); }
+    virtual void visitRel( RelNode* node ) { defaultVisit(node); }
+    virtual void visitAnd( AndNode* node ) { defaultVisit(node); }
+    virtual void visitOr( OrNode* node ) { defaultVisit(node); }
+    virtual void visitRelation( RelationNode* node ) { defaultVisit(node); }
+    virtual void visitComparison( ComparisonNode* node ) { defaultVisit(node); }
+
+    virtual void defaultVisit( RQLNode* node ) {
+	for(nodes_list_t::iterator it=node->get_children().begin();it!=node->get_children().end();++it)
+	{
+	    (*it)->visit( this );
+	}
+    }
+};
+
+
+class DisplayVisitor : public RQLVisitor {
+public:
+    DisplayVisitor( std::ostream& _out ):out(_out) {}
+
+    
+    virtual void visitConstant( Constant* node );
+    virtual void defaultVisit( RQLNode* node );
+
+protected:
+    std::ostream& out;
+};
+
+
+class RQLExpression {
+public:
+    RQLExpression():root(NULL) {}
+    StmtNode& RootNode() { return *root; }
+
+    void set_types( const TypeDict& td ) { types=td; }
+    int parse( const std::string& input );
+    int parse( std::istream& stream );
+
+    void show_types();
+
+protected:
+    TypeDict  types;
+    StmtNode* root;
+};
+
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/rql.cg	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,486 @@
+ /* -*- mode:c++ -*- */
+
+
+OPTIONS
+{
+  DEBUG_SCANNER = false
+  DEBUG_PARSER = false
+  //  OWN_STRINGS = true; DEPRECATED !
+  // PROFILING_FILE = "profile.dat";
+}
+
+{
+#include "nodes.hh"
+#include <string>
+#include <assert.h>
+#include <iostream>
+#include <cctype>
+#define MYDEBUG 0
+
+
+}
+
+TOKEN RqlToken
+{
+ public:
+    operator int() { return atoi(image().c_str()); }
+    operator double() { return atof(image().c_str()); }
+    void toupper() {
+	std::string& s = image();
+	std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) std::toupper);
+    }
+    void tolower() {
+	std::string& s = image();
+	std::transform(s.begin(), s.end(), s.begin(), (int(*)(int)) std::tolower);
+    }
+}
+
+
+
+SCANNER RqlScanner
+{
+
+    {
+    public:
+	void skipTo( const std::string& tok )
+	    {
+		RqlToken* token = la();
+		while( !_eof && token->image()!=tok ) {
+		    consume();
+		}
+	    }
+	std::streampos getStreamPos()
+	    {
+		std::streampos pos;
+		if (!_eof) {
+		    pos = inputStream->tellg() - std::streampos(_eob-_ch);
+		    if (pos<0) 
+			return std::streampos(0);
+		    return pos;
+		} else {
+		    inputStream->clear();
+		    inputStream->seekg (0, std::ios::end);
+		    return inputStream->tellg() - std::streampos(_eob-_ch);
+		}
+	    }
+	bool is_next_vars_decl() {
+	    RqlToken* _la;
+	    _la = la();
+	    if ( is_e_type(_la->image()) ) {
+		_la = la(1);
+		if ( is_var( _la->image() ) ) {
+		    return true;
+		}
+	    }
+	    return false;
+	}
+    }
+	  
+<START> SKIP {
+    <ws: " " | "\t" | "\v" | "\f" | "\n" > 
+	
+}
+
+<START> MORE {
+	<LONG_COMMENT1: "/*" > { pushState(LONG_COMMENT); }
+}
+
+<LONG_COMMENT> MORE
+{
+  <LONG_COMMENT2: "\n"/* | "\r" | "\n\r" | "\r\n"*/ > { newLine(); }
+  <LONG_COMMENT3: ~['*','\n','\r']* > 
+  <LONG_COMMENT4: ['*']+~['/','\n'] > 
+  <LONG_COMMENT5: ['*']+"\n" > { newLine(); }
+}
+
+<LONG_COMMENT> SKIP
+{
+  <LONG_COMMENT: ['*']+"/" > { popState(); }
+}
+
+<START> KEYWORD
+{
+    <DELETE:      ['D','d'] ['E','e'] ['L','l'] ['E','e'] ['T','t'] ['E','e'] >
+    <SET:         ['S','s'] ['E','e'] ['T','t']>
+    <INSERT:      ['I','i'] ['N','n'] ['S','s'] ['E','e'] ['R','r'] ['T','t']>
+    <DISTINCT:    ['D','d'] ['I','i'] ['S','s'] ['T','t'] ['I','i'] ['N','n'] ['C','c'] ['T','t'] >
+    <WHERE:       ['W','w'] ['H','h'] ['E','e'] ['R','r'] ['E','e'] > /* where */
+    <OR:          ['O','o'] ['R','r']>  /* or */
+    <AND:         ['A','a'] ['N','n'] ['D','d']> /* and */
+    <NOT:         ['N','n'] ['O','o'] ['T','t']> /* not */
+    <GROUPBY:     ['G','g'] ['R','r'] ['O','o'] ['U','u'] ['P','p'] ['B','b'] ['Y','y']> /* groupby */
+    <ORDERBY:     ['O','o'] ['R','r'] ['D','d'] ['E','e'] ['R','r'] ['B','b'] ['Y','y']> /* orderby */
+    <SORT_ASC:    ['A','a']['S','s']['C','c']>
+    <SORT_DESC:   ['D','d']['E','e']['S','s']['C','c']>
+    <LIMIT:       ['L','l']['I','i']['M','m']['I','i']['T','t']>
+    <OFFSET:      "OFFSET" | "offset">
+    <DATE:        "TODAY" | "today" > { token->image() = "TODAY"; }
+    <DATETIME:    "NOW" | "now" > { token->image() = "NOW"; }
+    <RQLNULL:     "NULL" | "null" >
+    <SEMICOLON:   ";">
+    <COLON:       ":">
+    <COMA:        ",">
+    <LPAREN:      "(">
+    <RPAREN:      ")">
+}
+
+<START> TOKEN
+{
+    <#L: ['a'-'z', 'A'-'Z', '_']>
+    <CMP_OP:      "<=" | "<" | ">=" | ">" | "~=" | "=" | "LIKE" | "like">
+    <BOOLEAN:     ['T','t']['R','r']['U','u']['E','e']|['F','f']['A','a']['L','l']['S','s']['E','e'] >
+	{ token->tolower();  }
+/*    <FUNCTION:    "@" ['A'-'Z','a'-'z']+ [' ','\t','\n']* "(">*/
+    <SYMBOL: ['A'-'Z','a'-'z','_'] ['A'-'Z','a'-'z','0'-'9','_']*>
+/*    <R_TYPE:      ['a'-'z','_']+>
+    <E_TYPE:      ['A'-'Z'] ['a'-'z']+>
+    <VARIABLE:    ['A'-'Z'] ['A'-'Z','0'-'9','_']*> */
+    <FLOAT:       ['0'-'9']+ "." ['0'-'9']*>
+    <INT:         ['0'-'9']+>
+    <SUBSTITUTE:  "%(" ['A'-'Z','a'-'z','_','0'-'9']+ ")s">
+	{ token->image() = token->image().substr(2,token->image().size()-4 ); }
+    <STRING: ( "\"" ( ~['\"'] | "\\\"" )* "\"" ) | ( "\'" ( ~['\''] | "\\\'" )* "\'" ) >
+	{ token->image() = unquote(token->image()); }
+    <ADD_OP:      "+"|"-">
+    <MUL_OP:      "*"|"/">
+
+}
+	     /* mieux: ~['\'','\\'] | ... */
+
+}
+
+
+PARSER RqlParser
+{
+    (StmtNode*) Goal( TypeDict* types )
+	{
+	    { 
+		DeleteStmt *tmp1=0;
+		InsertStmt *tmp2=0;
+		UpdateStmt *tmp3=0;
+		SelectStmt *tmp4=0;
+		StmtNode   *tmp=0;
+		std::streampos startpos = scanner.getStreamPos();
+
+		
+	    } (
+	    ( <DELETE> { tmp1 = new DeleteStmt( types ); } Delete( tmp1 ) <SEMICOLON> { tmp = tmp1; } )
+		| ( { tmp2 = new InsertStmt( types ); } <INSERT> Insert( tmp2 ) <SEMICOLON> { tmp = tmp2; } ) 
+		| ( { tmp3 = new UpdateStmt( types ); } <SET> Update( tmp3 ) <SEMICOLON> { tmp = tmp3; } )
+		| ( { tmp4 = new SelectStmt( types ); } Select( tmp4 ) <SEMICOLON> { tmp = tmp4; } )
+	    )
+		{
+		    tmp->stmt_start = startpos;
+		    tmp->stmt_end = scanner.getStreamPos();
+		    return tmp;
+		}
+	}
+    
+    /* Deletion */
+    (RQLNode*) Delete( DeleteStmt* parent ) { 
+	( LOOKAHEAD({scanner.is_next_vars_decl()}) ( Vars_Decl(parent) Restr(parent)? )
+          | ( Rels_Decl(parent) Restr(parent)? )
+	 )
+	    { return parent; }
+    }
+
+    
+    /* Insertion */
+    (RQLNode*) Insert( InsertStmt* parent ) {
+	Vars_Decl(parent) Insert_Rels(parent)?
+	    { return parent; }
+    }
+
+    (RQLNode*) Insert_Rels( InsertStmt* parent ) {
+	<COLON> Rels_Decl(parent) Restr(parent)?
+	    { return parent; }
+    }
+
+
+    /* Update */
+    (RQLNode*) Update( UpdateStmt* parent ) {
+	Rels_Decl(parent) Restr(parent)?
+	    { return parent; }
+    }
+
+    /* Selection */
+    (RQLNode*) Select( SelectStmt* parent ) {
+	( <DISTINCT> { parent->distinct = true; } )? Select_Base(parent)
+	    { return parent; }
+    }
+
+    (RQLNode*) Select_Base( SelectStmt* parent ) {
+	{ std::string etype; }
+	(etype = E_Type()
+	 Selected_Terms( parent ) Restr( parent )?
+	 Group( parent )?
+	 Sort( parent )?
+	 ( Limit_Offset( parent ) )? )
+	    { parent->set_statement_type( etype ); return parent; }
+    }
+
+    (RQLNode*) Selected_Terms( SelectStmt* parent ) {
+	{ RQLNode* added_expr=0; }
+	added_expr = Added_Expr( parent ) { parent->append_selected( added_expr ); }
+	( <COMA> added_expr = Added_Expr( parent ) { parent->append_selected( added_expr ); } ) *
+	    { return parent; }
+    }
+    
+    /* Group and sorts */
+
+    (RQLNode*) Group( StmtNode* parent ) {
+	{
+	    GroupNode *group = new GroupNode();
+	    VarNode *v=0;
+	}
+	<GROUPBY> v = Var( parent ) { group->append( v ); } 
+	( <COMA> v = Var( parent ) { group->append( v ); } )*
+	    { parent->append( group ); return parent; }
+    }
+
+    (RQLNode*) Sort( StmtNode* parent ) {
+	{
+	    SortNode *sort = new SortNode();
+	    SortTermNode* term=0;
+	}
+	<ORDERBY> term = Sort_Term( parent ) { sort->append( term ); }
+	(<COMA> term = Sort_Term( parent ) { sort->append( term ); } ) *
+	    { parent->append( sort ); return parent; }
+    }
+
+    (SortTermNode*) Sort_Term( StmtNode* parent ) {
+	{ ExprNode* added_expr=0; bool ordering = true }
+	added_expr = Added_Expr( parent ) 
+	    ( <SORT_DESC> { ordering = false; } 
+	      | <SORT_ASC> { ordering = true; } ) ?
+	    { return new SortTermNode( added_expr, ordering ); }
+    }
+
+    /* Limit and Offset */
+
+    (RQLNode*) Limit_Offset( SelectStmt* parent ) {
+	( Limit( parent )? Offset( parent )?) { return parent; }
+    }
+
+    () Limit( SelectStmt* parent ) {
+	<LIMIT> <INT> { parent->set_limit( int(*token) ); }
+    }
+    () Offset( SelectStmt* parent ) {
+	<OFFSET> <INT> { parent->set_offset( int(*token) ); }
+    }
+    
+    /* Restriction Statements */
+
+    (RQLNode*) Restr( StmtNode* parent ) {
+	{ RelNode* rels=0; }
+	<WHERE> rels = Rels( parent ) { parent->append( rels ); return parent; }
+    }
+    
+    (RelNode*) Rels( StmtNode* parent ) {
+	{ RelNode *lrel=0, *rrel=0; }
+	lrel = Ored_Rels( parent )
+	    ( <COMA> rrel = Ored_Rels( parent )
+		{ lrel = new AndNode( lrel, rrel ); } )*
+	    { return lrel; }
+    }
+
+    (RelNode*) Ored_Rels( StmtNode* parent ) {
+	{ RelNode *lrel=0, *rrel=0; }
+	lrel = Anded_Rels( parent )
+	    ( <OR> rrel = Anded_Rels( parent )
+		{ lrel = new OrNode( lrel, rrel ); } )*
+	    { return lrel; }
+    }
+
+    (RelNode*) Anded_Rels( StmtNode* parent ) {
+	{ RelNode *lrel=0, *rrel=0; }
+	lrel = Rel( parent )
+	    ( <AND> rrel = Rel( parent )
+		{ lrel = new AndNode( lrel, rrel ); } )*
+	    { return lrel; }
+    }
+
+    (RelNode*) Rel( StmtNode* parent ) {
+	{
+	    bool negated = false;
+	    RelNode *rel=0;
+	}
+	(( ( <NOT> { negated = true; } )?
+	   rel = Base_Rel( parent ) { rel->_not = negated;} )
+	 | ( <LPAREN> rel = Rels(parent) <RPAREN>  ))
+	    { return rel; }
+    }
+
+    (RelationNode*) Base_Rel( StmtNode* parent ) {
+	{
+	    RelationNode *e=0;
+	    VarNode *var=0;
+	    std::string rtype;
+	    ExprNode *expr=0;
+	}
+	var = Var(parent)
+        rtype = R_Type()
+	expr = Expr(parent)
+	    {
+		e = new RelationNode( rtype );
+		e->append(var);
+		assert(expr);
+		e->append(expr);
+		return e;
+	    }
+    }
+
+
+    (std::string) R_Type() {
+	<SYMBOL> {
+	    if (is_r_type( token->image() ))
+		return token->image();
+	    else
+		throw ScanException( token->bPos, "Expected R_Type"); 
+	}
+    }
+    (std::string) E_Type() {
+	<SYMBOL> {
+	    if (is_e_type( token->image() ))
+		return token->image();
+	    else
+		throw ScanException( token->bPos, "Expected E_Type"); 
+	}
+    }
+
+    /* common statements */
+
+    (RQLNode*) Vars_Decl( StmtNode* parent ) {
+	{
+	    VarNode *v=0;
+	    std::string etype;
+	}
+	etype = E_Type()
+	v = Var(parent) {parent->add_main_variable( etype, v ); }
+	( <COMA> etype = E_Type()
+	  v = Var(parent) {
+	    parent->add_main_variable( etype, v );
+	} ) *
+	    { return parent; }
+    }
+
+    (RQLNode*) Rels_Decl( StmtNode* parent ) { 
+	{ RelationNode *rel=0; }
+	rel = Simple_Rel( parent ) { parent->add_main_relation( rel ); }
+	( <COMA> rel = Simple_Rel( parent ) { parent->add_main_relation( rel ); } )*
+	    { return parent; }
+    }
+
+    (RelationNode*) Simple_Rel( StmtNode* parent ) {
+	{
+	    RelationNode *e=0;
+	    VarNode *v=0;
+	    ExprNode *expr=0;
+	    std::string rtype;
+	}
+	v = Var(parent) rtype = R_Type()
+	    expr = Added_Expr(parent)
+	    {
+		e = new RelationNode(rtype);
+		e->append( v );
+		e->append( expr );
+		return e;
+	    }
+    }
+    
+    (ExprNode*) Expr( StmtNode* parent ) {
+	{
+	    ExprNode *expr=0, *added_expr=0;
+	    std::string cmp_op;
+	}
+	( ( (<CMP_OP> { cmp_op = token->image(); })
+	    added_expr = Added_Expr( parent ) { expr = new ComparisonNode( cmp_op, added_expr ); } )
+	  | ( added_expr = Added_Expr( parent ) { expr = new ComparisonNode( "=", added_expr ); } ))
+	    { return expr; }
+    }
+
+    (ExprNode*) Added_Expr( StmtNode* parent ) {
+	{
+	    ExprNode *lhs=0, *rhs=0;
+	    std::string add_op;
+	}
+	lhs = Muled_Expr( parent )
+	    ( <ADD_OP> { add_op = token->image(); }
+	      rhs = Muled_Expr( parent ) { lhs = new MathExpression( add_op, lhs, rhs ); } )*
+	    { return lhs; }
+    }
+
+    (ExprNode*) Muled_Expr( StmtNode* parent ) {
+	{
+	    ExprNode *lhs=0, *rhs=0;
+	    std::string mul_op;
+	}
+	lhs = Base_Expr( parent )
+	    ( <MUL_OP> { mul_op = token->image(); }
+	      rhs = Base_Expr( parent ) { lhs = new MathExpression( mul_op, lhs, rhs ); } )*
+	    { return lhs; }
+    }
+    
+
+    (ExprNode*) Base_Expr( StmtNode* parent ) {
+	{ ExprNode* expr=0; }
+	( expr = Const()
+	  | expr = Var_E_Type_or_Func(parent)
+	  | <LPAREN> expr = Added_Expr(parent) <RPAREN> )
+	    { assert(expr); return expr; }
+    }
+
+
+    (ExprNode*) Var_E_Type_or_Func( StmtNode* parent ) {
+	{
+	    std::string name;
+	    FuncNode *func=0;
+	    ExprNode *expr=0;
+	}
+	<SYMBOL> { name =  token->image(); }
+	( <LPAREN> { func = new FuncNode(name ); }
+	  expr = Added_Expr(parent) { func->append( expr ); }
+	  ( <COMA> expr = Added_Expr(parent) { func->append( expr ); } )*
+	  <RPAREN> { return func; }
+	)?
+	    {
+		if (is_var(name)) {
+		    return parent->get_variable( name );
+		}
+		expr = parent->get_type( name );
+		assert(expr);
+#if MYDEBUG
+		std::cout << "E_TYPE ";
+		expr->display( std::cout, 0 );
+		std::cout << std::endl;
+#endif
+		return expr;
+	    }
+    }
+
+    (VarNode*) Var( StmtNode* parent ) {
+	<SYMBOL> {
+	    VarNode* v=0;
+	    if (!is_var( token->image() )) {
+		throw ScanException( token->bPos, "Expected Variable" );
+	    }
+	    v = parent->get_variable( token->image() );
+	    assert(v);
+	    return v;
+	}
+    }
+    
+
+    (ExprNode*) Const() {
+	<RQLNULL>    { return new Constant( "NULL", token->image() ); }
+	| <DATE>     { return new Constant( "Date", token->image() ); }
+	| <DATETIME> { return new Constant( "Datetime", token->image() ); }
+	| <BOOLEAN>  { return new Constant( "Boolean", token->image() ); }
+	| <FLOAT>    { return new Constant( "Float", double(*token) ); }
+	| <INT>      { return new Constant( "Int", int(*token) ); }
+	| <STRING>   { return new Constant( "String", token->image() ); }
+	| <SUBSTITUTE> { return new Constant( "Substitute", token->image() ); }
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/rql_main.cc	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,98 @@
+
+
+#include "rql_parser.hh"
+#include <fstream>
+#include <iostream>
+#include "nodes.hh"
+#include <string>
+
+using namespace cppcc;
+
+
+void skip( std::istream& f )
+{
+    char c;
+    std::cout << "Skipping:";
+    while(f) {
+	f.get(c);
+	std::cout << c;;
+	if (c=='\n')
+	    return ;
+    }
+}
+
+void show_state( std::ifstream& f, std::streampos _start, std::streampos _end )
+{
+    char *buffer;
+    ssize_t sz;
+    std::streampos _saved_pos;
+    _saved_pos = f.tellg();
+    f.seekg( _start );
+    std::cout << "Parsed: ("<<_start<<","<<_end<<")";
+    sz = int(_end-_start)+1;
+    //std::cout << sz << std::endl;
+    buffer = new char[sz];
+    f.read( buffer, _end - _start );
+    std::cout << buffer << std::endl;
+    delete [] buffer;
+    f.seekg( _saved_pos );
+}
+
+
+void recover( RqlParser* s )
+{
+    bool recovered = false;
+    while (!recovered) {
+	try {
+	    s->scanner.switchToState( RqlScanner::START );
+	    s->scanner.skipTo( ";" );
+	    recovered = true;
+	} catch ( ScanException& ex2 )
+	{
+	    // ignore
+	    std::cout << (char)s->scanner.getChar();
+	}
+    }
+}
+
+int main( int argc, char** argv )
+{
+    bool done = false;
+    std::streampos _start, _end;
+    if (argc<2) {
+	std::cout << "Usage: rqlparse rql_file" << std::endl;
+	exit(1);
+    }
+    std::ifstream fin( argv[1] );
+    RqlParser *s = new RqlParser( &fin );
+    TypeDict *types = new TypeDict();
+    StmtNode* goal;
+
+    while (!done) {
+	try {
+	    std::cout << "-------------------------------" << std::endl;
+	    _start = s->scanner.getStreamPos();
+	    if (s->scanner.la()->id == RqlToken::eof)
+		break;
+	    goal = s->Goal( NULL );
+	    DisplayVisitor disp( std::cout );
+	    goal->visit( &disp );
+	    std::cout << std::endl;
+	    std::cout << *goal << std::endl;
+	    _end = s->scanner.getStreamPos();
+	    show_state( fin, _start, _end );
+	    std::cout << "OK" << std::endl;
+	} catch( ScanException& exc ) {
+	    std::cout << std::string(exc) << std::endl;
+	    _end = s->scanner.getStreamPos();
+	    show_state( fin, _start, _end );
+	    recover( s );
+	}
+	catch( ParseException& exc ) {
+	    std::cout << std::string(exc) << std::endl;
+	    _end = s->scanner.getStreamPos();
+	    show_state( fin, _start, _end );
+	    recover( s );
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/rql_parser.cc	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2336 @@
+/******************************************************************
+ * File: rql_parser.cc
+ *
+ * This file was automatically generated by CppCC Version 0.0.8
+ * DO NOT EDIT MANUALLY
+ ******************************************************************/
+
+
+
+#include "rql_parser.hh"
+
+
+#line 155 "rql.cg"
+StmtNode* cppcc::
+#line 16 "rql_parser.cc"
+RqlParser::Goal (
+#line 155 "rql.cg"
+ TypeDict* types )
+#line 20 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 157 "rql.cg"
+ 
+		DeleteStmt *tmp1=0;
+		InsertStmt *tmp2=0;
+		UpdateStmt *tmp3=0;
+		SelectStmt *tmp4=0;
+		StmtNode   *tmp=0;
+		std::streampos startpos = scanner.getStreamPos();
+
+		
+	    ;
+#line 35 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::DELETE)) {
+    consumeToken(RqlToken::DELETE);
+    {
+#line 167 "rql.cg"
+ tmp1 = new DeleteStmt( types ); }
+#line 42 "rql_parser.cc"
+
+    Delete(
+#line 167 "rql.cg"
+ tmp1 );
+#line 47 "rql_parser.cc"
+
+    consumeToken(RqlToken::SEMICOLON);
+    {
+#line 167 "rql.cg"
+ tmp = tmp1; }
+#line 53 "rql_parser.cc"
+
+  } else { 
+    if ((scanner.la()->id == RqlToken::INSERT)) {
+      {
+#line 168 "rql.cg"
+ tmp2 = new InsertStmt( types ); }
+#line 60 "rql_parser.cc"
+
+      consumeToken(RqlToken::INSERT);
+      Insert(
+#line 168 "rql.cg"
+ tmp2 );
+#line 66 "rql_parser.cc"
+
+      consumeToken(RqlToken::SEMICOLON);
+      {
+#line 168 "rql.cg"
+ tmp = tmp2; }
+#line 72 "rql_parser.cc"
+
+    } else { 
+      if ((scanner.la()->id == RqlToken::SET)) {
+        {
+#line 169 "rql.cg"
+ tmp3 = new UpdateStmt( types ); }
+#line 79 "rql_parser.cc"
+
+        consumeToken(RqlToken::SET);
+        Update(
+#line 169 "rql.cg"
+ tmp3 );
+#line 85 "rql_parser.cc"
+
+        consumeToken(RqlToken::SEMICOLON);
+        {
+#line 169 "rql.cg"
+ tmp = tmp3; }
+#line 91 "rql_parser.cc"
+
+      } else { 
+        {
+#line 170 "rql.cg"
+ tmp4 = new SelectStmt( types ); }
+#line 97 "rql_parser.cc"
+
+        Select(
+#line 170 "rql.cg"
+ tmp4 );
+#line 102 "rql_parser.cc"
+
+        consumeToken(RqlToken::SEMICOLON);
+        {
+#line 170 "rql.cg"
+ tmp = tmp4; }
+#line 108 "rql_parser.cc"
+
+      }
+    }
+  }
+  {
+#line 172 "rql.cg"
+
+		    tmp->stmt_start = startpos;
+		    tmp->stmt_end = scanner.getStreamPos();
+		    return tmp;
+		}
+#line 120 "rql_parser.cc"
+
+}
+
+
+
+#line 180 "rql.cg"
+RQLNode* cppcc::
+#line 128 "rql_parser.cc"
+RqlParser::Delete (
+#line 180 "rql.cg"
+ DeleteStmt* parent )
+#line 132 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  if ((
+#line 181 "rql.cg"
+scanner.is_next_vars_decl())
+#line 139 "rql_parser.cc"
+) {
+    Vars_Decl(
+#line 181 "rql.cg"
+parent);
+#line 144 "rql_parser.cc"
+
+    if ((scanner.la()->id == RqlToken::WHERE)) {
+      Restr(
+#line 181 "rql.cg"
+parent);
+#line 150 "rql_parser.cc"
+
+    } else { 
+       /* lambda */
+    }
+  } else { 
+    Rels_Decl(
+#line 182 "rql.cg"
+parent);
+#line 159 "rql_parser.cc"
+
+    if ((scanner.la()->id == RqlToken::WHERE)) {
+      Restr(
+#line 182 "rql.cg"
+parent);
+#line 165 "rql_parser.cc"
+
+    } else { 
+       /* lambda */
+    }
+  }
+  {
+#line 184 "rql.cg"
+ return parent; }
+#line 174 "rql_parser.cc"
+
+}
+
+
+
+#line 189 "rql.cg"
+RQLNode* cppcc::
+#line 182 "rql_parser.cc"
+RqlParser::Insert (
+#line 189 "rql.cg"
+ InsertStmt* parent )
+#line 186 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  Vars_Decl(
+#line 190 "rql.cg"
+parent);
+#line 193 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::COLON)) {
+    Insert_Rels(
+#line 190 "rql.cg"
+parent);
+#line 199 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 191 "rql.cg"
+ return parent; }
+#line 207 "rql_parser.cc"
+
+}
+
+
+
+#line 194 "rql.cg"
+RQLNode* cppcc::
+#line 215 "rql_parser.cc"
+RqlParser::Insert_Rels (
+#line 194 "rql.cg"
+ InsertStmt* parent )
+#line 219 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::COLON);
+  Rels_Decl(
+#line 195 "rql.cg"
+parent);
+#line 227 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    Restr(
+#line 195 "rql.cg"
+parent);
+#line 233 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 196 "rql.cg"
+ return parent; }
+#line 241 "rql_parser.cc"
+
+}
+
+
+
+#line 201 "rql.cg"
+RQLNode* cppcc::
+#line 249 "rql_parser.cc"
+RqlParser::Update (
+#line 201 "rql.cg"
+ UpdateStmt* parent )
+#line 253 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  Rels_Decl(
+#line 202 "rql.cg"
+parent);
+#line 260 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    Restr(
+#line 202 "rql.cg"
+parent);
+#line 266 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 203 "rql.cg"
+ return parent; }
+#line 274 "rql_parser.cc"
+
+}
+
+
+
+#line 207 "rql.cg"
+RQLNode* cppcc::
+#line 282 "rql_parser.cc"
+RqlParser::Select (
+#line 207 "rql.cg"
+ SelectStmt* parent )
+#line 286 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  if ((scanner.la()->id == RqlToken::DISTINCT)) {
+    consumeToken(RqlToken::DISTINCT);
+    {
+#line 208 "rql.cg"
+ parent->distinct = true; }
+#line 295 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  Select_Base(
+#line 208 "rql.cg"
+parent);
+#line 303 "rql_parser.cc"
+
+  {
+#line 209 "rql.cg"
+ return parent; }
+#line 308 "rql_parser.cc"
+
+}
+
+
+
+#line 212 "rql.cg"
+RQLNode* cppcc::
+#line 316 "rql_parser.cc"
+RqlParser::Select_Base (
+#line 212 "rql.cg"
+ SelectStmt* parent )
+#line 320 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 213 "rql.cg"
+ std::string etype; ;
+#line 326 "rql_parser.cc"
+
+  
+#line 214 "rql.cg"
+etype = 
+#line 331 "rql_parser.cc"
+E_Type();
+  Selected_Terms(
+#line 215 "rql.cg"
+ parent );
+#line 336 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    Restr(
+#line 215 "rql.cg"
+ parent );
+#line 342 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::GROUPBY)) {
+    Group(
+#line 216 "rql.cg"
+ parent );
+#line 351 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::ORDERBY)) {
+    Sort(
+#line 217 "rql.cg"
+ parent );
+#line 360 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::LIMIT) || (scanner.la()->id == RqlToken::OFFSET)) {
+    Limit_Offset(
+#line 218 "rql.cg"
+ parent );
+#line 369 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 219 "rql.cg"
+ parent->set_statement_type( etype ); return parent; }
+#line 377 "rql_parser.cc"
+
+}
+
+
+
+#line 222 "rql.cg"
+RQLNode* cppcc::
+#line 385 "rql_parser.cc"
+RqlParser::Selected_Terms (
+#line 222 "rql.cg"
+ SelectStmt* parent )
+#line 389 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 223 "rql.cg"
+ RQLNode* added_expr=0; ;
+#line 395 "rql_parser.cc"
+
+  
+#line 224 "rql.cg"
+added_expr = 
+#line 400 "rql_parser.cc"
+Added_Expr(
+#line 224 "rql.cg"
+ parent );
+#line 404 "rql_parser.cc"
+
+  {
+#line 224 "rql.cg"
+ parent->append_selected( added_expr ); }
+#line 409 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 225 "rql.cg"
+added_expr = 
+#line 416 "rql_parser.cc"
+Added_Expr(
+#line 225 "rql.cg"
+ parent );
+#line 420 "rql_parser.cc"
+
+    {
+#line 225 "rql.cg"
+ parent->append_selected( added_expr ); }
+#line 425 "rql_parser.cc"
+
+  }
+  {
+#line 226 "rql.cg"
+ return parent; }
+#line 431 "rql_parser.cc"
+
+}
+
+
+
+#line 231 "rql.cg"
+RQLNode* cppcc::
+#line 439 "rql_parser.cc"
+RqlParser::Group (
+#line 231 "rql.cg"
+ StmtNode* parent )
+#line 443 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 232 "rql.cg"
+
+	    GroupNode *group = new GroupNode();
+	    VarNode *v=0;
+	;
+#line 452 "rql_parser.cc"
+
+  consumeToken(RqlToken::GROUPBY);
+  
+#line 236 "rql.cg"
+v = 
+#line 458 "rql_parser.cc"
+Var(
+#line 236 "rql.cg"
+ parent );
+#line 462 "rql_parser.cc"
+
+  {
+#line 236 "rql.cg"
+ group->append( v ); }
+#line 467 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 237 "rql.cg"
+v = 
+#line 474 "rql_parser.cc"
+Var(
+#line 237 "rql.cg"
+ parent );
+#line 478 "rql_parser.cc"
+
+    {
+#line 237 "rql.cg"
+ group->append( v ); }
+#line 483 "rql_parser.cc"
+
+  }
+  {
+#line 238 "rql.cg"
+ parent->append( group ); return parent; }
+#line 489 "rql_parser.cc"
+
+}
+
+
+
+#line 241 "rql.cg"
+RQLNode* cppcc::
+#line 497 "rql_parser.cc"
+RqlParser::Sort (
+#line 241 "rql.cg"
+ StmtNode* parent )
+#line 501 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 242 "rql.cg"
+
+	    SortNode *sort = new SortNode();
+	    SortTermNode* term=0;
+	;
+#line 510 "rql_parser.cc"
+
+  consumeToken(RqlToken::ORDERBY);
+  
+#line 246 "rql.cg"
+term = 
+#line 516 "rql_parser.cc"
+Sort_Term(
+#line 246 "rql.cg"
+ parent );
+#line 520 "rql_parser.cc"
+
+  {
+#line 246 "rql.cg"
+ sort->append( term ); }
+#line 525 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 247 "rql.cg"
+term = 
+#line 532 "rql_parser.cc"
+Sort_Term(
+#line 247 "rql.cg"
+ parent );
+#line 536 "rql_parser.cc"
+
+    {
+#line 247 "rql.cg"
+ sort->append( term ); }
+#line 541 "rql_parser.cc"
+
+  }
+  {
+#line 248 "rql.cg"
+ parent->append( sort ); return parent; }
+#line 547 "rql_parser.cc"
+
+}
+
+
+
+#line 251 "rql.cg"
+SortTermNode* cppcc::
+#line 555 "rql_parser.cc"
+RqlParser::Sort_Term (
+#line 251 "rql.cg"
+ StmtNode* parent )
+#line 559 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 252 "rql.cg"
+ ExprNode* added_expr=0; bool ordering = true ;
+#line 565 "rql_parser.cc"
+
+  
+#line 253 "rql.cg"
+added_expr = 
+#line 570 "rql_parser.cc"
+Added_Expr(
+#line 253 "rql.cg"
+ parent );
+#line 574 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::SORT_ASC) || (scanner.la()->id == RqlToken::SORT_DESC)) {
+    if ((scanner.la()->id == RqlToken::SORT_DESC)) {
+      consumeToken(RqlToken::SORT_DESC);
+      {
+#line 254 "rql.cg"
+ ordering = false; }
+#line 582 "rql_parser.cc"
+
+    } else { 
+      consumeToken(RqlToken::SORT_ASC);
+      {
+#line 255 "rql.cg"
+ ordering = true; }
+#line 589 "rql_parser.cc"
+
+    }
+  } else { 
+     /* lambda */
+  }
+  {
+#line 256 "rql.cg"
+ return new SortTermNode( added_expr, ordering ); }
+#line 598 "rql_parser.cc"
+
+}
+
+
+
+#line 261 "rql.cg"
+RQLNode* cppcc::
+#line 606 "rql_parser.cc"
+RqlParser::Limit_Offset (
+#line 261 "rql.cg"
+ SelectStmt* parent )
+#line 610 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  if ((scanner.la()->id == RqlToken::LIMIT)) {
+    Limit(
+#line 262 "rql.cg"
+ parent );
+#line 618 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::OFFSET)) {
+    Offset(
+#line 262 "rql.cg"
+ parent );
+#line 627 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 262 "rql.cg"
+ return parent; }
+#line 635 "rql_parser.cc"
+
+}
+
+
+void cppcc::RqlParser::Limit (
+#line 265 "rql.cg"
+ SelectStmt* parent )
+#line 643 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::LIMIT);
+  consumeToken(RqlToken::INT);
+  {
+#line 266 "rql.cg"
+ parent->set_limit( int(*token) ); }
+#line 652 "rql_parser.cc"
+
+}
+
+
+void cppcc::RqlParser::Offset (
+#line 268 "rql.cg"
+ SelectStmt* parent )
+#line 660 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::OFFSET);
+  consumeToken(RqlToken::INT);
+  {
+#line 269 "rql.cg"
+ parent->set_offset( int(*token) ); }
+#line 669 "rql_parser.cc"
+
+}
+
+
+
+#line 274 "rql.cg"
+RQLNode* cppcc::
+#line 677 "rql_parser.cc"
+RqlParser::Restr (
+#line 274 "rql.cg"
+ StmtNode* parent )
+#line 681 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 275 "rql.cg"
+ RelNode* rels=0; ;
+#line 687 "rql_parser.cc"
+
+  consumeToken(RqlToken::WHERE);
+  
+#line 276 "rql.cg"
+rels = 
+#line 693 "rql_parser.cc"
+Rels(
+#line 276 "rql.cg"
+ parent );
+#line 697 "rql_parser.cc"
+
+  {
+#line 276 "rql.cg"
+ parent->append( rels ); return parent; }
+#line 702 "rql_parser.cc"
+
+}
+
+
+
+#line 279 "rql.cg"
+RelNode* cppcc::
+#line 710 "rql_parser.cc"
+RqlParser::Rels (
+#line 279 "rql.cg"
+ StmtNode* parent )
+#line 714 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 280 "rql.cg"
+ RelNode *lrel=0, *rrel=0; ;
+#line 720 "rql_parser.cc"
+
+  
+#line 281 "rql.cg"
+lrel = 
+#line 725 "rql_parser.cc"
+Ored_Rels(
+#line 281 "rql.cg"
+ parent );
+#line 729 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 282 "rql.cg"
+rrel = 
+#line 736 "rql_parser.cc"
+Ored_Rels(
+#line 282 "rql.cg"
+ parent );
+#line 740 "rql_parser.cc"
+
+    {
+#line 283 "rql.cg"
+ lrel = new AndNode( lrel, rrel ); }
+#line 745 "rql_parser.cc"
+
+  }
+  {
+#line 284 "rql.cg"
+ return lrel; }
+#line 751 "rql_parser.cc"
+
+}
+
+
+
+#line 287 "rql.cg"
+RelNode* cppcc::
+#line 759 "rql_parser.cc"
+RqlParser::Ored_Rels (
+#line 287 "rql.cg"
+ StmtNode* parent )
+#line 763 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 288 "rql.cg"
+ RelNode *lrel=0, *rrel=0; ;
+#line 769 "rql_parser.cc"
+
+  
+#line 289 "rql.cg"
+lrel = 
+#line 774 "rql_parser.cc"
+Anded_Rels(
+#line 289 "rql.cg"
+ parent );
+#line 778 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::OR)) {
+    consumeToken(RqlToken::OR);
+    
+#line 290 "rql.cg"
+rrel = 
+#line 785 "rql_parser.cc"
+Anded_Rels(
+#line 290 "rql.cg"
+ parent );
+#line 789 "rql_parser.cc"
+
+    {
+#line 291 "rql.cg"
+ lrel = new OrNode( lrel, rrel ); }
+#line 794 "rql_parser.cc"
+
+  }
+  {
+#line 292 "rql.cg"
+ return lrel; }
+#line 800 "rql_parser.cc"
+
+}
+
+
+
+#line 295 "rql.cg"
+RelNode* cppcc::
+#line 808 "rql_parser.cc"
+RqlParser::Anded_Rels (
+#line 295 "rql.cg"
+ StmtNode* parent )
+#line 812 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 296 "rql.cg"
+ RelNode *lrel=0, *rrel=0; ;
+#line 818 "rql_parser.cc"
+
+  
+#line 297 "rql.cg"
+lrel = 
+#line 823 "rql_parser.cc"
+Rel(
+#line 297 "rql.cg"
+ parent );
+#line 827 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::AND)) {
+    consumeToken(RqlToken::AND);
+    
+#line 298 "rql.cg"
+rrel = 
+#line 834 "rql_parser.cc"
+Rel(
+#line 298 "rql.cg"
+ parent );
+#line 838 "rql_parser.cc"
+
+    {
+#line 299 "rql.cg"
+ lrel = new AndNode( lrel, rrel ); }
+#line 843 "rql_parser.cc"
+
+  }
+  {
+#line 300 "rql.cg"
+ return lrel; }
+#line 849 "rql_parser.cc"
+
+}
+
+
+
+#line 303 "rql.cg"
+RelNode* cppcc::
+#line 857 "rql_parser.cc"
+RqlParser::Rel (
+#line 303 "rql.cg"
+ StmtNode* parent )
+#line 861 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 304 "rql.cg"
+
+	    bool negated = false;
+	    RelNode *rel=0;
+	;
+#line 870 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::NOT) || (scanner.la()->id == RqlToken::SYMBOL)) {
+    if ((scanner.la()->id == RqlToken::NOT)) {
+      consumeToken(RqlToken::NOT);
+      {
+#line 308 "rql.cg"
+ negated = true; }
+#line 878 "rql_parser.cc"
+
+    } else { 
+       /* lambda */
+    }
+    
+#line 309 "rql.cg"
+rel = 
+#line 886 "rql_parser.cc"
+Base_Rel(
+#line 309 "rql.cg"
+ parent );
+#line 890 "rql_parser.cc"
+
+    {
+#line 309 "rql.cg"
+ rel->_not = negated;}
+#line 895 "rql_parser.cc"
+
+  } else { 
+    consumeToken(RqlToken::LPAREN);
+    
+#line 310 "rql.cg"
+rel = 
+#line 902 "rql_parser.cc"
+Rels(
+#line 310 "rql.cg"
+parent);
+#line 906 "rql_parser.cc"
+
+    consumeToken(RqlToken::RPAREN);
+  }
+  {
+#line 311 "rql.cg"
+ return rel; }
+#line 913 "rql_parser.cc"
+
+}
+
+
+
+#line 314 "rql.cg"
+RelationNode* cppcc::
+#line 921 "rql_parser.cc"
+RqlParser::Base_Rel (
+#line 314 "rql.cg"
+ StmtNode* parent )
+#line 925 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 315 "rql.cg"
+
+	    RelationNode *e=0;
+	    VarNode *var=0;
+	    std::string rtype;
+	    ExprNode *expr=0;
+	;
+#line 936 "rql_parser.cc"
+
+  
+#line 321 "rql.cg"
+var = 
+#line 941 "rql_parser.cc"
+Var(
+#line 321 "rql.cg"
+parent);
+#line 945 "rql_parser.cc"
+
+  
+#line 322 "rql.cg"
+rtype = 
+#line 950 "rql_parser.cc"
+R_Type();
+  
+#line 323 "rql.cg"
+expr = 
+#line 955 "rql_parser.cc"
+Expr(
+#line 323 "rql.cg"
+parent);
+#line 959 "rql_parser.cc"
+
+  {
+#line 324 "rql.cg"
+
+		e = new RelationNode( rtype );
+		e->append(var);
+		assert(expr);
+		e->append(expr);
+		return e;
+	    }
+#line 970 "rql_parser.cc"
+
+}
+
+
+
+#line 334 "rql.cg"
+std::string cppcc::
+#line 978 "rql_parser.cc"
+RqlParser::R_Type ()
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::SYMBOL);
+  {
+#line 335 "rql.cg"
+
+	    if (is_r_type( token->image() ))
+		return token->image();
+	    else
+		throw ScanException( token->bPos, "Expected R_Type"); 
+	}
+#line 991 "rql_parser.cc"
+
+}
+
+
+
+#line 342 "rql.cg"
+std::string cppcc::
+#line 999 "rql_parser.cc"
+RqlParser::E_Type ()
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::SYMBOL);
+  {
+#line 343 "rql.cg"
+
+	    if (is_e_type( token->image() ))
+		return token->image();
+	    else
+		throw ScanException( token->bPos, "Expected E_Type"); 
+	}
+#line 1012 "rql_parser.cc"
+
+}
+
+
+
+#line 353 "rql.cg"
+RQLNode* cppcc::
+#line 1020 "rql_parser.cc"
+RqlParser::Vars_Decl (
+#line 353 "rql.cg"
+ StmtNode* parent )
+#line 1024 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 354 "rql.cg"
+
+	    VarNode *v=0;
+	    std::string etype;
+	;
+#line 1033 "rql_parser.cc"
+
+  
+#line 358 "rql.cg"
+etype = 
+#line 1038 "rql_parser.cc"
+E_Type();
+  
+#line 359 "rql.cg"
+v = 
+#line 1043 "rql_parser.cc"
+Var(
+#line 359 "rql.cg"
+parent);
+#line 1047 "rql_parser.cc"
+
+  {
+#line 359 "rql.cg"
+parent->add_main_variable( etype, v ); }
+#line 1052 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 360 "rql.cg"
+etype = 
+#line 1059 "rql_parser.cc"
+E_Type();
+    
+#line 361 "rql.cg"
+v = 
+#line 1064 "rql_parser.cc"
+Var(
+#line 361 "rql.cg"
+parent);
+#line 1068 "rql_parser.cc"
+
+    {
+#line 361 "rql.cg"
+
+	    parent->add_main_variable( etype, v );
+	}
+#line 1075 "rql_parser.cc"
+
+  }
+  {
+#line 364 "rql.cg"
+ return parent; }
+#line 1081 "rql_parser.cc"
+
+}
+
+
+
+#line 367 "rql.cg"
+RQLNode* cppcc::
+#line 1089 "rql_parser.cc"
+RqlParser::Rels_Decl (
+#line 367 "rql.cg"
+ StmtNode* parent )
+#line 1093 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 368 "rql.cg"
+ RelationNode *rel=0; ;
+#line 1099 "rql_parser.cc"
+
+  
+#line 369 "rql.cg"
+rel = 
+#line 1104 "rql_parser.cc"
+Simple_Rel(
+#line 369 "rql.cg"
+ parent );
+#line 1108 "rql_parser.cc"
+
+  {
+#line 369 "rql.cg"
+ parent->add_main_relation( rel ); }
+#line 1113 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    consumeToken(RqlToken::COMA);
+    
+#line 370 "rql.cg"
+rel = 
+#line 1120 "rql_parser.cc"
+Simple_Rel(
+#line 370 "rql.cg"
+ parent );
+#line 1124 "rql_parser.cc"
+
+    {
+#line 370 "rql.cg"
+ parent->add_main_relation( rel ); }
+#line 1129 "rql_parser.cc"
+
+  }
+  {
+#line 371 "rql.cg"
+ return parent; }
+#line 1135 "rql_parser.cc"
+
+}
+
+
+
+#line 374 "rql.cg"
+RelationNode* cppcc::
+#line 1143 "rql_parser.cc"
+RqlParser::Simple_Rel (
+#line 374 "rql.cg"
+ StmtNode* parent )
+#line 1147 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 375 "rql.cg"
+
+	    RelationNode *e=0;
+	    VarNode *v=0;
+	    ExprNode *expr=0;
+	    std::string rtype;
+	;
+#line 1158 "rql_parser.cc"
+
+  
+#line 381 "rql.cg"
+v = 
+#line 1163 "rql_parser.cc"
+Var(
+#line 381 "rql.cg"
+parent);
+#line 1167 "rql_parser.cc"
+
+  
+#line 381 "rql.cg"
+rtype = 
+#line 1172 "rql_parser.cc"
+R_Type();
+  
+#line 382 "rql.cg"
+expr = 
+#line 1177 "rql_parser.cc"
+Added_Expr(
+#line 382 "rql.cg"
+parent);
+#line 1181 "rql_parser.cc"
+
+  {
+#line 383 "rql.cg"
+
+		e = new RelationNode(rtype);
+		e->append( v );
+		e->append( expr );
+		return e;
+	    }
+#line 1191 "rql_parser.cc"
+
+}
+
+
+
+#line 391 "rql.cg"
+ExprNode* cppcc::
+#line 1199 "rql_parser.cc"
+RqlParser::Expr (
+#line 391 "rql.cg"
+ StmtNode* parent )
+#line 1203 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 392 "rql.cg"
+
+	    ExprNode *expr=0, *added_expr=0;
+	    std::string cmp_op;
+	;
+#line 1212 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::CMP_OP)) {
+    consumeToken(RqlToken::CMP_OP);
+    {
+#line 396 "rql.cg"
+ cmp_op = token->image(); }
+#line 1219 "rql_parser.cc"
+
+    
+#line 397 "rql.cg"
+added_expr = 
+#line 1224 "rql_parser.cc"
+Added_Expr(
+#line 397 "rql.cg"
+ parent );
+#line 1228 "rql_parser.cc"
+
+    {
+#line 397 "rql.cg"
+ expr = new ComparisonNode( cmp_op, added_expr ); }
+#line 1233 "rql_parser.cc"
+
+  } else { 
+    
+#line 398 "rql.cg"
+added_expr = 
+#line 1239 "rql_parser.cc"
+Added_Expr(
+#line 398 "rql.cg"
+ parent );
+#line 1243 "rql_parser.cc"
+
+    {
+#line 398 "rql.cg"
+ expr = new ComparisonNode( "=", added_expr ); }
+#line 1248 "rql_parser.cc"
+
+  }
+  {
+#line 399 "rql.cg"
+ return expr; }
+#line 1254 "rql_parser.cc"
+
+}
+
+
+
+#line 402 "rql.cg"
+ExprNode* cppcc::
+#line 1262 "rql_parser.cc"
+RqlParser::Added_Expr (
+#line 402 "rql.cg"
+ StmtNode* parent )
+#line 1266 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 403 "rql.cg"
+
+	    ExprNode *lhs=0, *rhs=0;
+	    std::string add_op;
+	;
+#line 1275 "rql_parser.cc"
+
+  
+#line 407 "rql.cg"
+lhs = 
+#line 1280 "rql_parser.cc"
+Muled_Expr(
+#line 407 "rql.cg"
+ parent );
+#line 1284 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::ADD_OP)) {
+    consumeToken(RqlToken::ADD_OP);
+    {
+#line 408 "rql.cg"
+ add_op = token->image(); }
+#line 1291 "rql_parser.cc"
+
+    
+#line 409 "rql.cg"
+rhs = 
+#line 1296 "rql_parser.cc"
+Muled_Expr(
+#line 409 "rql.cg"
+ parent );
+#line 1300 "rql_parser.cc"
+
+    {
+#line 409 "rql.cg"
+ lhs = new MathExpression( add_op, lhs, rhs ); }
+#line 1305 "rql_parser.cc"
+
+  }
+  {
+#line 410 "rql.cg"
+ return lhs; }
+#line 1311 "rql_parser.cc"
+
+}
+
+
+
+#line 413 "rql.cg"
+ExprNode* cppcc::
+#line 1319 "rql_parser.cc"
+RqlParser::Muled_Expr (
+#line 413 "rql.cg"
+ StmtNode* parent )
+#line 1323 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 414 "rql.cg"
+
+	    ExprNode *lhs=0, *rhs=0;
+	    std::string mul_op;
+	;
+#line 1332 "rql_parser.cc"
+
+  
+#line 418 "rql.cg"
+lhs = 
+#line 1337 "rql_parser.cc"
+Base_Expr(
+#line 418 "rql.cg"
+ parent );
+#line 1341 "rql_parser.cc"
+
+  while ((scanner.la()->id == RqlToken::MUL_OP)) {
+    consumeToken(RqlToken::MUL_OP);
+    {
+#line 419 "rql.cg"
+ mul_op = token->image(); }
+#line 1348 "rql_parser.cc"
+
+    
+#line 420 "rql.cg"
+rhs = 
+#line 1353 "rql_parser.cc"
+Base_Expr(
+#line 420 "rql.cg"
+ parent );
+#line 1357 "rql_parser.cc"
+
+    {
+#line 420 "rql.cg"
+ lhs = new MathExpression( mul_op, lhs, rhs ); }
+#line 1362 "rql_parser.cc"
+
+  }
+  {
+#line 421 "rql.cg"
+ return lhs; }
+#line 1368 "rql_parser.cc"
+
+}
+
+
+
+#line 425 "rql.cg"
+ExprNode* cppcc::
+#line 1376 "rql_parser.cc"
+RqlParser::Base_Expr (
+#line 425 "rql.cg"
+ StmtNode* parent )
+#line 1380 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 426 "rql.cg"
+ ExprNode* expr=0; ;
+#line 1386 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::DATE) || (scanner.la()->id == RqlToken::DATETIME) || (scanner.la()->id == RqlToken::RQLNULL) || (scanner.la()->id == RqlToken::BOOLEAN) || (scanner.la()->id == RqlToken::FLOAT) || (scanner.la()->id == RqlToken::INT) || (scanner.la()->id == RqlToken::SUBSTITUTE) || (scanner.la()->id == RqlToken::STRING)) {
+    
+#line 427 "rql.cg"
+expr = 
+#line 1392 "rql_parser.cc"
+Const();
+  } else { 
+    if ((scanner.la()->id == RqlToken::SYMBOL)) {
+      
+#line 428 "rql.cg"
+expr = 
+#line 1399 "rql_parser.cc"
+Var_E_Type_or_Func(
+#line 428 "rql.cg"
+parent);
+#line 1403 "rql_parser.cc"
+
+    } else { 
+      consumeToken(RqlToken::LPAREN);
+      
+#line 429 "rql.cg"
+expr = 
+#line 1410 "rql_parser.cc"
+Added_Expr(
+#line 429 "rql.cg"
+parent);
+#line 1414 "rql_parser.cc"
+
+      consumeToken(RqlToken::RPAREN);
+    }
+  }
+  {
+#line 430 "rql.cg"
+ assert(expr); return expr; }
+#line 1422 "rql_parser.cc"
+
+}
+
+
+
+#line 434 "rql.cg"
+ExprNode* cppcc::
+#line 1430 "rql_parser.cc"
+RqlParser::Var_E_Type_or_Func (
+#line 434 "rql.cg"
+ StmtNode* parent )
+#line 1434 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+#line 435 "rql.cg"
+
+	    std::string name;
+	    FuncNode *func=0;
+	    ExprNode *expr=0;
+	;
+#line 1444 "rql_parser.cc"
+
+  consumeToken(RqlToken::SYMBOL);
+  {
+#line 440 "rql.cg"
+ name =  token->image(); }
+#line 1450 "rql_parser.cc"
+
+  if ((scanner.la()->id == RqlToken::LPAREN)) {
+    consumeToken(RqlToken::LPAREN);
+    {
+#line 441 "rql.cg"
+ func = new FuncNode(name ); }
+#line 1457 "rql_parser.cc"
+
+    
+#line 442 "rql.cg"
+expr = 
+#line 1462 "rql_parser.cc"
+Added_Expr(
+#line 442 "rql.cg"
+parent);
+#line 1466 "rql_parser.cc"
+
+    {
+#line 442 "rql.cg"
+ func->append( expr ); }
+#line 1471 "rql_parser.cc"
+
+    while ((scanner.la()->id == RqlToken::COMA)) {
+      consumeToken(RqlToken::COMA);
+      
+#line 443 "rql.cg"
+expr = 
+#line 1478 "rql_parser.cc"
+Added_Expr(
+#line 443 "rql.cg"
+parent);
+#line 1482 "rql_parser.cc"
+
+      {
+#line 443 "rql.cg"
+ func->append( expr ); }
+#line 1487 "rql_parser.cc"
+
+    }
+    consumeToken(RqlToken::RPAREN);
+    {
+#line 444 "rql.cg"
+ return func; }
+#line 1494 "rql_parser.cc"
+
+  } else { 
+     /* lambda */
+  }
+  {
+#line 446 "rql.cg"
+
+		if (is_var(name)) {
+		    return parent->get_variable( name );
+		}
+		expr = parent->get_type( name );
+		assert(expr);
+#if MYDEBUG
+		std::cout << "E_TYPE ";
+		expr->display( std::cout, 0 );
+		std::cout << std::endl;
+#endif
+		return expr;
+	    }
+#line 1514 "rql_parser.cc"
+
+}
+
+
+
+#line 461 "rql.cg"
+VarNode* cppcc::
+#line 1522 "rql_parser.cc"
+RqlParser::Var (
+#line 461 "rql.cg"
+ StmtNode* parent )
+#line 1526 "rql_parser.cc"
+
+     throw (ScanException, ParseException)
+{
+  consumeToken(RqlToken::SYMBOL);
+  {
+#line 462 "rql.cg"
+
+	    VarNode* v=0;
+	    if (!is_var( token->image() )) {
+		throw ScanException( token->bPos, "Expected Variable" );
+	    }
+	    v = parent->get_variable( token->image() );
+	    assert(v);
+	    return v;
+	}
+#line 1542 "rql_parser.cc"
+
+}
+
+
+
+#line 474 "rql.cg"
+ExprNode* cppcc::
+#line 1550 "rql_parser.cc"
+RqlParser::Const ()
+     throw (ScanException, ParseException)
+{
+  if ((scanner.la()->id == RqlToken::RQLNULL)) {
+    consumeToken(RqlToken::RQLNULL);
+    {
+#line 475 "rql.cg"
+ return new Constant( "NULL", token->image() ); }
+#line 1559 "rql_parser.cc"
+
+  } else { 
+    if ((scanner.la()->id == RqlToken::DATE)) {
+      consumeToken(RqlToken::DATE);
+      {
+#line 476 "rql.cg"
+ return new Constant( "Date", token->image() ); }
+#line 1567 "rql_parser.cc"
+
+    } else { 
+      if ((scanner.la()->id == RqlToken::DATETIME)) {
+        consumeToken(RqlToken::DATETIME);
+        {
+#line 477 "rql.cg"
+ return new Constant( "Datetime", token->image() ); }
+#line 1575 "rql_parser.cc"
+
+      } else { 
+        if ((scanner.la()->id == RqlToken::BOOLEAN)) {
+          consumeToken(RqlToken::BOOLEAN);
+          {
+#line 478 "rql.cg"
+ return new Constant( "Boolean", token->image() ); }
+#line 1583 "rql_parser.cc"
+
+        } else { 
+          if ((scanner.la()->id == RqlToken::FLOAT)) {
+            consumeToken(RqlToken::FLOAT);
+            {
+#line 479 "rql.cg"
+ return new Constant( "Float", double(*token) ); }
+#line 1591 "rql_parser.cc"
+
+          } else { 
+            if ((scanner.la()->id == RqlToken::INT)) {
+              consumeToken(RqlToken::INT);
+              {
+#line 480 "rql.cg"
+ return new Constant( "Int", int(*token) ); }
+#line 1599 "rql_parser.cc"
+
+            } else { 
+              if ((scanner.la()->id == RqlToken::STRING)) {
+                consumeToken(RqlToken::STRING);
+                {
+#line 481 "rql.cg"
+ return new Constant( "String", token->image() ); }
+#line 1607 "rql_parser.cc"
+
+              } else { 
+                consumeToken(RqlToken::SUBSTITUTE);
+                {
+#line 482 "rql.cg"
+ return new Constant( "Substitute", token->image() ); }
+#line 1614 "rql_parser.cc"
+
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
+bool cppcc::RqlParser::__la_Goal_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::DELETE)) {
+    if (!laConsumeToken(RqlToken::DELETE)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Delete_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!laConsumeToken(RqlToken::SEMICOLON)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+    if ((scanner.la()->id == RqlToken::INSERT)) {
+      if (!laConsumeToken(RqlToken::INSERT)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+      if (!__la_Insert_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+      if (!laConsumeToken(RqlToken::SEMICOLON)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+      if ((scanner.la()->id == RqlToken::SET)) {
+        if (!laConsumeToken(RqlToken::SET)) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+        if (!__la_Update_()) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+        if (!laConsumeToken(RqlToken::SEMICOLON)) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+      } else { 
+        if (!__la_Select_()) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+        if (!laConsumeToken(RqlToken::SEMICOLON)) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+      }
+    }
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Delete_ () throw (ScanException)
+{
+  if ((
+#line 181 "rql.cg"
+scanner.is_next_vars_decl())
+#line 1673 "rql_parser.cc"
+) {
+    if (!__la_Vars_Decl_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if ((scanner.la()->id == RqlToken::WHERE)) {
+      if (!__la_Restr_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+       /* lambda */
+    }
+  } else { 
+    if (!__la_Rels_Decl_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if ((scanner.la()->id == RqlToken::WHERE)) {
+      if (!__la_Restr_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+       /* lambda */
+    }
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Insert_ () throw (ScanException)
+{
+  if (!__la_Vars_Decl_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::COLON)) {
+    if (!__la_Insert_Rels_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Insert_Rels_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::COLON)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Rels_Decl_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    if (!__la_Restr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Update_ () throw (ScanException)
+{
+  if (!__la_Rels_Decl_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    if (!__la_Restr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Select_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::DISTINCT)) {
+    if (!laConsumeToken(RqlToken::DISTINCT)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  if (!__la_Select_Base_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Select_Base_ () throw (ScanException)
+{
+  if (!__la_E_Type_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Selected_Terms_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::WHERE)) {
+    if (!__la_Restr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::GROUPBY)) {
+    if (!__la_Group_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::ORDERBY)) {
+    if (!__la_Sort_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::LIMIT) || (scanner.la()->id == RqlToken::OFFSET)) {
+    if (!__la_Limit_Offset_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Selected_Terms_ () throw (ScanException)
+{
+  if (!__la_Added_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Added_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Group_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::GROUPBY)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Var_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Var_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Sort_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::ORDERBY)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Sort_Term_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Sort_Term_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Sort_Term_ () throw (ScanException)
+{
+  if (!__la_Added_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::SORT_ASC) || (scanner.la()->id == RqlToken::SORT_DESC)) {
+    if ((scanner.la()->id == RqlToken::SORT_DESC)) {
+      if (!laConsumeToken(RqlToken::SORT_DESC)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+      if (!laConsumeToken(RqlToken::SORT_ASC)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    }
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Limit_Offset_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::LIMIT)) {
+    if (!__la_Limit_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  if ((scanner.la()->id == RqlToken::OFFSET)) {
+    if (!__la_Offset_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Limit_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::LIMIT)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!laConsumeToken(RqlToken::INT)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Offset_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::OFFSET)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!laConsumeToken(RqlToken::INT)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Restr_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::WHERE)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Rels_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Rels_ () throw (ScanException)
+{
+  if (!__la_Ored_Rels_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Ored_Rels_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Ored_Rels_ () throw (ScanException)
+{
+  if (!__la_Anded_Rels_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::OR)) {
+    if (!laConsumeToken(RqlToken::OR)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Anded_Rels_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Anded_Rels_ () throw (ScanException)
+{
+  if (!__la_Rel_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::AND)) {
+    if (!laConsumeToken(RqlToken::AND)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Rel_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Rel_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::NOT) || (scanner.la()->id == RqlToken::SYMBOL)) {
+    if ((scanner.la()->id == RqlToken::NOT)) {
+      if (!laConsumeToken(RqlToken::NOT)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+       /* lambda */
+    }
+    if (!__la_Base_Rel_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+    if (!laConsumeToken(RqlToken::LPAREN)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Rels_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!laConsumeToken(RqlToken::RPAREN)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Base_Rel_ () throw (ScanException)
+{
+  if (!__la_Var_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_R_Type_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_R_Type_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::SYMBOL)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_E_Type_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::SYMBOL)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Vars_Decl_ () throw (ScanException)
+{
+  if (!__la_E_Type_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Var_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_E_Type_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Var_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Rels_Decl_ () throw (ScanException)
+{
+  if (!__la_Simple_Rel_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::COMA)) {
+    if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Simple_Rel_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Simple_Rel_ () throw (ScanException)
+{
+  if (!__la_Var_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_R_Type_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if (!__la_Added_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Expr_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::CMP_OP)) {
+    if (!laConsumeToken(RqlToken::CMP_OP)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Added_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+    if (!__la_Added_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Added_Expr_ () throw (ScanException)
+{
+  if (!__la_Muled_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::ADD_OP)) {
+    if (!laConsumeToken(RqlToken::ADD_OP)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Muled_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Muled_Expr_ () throw (ScanException)
+{
+  if (!__la_Base_Expr_()) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  while ((scanner.la()->id == RqlToken::MUL_OP)) {
+    if (!laConsumeToken(RqlToken::MUL_OP)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Base_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Base_Expr_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::DATE) || (scanner.la()->id == RqlToken::DATETIME) || (scanner.la()->id == RqlToken::RQLNULL) || (scanner.la()->id == RqlToken::BOOLEAN) || (scanner.la()->id == RqlToken::FLOAT) || (scanner.la()->id == RqlToken::INT) || (scanner.la()->id == RqlToken::SUBSTITUTE) || (scanner.la()->id == RqlToken::STRING)) {
+    if (!__la_Const_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+    if ((scanner.la()->id == RqlToken::SYMBOL)) {
+      if (!__la_Var_E_Type_or_Func_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+      if (!laConsumeToken(RqlToken::LPAREN)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+      if (!__la_Added_Expr_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+      if (!laConsumeToken(RqlToken::RPAREN)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    }
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Var_E_Type_or_Func_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::SYMBOL)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  if ((scanner.la()->id == RqlToken::LPAREN)) {
+    if (!laConsumeToken(RqlToken::LPAREN)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    if (!__la_Added_Expr_()) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+    while ((scanner.la()->id == RqlToken::COMA)) {
+      if (!laConsumeToken(RqlToken::COMA)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+      if (!__la_Added_Expr_()) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    }
+    if (!laConsumeToken(RqlToken::RPAREN)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+     /* lambda */
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Var_ () throw (ScanException)
+{
+  if (!laConsumeToken(RqlToken::SYMBOL)) goto __lookahead_fail_;
+  if (_la == 0) goto __lookahead_succeed_;
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+bool cppcc::RqlParser::__la_Const_ () throw (ScanException)
+{
+  if ((scanner.la()->id == RqlToken::RQLNULL)) {
+    if (!laConsumeToken(RqlToken::RQLNULL)) goto __lookahead_fail_;
+    if (_la == 0) goto __lookahead_succeed_;
+  } else { 
+    if ((scanner.la()->id == RqlToken::DATE)) {
+      if (!laConsumeToken(RqlToken::DATE)) goto __lookahead_fail_;
+      if (_la == 0) goto __lookahead_succeed_;
+    } else { 
+      if ((scanner.la()->id == RqlToken::DATETIME)) {
+        if (!laConsumeToken(RqlToken::DATETIME)) goto __lookahead_fail_;
+        if (_la == 0) goto __lookahead_succeed_;
+      } else { 
+        if ((scanner.la()->id == RqlToken::BOOLEAN)) {
+          if (!laConsumeToken(RqlToken::BOOLEAN)) goto __lookahead_fail_;
+          if (_la == 0) goto __lookahead_succeed_;
+        } else { 
+          if ((scanner.la()->id == RqlToken::FLOAT)) {
+            if (!laConsumeToken(RqlToken::FLOAT)) goto __lookahead_fail_;
+            if (_la == 0) goto __lookahead_succeed_;
+          } else { 
+            if ((scanner.la()->id == RqlToken::INT)) {
+              if (!laConsumeToken(RqlToken::INT)) goto __lookahead_fail_;
+              if (_la == 0) goto __lookahead_succeed_;
+            } else { 
+              if ((scanner.la()->id == RqlToken::STRING)) {
+                if (!laConsumeToken(RqlToken::STRING)) goto __lookahead_fail_;
+                if (_la == 0) goto __lookahead_succeed_;
+              } else { 
+                if (!laConsumeToken(RqlToken::SUBSTITUTE)) goto __lookahead_fail_;
+                if (_la == 0) goto __lookahead_succeed_;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  __lookahead_succeed_:
+    return true;
+    
+  __lookahead_fail_:
+    return false;
+}
+
+
+
+
+
+/* End of file. */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/rql_parser.hh	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,546 @@
+/******************************************************************
+ * File: rql_parser.hh
+ *
+ * This file was automatically generated by CppCC Version 0.0.8
+ * DO NOT EDIT MANUALLY
+ ******************************************************************/
+
+
+#ifndef __RQL_PARSER_HH__
+#define __RQL_PARSER_HH__
+
+#include <iostream>
+#include <string>
+#include <exception>
+
+#include "rql_token.hh"
+#include "rql_scanner.hh"
+namespace cppcc
+{
+
+class ParseException : public std::exception
+{
+  public:
+    
+    ParseException (const std::string &message_ = "Parse exception") :
+      message(message_)
+    {}
+    
+    ParseException (const Position &pos_,
+                   const std::string &message_ = "Parse exception") :
+      message(message_), pos(pos_)
+    {}
+    
+    ~ParseException () throw ()
+    {}
+    
+    virtual operator std::string () const
+    {
+      return std::string(pos) + ": " + message;
+    }
+    
+    virtual const char* what () const throw ()
+    {
+      return message.c_str();
+    }
+    
+    virtual Position& where () throw ()
+    {
+      return pos;
+    }
+    
+  private:
+  
+    std::string message;
+    Position pos;
+}; // end class ParseException
+
+
+class RqlParser_base
+{
+  protected:
+    bool onParseError (ParseException &pex) { return false; }
+};
+
+
+class RqlParser : public RqlParser_base
+{
+  public: // methods
+    
+    RqlParser (std::istream *in_ = NULL) throw (ScanException, ParseException) :
+       scanner(in_), _la(0)
+    {}
+    
+    // productions entry points:
+    
+    
+#line 155 "rql.cg"
+StmtNode*
+#line 80 "rql_parser.hh"
+
+     Goal (
+#line 155 "rql.cg"
+ TypeDict* types )
+#line 85 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 180 "rql.cg"
+RQLNode*
+#line 91 "rql_parser.hh"
+
+     Delete (
+#line 180 "rql.cg"
+ DeleteStmt* parent )
+#line 96 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 189 "rql.cg"
+RQLNode*
+#line 102 "rql_parser.hh"
+
+     Insert (
+#line 189 "rql.cg"
+ InsertStmt* parent )
+#line 107 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 194 "rql.cg"
+RQLNode*
+#line 113 "rql_parser.hh"
+
+     Insert_Rels (
+#line 194 "rql.cg"
+ InsertStmt* parent )
+#line 118 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 201 "rql.cg"
+RQLNode*
+#line 124 "rql_parser.hh"
+
+     Update (
+#line 201 "rql.cg"
+ UpdateStmt* parent )
+#line 129 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 207 "rql.cg"
+RQLNode*
+#line 135 "rql_parser.hh"
+
+     Select (
+#line 207 "rql.cg"
+ SelectStmt* parent )
+#line 140 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 212 "rql.cg"
+RQLNode*
+#line 146 "rql_parser.hh"
+
+     Select_Base (
+#line 212 "rql.cg"
+ SelectStmt* parent )
+#line 151 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 222 "rql.cg"
+RQLNode*
+#line 157 "rql_parser.hh"
+
+     Selected_Terms (
+#line 222 "rql.cg"
+ SelectStmt* parent )
+#line 162 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 231 "rql.cg"
+RQLNode*
+#line 168 "rql_parser.hh"
+
+     Group (
+#line 231 "rql.cg"
+ StmtNode* parent )
+#line 173 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 241 "rql.cg"
+RQLNode*
+#line 179 "rql_parser.hh"
+
+     Sort (
+#line 241 "rql.cg"
+ StmtNode* parent )
+#line 184 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 251 "rql.cg"
+SortTermNode*
+#line 190 "rql_parser.hh"
+
+     Sort_Term (
+#line 251 "rql.cg"
+ StmtNode* parent )
+#line 195 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 261 "rql.cg"
+RQLNode*
+#line 201 "rql_parser.hh"
+
+     Limit_Offset (
+#line 261 "rql.cg"
+ SelectStmt* parent )
+#line 206 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    void
+     Limit (
+#line 265 "rql.cg"
+ SelectStmt* parent )
+#line 213 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    void
+     Offset (
+#line 268 "rql.cg"
+ SelectStmt* parent )
+#line 220 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 274 "rql.cg"
+RQLNode*
+#line 226 "rql_parser.hh"
+
+     Restr (
+#line 274 "rql.cg"
+ StmtNode* parent )
+#line 231 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 279 "rql.cg"
+RelNode*
+#line 237 "rql_parser.hh"
+
+     Rels (
+#line 279 "rql.cg"
+ StmtNode* parent )
+#line 242 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 287 "rql.cg"
+RelNode*
+#line 248 "rql_parser.hh"
+
+     Ored_Rels (
+#line 287 "rql.cg"
+ StmtNode* parent )
+#line 253 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 295 "rql.cg"
+RelNode*
+#line 259 "rql_parser.hh"
+
+     Anded_Rels (
+#line 295 "rql.cg"
+ StmtNode* parent )
+#line 264 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 303 "rql.cg"
+RelNode*
+#line 270 "rql_parser.hh"
+
+     Rel (
+#line 303 "rql.cg"
+ StmtNode* parent )
+#line 275 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 314 "rql.cg"
+RelationNode*
+#line 281 "rql_parser.hh"
+
+     Base_Rel (
+#line 314 "rql.cg"
+ StmtNode* parent )
+#line 286 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 334 "rql.cg"
+std::string
+#line 292 "rql_parser.hh"
+
+     R_Type ()
+       throw (ScanException, ParseException);
+    
+#line 342 "rql.cg"
+std::string
+#line 299 "rql_parser.hh"
+
+     E_Type ()
+       throw (ScanException, ParseException);
+    
+#line 353 "rql.cg"
+RQLNode*
+#line 306 "rql_parser.hh"
+
+     Vars_Decl (
+#line 353 "rql.cg"
+ StmtNode* parent )
+#line 311 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 367 "rql.cg"
+RQLNode*
+#line 317 "rql_parser.hh"
+
+     Rels_Decl (
+#line 367 "rql.cg"
+ StmtNode* parent )
+#line 322 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 374 "rql.cg"
+RelationNode*
+#line 328 "rql_parser.hh"
+
+     Simple_Rel (
+#line 374 "rql.cg"
+ StmtNode* parent )
+#line 333 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 391 "rql.cg"
+ExprNode*
+#line 339 "rql_parser.hh"
+
+     Expr (
+#line 391 "rql.cg"
+ StmtNode* parent )
+#line 344 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 402 "rql.cg"
+ExprNode*
+#line 350 "rql_parser.hh"
+
+     Added_Expr (
+#line 402 "rql.cg"
+ StmtNode* parent )
+#line 355 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 413 "rql.cg"
+ExprNode*
+#line 361 "rql_parser.hh"
+
+     Muled_Expr (
+#line 413 "rql.cg"
+ StmtNode* parent )
+#line 366 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 425 "rql.cg"
+ExprNode*
+#line 372 "rql_parser.hh"
+
+     Base_Expr (
+#line 425 "rql.cg"
+ StmtNode* parent )
+#line 377 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 434 "rql.cg"
+ExprNode*
+#line 383 "rql_parser.hh"
+
+     Var_E_Type_or_Func (
+#line 434 "rql.cg"
+ StmtNode* parent )
+#line 388 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 461 "rql.cg"
+VarNode*
+#line 394 "rql_parser.hh"
+
+     Var (
+#line 461 "rql.cg"
+ StmtNode* parent )
+#line 399 "rql_parser.hh"
+
+       throw (ScanException, ParseException);
+    
+#line 474 "rql.cg"
+ExprNode*
+#line 405 "rql_parser.hh"
+
+     Const ()
+       throw (ScanException, ParseException);
+    
+    // productions LA methods:
+    
+    bool __la_Goal_ () throw (ScanException);
+    bool __la_Delete_ () throw (ScanException);
+    bool __la_Insert_ () throw (ScanException);
+    bool __la_Insert_Rels_ () throw (ScanException);
+    bool __la_Update_ () throw (ScanException);
+    bool __la_Select_ () throw (ScanException);
+    bool __la_Select_Base_ () throw (ScanException);
+    bool __la_Selected_Terms_ () throw (ScanException);
+    bool __la_Group_ () throw (ScanException);
+    bool __la_Sort_ () throw (ScanException);
+    bool __la_Sort_Term_ () throw (ScanException);
+    bool __la_Limit_Offset_ () throw (ScanException);
+    bool __la_Limit_ () throw (ScanException);
+    bool __la_Offset_ () throw (ScanException);
+    bool __la_Restr_ () throw (ScanException);
+    bool __la_Rels_ () throw (ScanException);
+    bool __la_Ored_Rels_ () throw (ScanException);
+    bool __la_Anded_Rels_ () throw (ScanException);
+    bool __la_Rel_ () throw (ScanException);
+    bool __la_Base_Rel_ () throw (ScanException);
+    bool __la_R_Type_ () throw (ScanException);
+    bool __la_E_Type_ () throw (ScanException);
+    bool __la_Vars_Decl_ () throw (ScanException);
+    bool __la_Rels_Decl_ () throw (ScanException);
+    bool __la_Simple_Rel_ () throw (ScanException);
+    bool __la_Expr_ () throw (ScanException);
+    bool __la_Added_Expr_ () throw (ScanException);
+    bool __la_Muled_Expr_ () throw (ScanException);
+    bool __la_Base_Expr_ () throw (ScanException);
+    bool __la_Var_E_Type_or_Func_ () throw (ScanException);
+    bool __la_Var_ () throw (ScanException);
+    bool __la_Const_ () throw (ScanException);
+    
+    // lookahead entry points:
+    
+    // LA entry points for Goal
+    
+    // LA entry points for Delete
+    
+    // LA entry points for Insert
+    
+    // LA entry points for Insert_Rels
+    
+    // LA entry points for Update
+    
+    // LA entry points for Select
+    
+    // LA entry points for Select_Base
+    
+    // LA entry points for Selected_Terms
+    
+    // LA entry points for Group
+    
+    // LA entry points for Sort
+    
+    // LA entry points for Sort_Term
+    
+    // LA entry points for Limit_Offset
+    
+    // LA entry points for Limit
+    
+    // LA entry points for Offset
+    
+    // LA entry points for Restr
+    
+    // LA entry points for Rels
+    
+    // LA entry points for Ored_Rels
+    
+    // LA entry points for Anded_Rels
+    
+    // LA entry points for Rel
+    
+    // LA entry points for Base_Rel
+    
+    // LA entry points for R_Type
+    
+    // LA entry points for E_Type
+    
+    // LA entry points for Vars_Decl
+    
+    // LA entry points for Rels_Decl
+    
+    // LA entry points for Simple_Rel
+    
+    // LA entry points for Expr
+    
+    // LA entry points for Added_Expr
+    
+    // LA entry points for Muled_Expr
+    
+    // LA entry points for Base_Expr
+    
+    // LA entry points for Var_E_Type_or_Func
+    
+    // LA entry points for Var
+    
+    // LA entry points for Const
+    
+    
+    
+  private: // methods
+    
+    void consumeToken (int tId)  throw (ScanException, ParseException)
+    {
+      if ((token = scanner.la())->id != tId)
+      {
+        ParseException pex(scanner.la()->bPos, "Parse error.");
+        if (!onParseError(pex)) throw pex;
+      }
+      scanner.unchecked_consume();
+    }
+    
+    bool laConsumeToken (int tId)  throw (ScanException, ParseException)
+    {
+      if (scanner.la()->id != tId) return false;
+      scanner.unchecked_consume();
+      return true;
+    }
+    
+  public: // data
+    
+    RqlScanner scanner;
+    int _la;
+    RqlToken *token;
+    
+}; //end class RqlParser
+
+
+} //end namespace cppcc
+
+
+#endif // ifndef __RQL_PARSER_HH__
+
+
+/* End of file. */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rqlmodule/rql_scanner.cc	Mon May 08 20:03:41 2006 +0200
@@ -0,0 +1,2485 @@
+/******************************************************************
+ * File: rql_scanner.cc
+ *
+ * This file was automatically generated by CppCC Version 0.0.8
+ * DO NOT EDIT MANUALLY
+ ******************************************************************/
+
+
+
+#include "rql_scanner.hh"
+
+const int cppcc::RqlScanner::START = 0;
+const int cppcc::RqlScanner::LONG_COMMENT = 1;
+
+void cppcc::RqlScanner::_brefill () throw (ScanException)
+{
+  if (!*inputStream) {
+    ScanException __ex(ePos, "Input error.");
+    if (!onIOError(__ex))
+      throw __ex;
+  }
+  for (struct t_laCell *p = _laBegin; p != _laEnd; p = p->next)
+    p->token->_cacheImg();
+  if (_start != _ch) {
+    if (_start <= _buffer + _pbsz) {
+      int nbsz = _pbsz;
+      do { nbsz *= 2; } while (nbsz <= _bsz + _pbsz);
+      _bsz = nbsz;
+      char *newBuf = new char[_bsz + _pbsz + 1];
+      memcpy(newBuf + _pbsz, _start, _ch - _start);
+      _bol += newBuf + _pbsz - _start;
+      _ch += newBuf + _pbsz - _start;
+      _start = newBuf + _pbsz;
+      delete[] _buffer;
+      _buffer = newBuf;
+    } else {
+      memmove(_buffer + _pbsz, _start, _ch - _start);
+      _bol -= _start - (_buffer + _pbsz);
+      _ch = _buffer + _pbsz + (_ch - _start);
+      _start = _buffer + _pbsz;
+    }
+  } else {
+    _start = _ch = _buffer + _pbsz;
+    _bol = _start;
+  }
+  inputStream->read(_ch, _bsz - (_ch - (_buffer + _pbsz)));
+  _eob = _ch + inputStream->gcount();
+  *_eob++  = '\0';
+  _eof = inputStream->eof();
+  _lta = false;
+}
+
+void cppcc::RqlScanner::_binit () throw (ScanException)
+{
+  if (_buffer == NULL) _buffer = new char[_bsz + _pbsz + 1];
+  _start = _ch = _eob = _buffer + _pbsz;
+  *_eob++  = '\0';
+  _eof = inputStream == NULL;
+}
+void cppcc::RqlScanner::unGetChars (const char *c, int n)
+{
+  if (_start < _buffer + n) { //grow the buffer
+    int npbsz = _pbsz, delta = 0;
+    for (struct t_laCell *p = _laBegin; p != _laEnd; p = p->next)
+      p->token->_cacheImg();
+    if (la0 == _laEnd) la0->token->_cacheImg();
+    do { npbsz *= 2; delta = npbsz - _pbsz; } while (delta < n);
+    char *newBuf = new char[_bsz + npbsz + 1];
+    memcpy(newBuf + delta, _start, _eob - _start + 1);
+    _bol += newBuf + delta - _start;
+    _ch += newBuf + delta - _start;
+    _eob += newBuf + delta - _start;
+    _start = newBuf + delta;
+    _pbsz = npbsz;
+    delete[] _buffer;
+    _buffer = newBuf;
+  }
+  memmove(_start - n, _start, n);
+  _ch -= n;
+  _start -= n;
+  _bol -= n;
+  memcpy(_ch, c, n);
+}
+
+void cppcc::RqlScanner::_scan (RqlToken *token) throw (ScanException)
+{
+  register unsigned char c;
+  
+  for(;;)
+  {
+    switch (getState())
+    {
+    case START:
+      __START_0_:
+        c = *_ch++;
+         /*0*/ if ((('\t' /*9*/ <= c) && (c <= '\f' /*12*/)) || (c == ' ' /*32*/))
+          goto __START_1_;
+        else  /*0*/ if ((c == '"' /*34*/))
+          goto __START_2_;
+        else  /*0*/ if ((c == '%' /*37*/))
+          goto __START_3_;
+        else  /*0*/ if ((c == '\'' /*39*/))
+          goto __START_4_;
+        else  /*0*/ if ((c == '(' /*40*/))
+          goto __START_5_;
+        else  /*0*/ if ((c == ')' /*41*/))
+          goto __START_6_;
+        else  /*0*/ if ((c == '*' /*42*/))
+          goto __START_7_;
+        else  /*0*/ if ((c == '+' /*43*/) || (c == '-' /*45*/))
+          goto __START_8_;
+        else  /*0*/ if ((c == ',' /*44*/))
+          goto __START_9_;
+        else  /*0*/ if ((c == '/' /*47*/))
+          goto __START_10_;
+        else  /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)))
+          goto __START_11_;
+        else  /*0*/ if ((c == ':' /*58*/))
+          goto __START_12_;
+        else  /*0*/ if ((c == ';' /*59*/))
+          goto __START_13_;
+        else  /*0*/ if ((c == '<' /*60*/))
+          goto __START_14_;
+        else  /*0*/ if ((c == '=' /*61*/))
+          goto __START_15_;
+        else  /*0*/ if ((c == '>' /*62*/))
+          goto __START_16_;
+        else  /*0*/ if ((c == 'A' /*65*/) || (c == 'a' /*97*/))
+          goto __START_17_;
+        else  /*0*/ if ((('B' /*66*/ <= c) && (c <= 'C' /*67*/)) || (c == 'E' /*69*/) || (c == 'H' /*72*/) || (('J' /*74*/ <= c) && (c <= 'K' /*75*/)) || (c == 'M' /*77*/) || (('P' /*80*/ <= c) && (c <= 'R' /*82*/)) || (('U' /*85*/ <= c) && (c <= 'V' /*86*/)) || (('X' /*88*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('b' /*98*/ <= c) && (c <= 'c' /*99*/)) || (c == 'e' /*101*/) || (c == 'h' /*104*/) || (('j' /*106*/ <= c) && (c <= 'k' /*107*/)) || (c == 'm' /*109*/) || (('p' /*112*/ <= c) && (c <= 'r' /*114*/)) || (('u' /*117*/ <= c) && (c <= 'v' /*118*/)) || (('x' /*120*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'D' /*68*/) || (c == 'd' /*100*/))
+          goto __START_19_;
+        else  /*0*/ if ((c == 'F' /*70*/) || (c == 'f' /*102*/))
+          goto __START_20_;
+        else  /*0*/ if ((c == 'G' /*71*/) || (c == 'g' /*103*/))
+          goto __START_21_;
+        else  /*0*/ if ((c == 'I' /*73*/) || (c == 'i' /*105*/))
+          goto __START_22_;
+        else  /*0*/ if ((c == 'L' /*76*/))
+          goto __START_23_;
+        else  /*0*/ if ((c == 'N' /*78*/))
+          goto __START_24_;
+        else  /*0*/ if ((c == 'O' /*79*/))
+          goto __START_25_;
+        else  /*0*/ if ((c == 'S' /*83*/) || (c == 's' /*115*/))
+          goto __START_26_;
+        else  /*0*/ if ((c == 'T' /*84*/))
+          goto __START_27_;
+        else  /*0*/ if ((c == 'W' /*87*/) || (c == 'w' /*119*/))
+          goto __START_28_;
+        else  /*0*/ if ((c == 'l' /*108*/))
+          goto __START_29_;
+        else  /*0*/ if ((c == 'n' /*110*/))
+          goto __START_30_;
+        else  /*0*/ if ((c == 'o' /*111*/))
+          goto __START_31_;
+        else  /*0*/ if ((c == 't' /*116*/))
+          goto __START_32_;
+        else  /*0*/ if ((c == '~' /*126*/))
+          goto __START_33_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_0_;
+        }
+        goto __scan_error_;
+      __START_1_:
+        goto __accept_token_ws_;
+      __START_2_:
+        c = *_ch++;
+         /*0*/ if (((c == '\0') && (_ch != _eob)) || (('\1' /*1*/ <= c) && (c <= '!' /*33*/)) || (('#' /*35*/ <= c) && (c <= '[' /*91*/)) || (']' /*93*/ <= c))
+          goto __START_2_;
+        else  /*0*/ if ((c == '"' /*34*/))
+          goto __START_34_;
+        else  /*0*/ if ((c == '\\' /*92*/))
+          goto __START_35_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_2_;
+        }
+        goto __scan_error_;
+      __START_3_:
+        c = *_ch++;
+         /*0*/ if ((c == '(' /*40*/))
+          goto __START_36_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_3_;
+        }
+        goto __scan_error_;
+      __START_4_:
+        c = *_ch++;
+         /*0*/ if (((c == '\0') && (_ch != _eob)) || (('\1' /*1*/ <= c) && (c <= '&' /*38*/)) || (('(' /*40*/ <= c) && (c <= '[' /*91*/)) || (']' /*93*/ <= c))
+          goto __START_4_;
+        else  /*0*/ if ((c == '\'' /*39*/))
+          goto __START_34_;
+        else  /*0*/ if ((c == '\\' /*92*/))
+          goto __START_37_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_4_;
+        }
+        goto __scan_error_;
+      __START_5_:
+        goto __accept_token_LPAREN_;
+      __START_6_:
+        goto __accept_token_RPAREN_;
+      __START_7_:
+        goto __accept_token_MUL_OP_;
+      __START_8_:
+        goto __accept_token_ADD_OP_;
+      __START_9_:
+        goto __accept_token_COMA_;
+      __START_10_:
+        c = *_ch++;
+         /*0*/ if ((c == '*' /*42*/))
+          goto __START_38_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_MUL_OP_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_10_;
+        }
+        goto __accept_token_MUL_OP_;
+      __START_11_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)))
+          goto __START_11_;
+        else  /*0*/ if ((c == '.' /*46*/))
+          goto __START_39_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_INT_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_11_;
+        }
+        goto __accept_token_INT_;
+      __START_12_:
+        goto __accept_token_COLON_;
+      __START_13_:
+        goto __accept_token_SEMICOLON_;
+      __START_14_:
+        c = *_ch++;
+         /*0*/ if ((c == '=' /*61*/))
+          goto __START_15_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_CMP_OP_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_14_;
+        }
+        goto __accept_token_CMP_OP_;
+      __START_15_:
+        goto __accept_token_CMP_OP_;
+      __START_16_:
+        c = *_ch++;
+         /*0*/ if ((c == '=' /*61*/))
+          goto __START_15_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_CMP_OP_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_16_;
+        }
+        goto __accept_token_CMP_OP_;
+      __START_17_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'M' /*77*/)) || (('O' /*79*/ <= c) && (c <= 'R' /*82*/)) || (('T' /*84*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'm' /*109*/)) || (('o' /*111*/ <= c) && (c <= 'r' /*114*/)) || (('t' /*116*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'N' /*78*/) || (c == 'n' /*110*/))
+          goto __START_40_;
+        else  /*0*/ if ((c == 'S' /*83*/) || (c == 's' /*115*/))
+          goto __START_41_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_17_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_18_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_18_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_19_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'D' /*68*/)) || (('F' /*70*/ <= c) && (c <= 'H' /*72*/)) || (('J' /*74*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'd' /*100*/)) || (('f' /*102*/ <= c) && (c <= 'h' /*104*/)) || (('j' /*106*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'E' /*69*/) || (c == 'e' /*101*/))
+          goto __START_42_;
+        else  /*0*/ if ((c == 'I' /*73*/) || (c == 'i' /*105*/))
+          goto __START_43_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_19_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_20_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('B' /*66*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('b' /*98*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'A' /*65*/) || (c == 'a' /*97*/))
+          goto __START_44_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_20_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_21_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Q' /*81*/)) || (('S' /*83*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'q' /*113*/)) || (('s' /*115*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'R' /*82*/) || (c == 'r' /*114*/))
+          goto __START_45_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_21_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_22_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'M' /*77*/)) || (('O' /*79*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'm' /*109*/)) || (('o' /*111*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'N' /*78*/) || (c == 'n' /*110*/))
+          goto __START_46_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_22_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_23_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'H' /*72*/)) || (('J' /*74*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'h' /*104*/)) || (('j' /*106*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'I' /*73*/))
+          goto __START_47_;
+        else  /*0*/ if ((c == 'i' /*105*/))
+          goto __START_48_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_23_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_24_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'N' /*78*/)) || (('P' /*80*/ <= c) && (c <= 'T' /*84*/)) || (('V' /*86*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'n' /*110*/)) || (('p' /*112*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'O' /*79*/))
+          goto __START_49_;
+        else  /*0*/ if ((c == 'U' /*85*/))
+          goto __START_50_;
+        else  /*0*/ if ((c == 'o' /*111*/))
+          goto __START_51_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_24_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_25_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'E' /*69*/)) || (('G' /*71*/ <= c) && (c <= 'Q' /*81*/)) || (('S' /*83*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'q' /*113*/)) || (('s' /*115*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'F' /*70*/))
+          goto __START_52_;
+        else  /*0*/ if ((c == 'R' /*82*/) || (c == 'r' /*114*/))
+          goto __START_53_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_25_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_26_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'D' /*68*/)) || (('F' /*70*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'd' /*100*/)) || (('f' /*102*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'E' /*69*/) || (c == 'e' /*101*/))
+          goto __START_54_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_26_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_27_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'N' /*78*/)) || (('P' /*80*/ <= c) && (c <= 'Q' /*81*/)) || (('S' /*83*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'q' /*113*/)) || (('s' /*115*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'O' /*79*/))
+          goto __START_55_;
+        else  /*0*/ if ((c == 'R' /*82*/) || (c == 'r' /*114*/))
+          goto __START_56_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_27_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_28_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'G' /*71*/)) || (('I' /*73*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'g' /*103*/)) || (('i' /*105*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'H' /*72*/) || (c == 'h' /*104*/))
+          goto __START_57_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_28_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_29_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'H' /*72*/)) || (('J' /*74*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'h' /*104*/)) || (('j' /*106*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'I' /*73*/))
+          goto __START_48_;
+        else  /*0*/ if ((c == 'i' /*105*/))
+          goto __START_58_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_29_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_30_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'N' /*78*/)) || (('P' /*80*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'n' /*110*/)) || (('p' /*112*/ <= c) && (c <= 't' /*116*/)) || (('v' /*118*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'O' /*79*/))
+          goto __START_51_;
+        else  /*0*/ if ((c == 'o' /*111*/))
+          goto __START_59_;
+        else  /*0*/ if ((c == 'u' /*117*/))
+          goto __START_60_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_30_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_31_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Q' /*81*/)) || (('S' /*83*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'e' /*101*/)) || (('g' /*103*/ <= c) && (c <= 'q' /*113*/)) || (('s' /*115*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'R' /*82*/) || (c == 'r' /*114*/))
+          goto __START_53_;
+        else  /*0*/ if ((c == 'f' /*102*/))
+          goto __START_61_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_31_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_32_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Q' /*81*/)) || (('S' /*83*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'n' /*110*/)) || (('p' /*112*/ <= c) && (c <= 'q' /*113*/)) || (('s' /*115*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'R' /*82*/) || (c == 'r' /*114*/))
+          goto __START_56_;
+        else  /*0*/ if ((c == 'o' /*111*/))
+          goto __START_62_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_32_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_33_:
+        c = *_ch++;
+         /*0*/ if ((c == '=' /*61*/))
+          goto __START_15_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_33_;
+        }
+        goto __scan_error_;
+      __START_34_:
+        goto __accept_token_STRING_;
+      __START_35_:
+        c = *_ch++;
+         /*0*/ if (((c == '\0') && (_ch != _eob)) || (('\1' /*1*/ <= c) && (c <= '!' /*33*/)) || (('#' /*35*/ <= c) && (c <= '[' /*91*/)) || (']' /*93*/ <= c))
+          goto __START_2_;
+        else  /*0*/ if ((c == '\\' /*92*/))
+          goto __START_35_;
+        else  /*0*/ if ((c == '"' /*34*/))
+          goto __START_63_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_35_;
+        }
+        goto __scan_error_;
+      __START_36_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_64_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_36_;
+        }
+        goto __scan_error_;
+      __START_37_:
+        c = *_ch++;
+         /*0*/ if (((c == '\0') && (_ch != _eob)) || (('\1' /*1*/ <= c) && (c <= '&' /*38*/)) || (('(' /*40*/ <= c) && (c <= '[' /*91*/)) || (']' /*93*/ <= c))
+          goto __START_4_;
+        else  /*0*/ if ((c == '\\' /*92*/))
+          goto __START_37_;
+        else  /*0*/ if ((c == '\'' /*39*/))
+          goto __START_65_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta)goto __unexpected_eof_;
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_37_;
+        }
+        goto __scan_error_;
+      __START_38_:
+        goto __accept_token_LONG_COMMENT1_;
+      __START_39_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)))
+          goto __START_39_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_FLOAT_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_39_;
+        }
+        goto __accept_token_FLOAT_;
+      __START_40_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'C' /*67*/)) || (('E' /*69*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'c' /*99*/)) || (('e' /*101*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'D' /*68*/) || (c == 'd' /*100*/))
+          goto __START_66_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_40_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_41_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'B' /*66*/)) || (('D' /*68*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'b' /*98*/)) || (('d' /*100*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'C' /*67*/) || (c == 'c' /*99*/))
+          goto __START_67_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_41_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_42_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'K' /*75*/)) || (('M' /*77*/ <= c) && (c <= 'R' /*82*/)) || (('T' /*84*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'k' /*107*/)) || (('m' /*109*/ <= c) && (c <= 'r' /*114*/)) || (('t' /*116*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'L' /*76*/) || (c == 'l' /*108*/))
+          goto __START_68_;
+        else  /*0*/ if ((c == 'S' /*83*/) || (c == 's' /*115*/))
+          goto __START_69_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_42_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_43_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'R' /*82*/)) || (('T' /*84*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'r' /*114*/)) || (('t' /*116*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'S' /*83*/) || (c == 's' /*115*/))
+          goto __START_70_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_43_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_44_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'K' /*75*/)) || (('M' /*77*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'k' /*107*/)) || (('m' /*109*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'L' /*76*/) || (c == 'l' /*108*/))
+          goto __START_71_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_44_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_45_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'N' /*78*/)) || (('P' /*80*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'n' /*110*/)) || (('p' /*112*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'O' /*79*/) || (c == 'o' /*111*/))
+          goto __START_72_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_45_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_46_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'R' /*82*/)) || (('T' /*84*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'r' /*114*/)) || (('t' /*116*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'S' /*83*/) || (c == 's' /*115*/))
+          goto __START_73_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_46_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_47_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'J' /*74*/)) || (c == 'L' /*76*/) || (('N' /*78*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'l' /*108*/)) || (('n' /*110*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'K' /*75*/))
+          goto __START_74_;
+        else  /*0*/ if ((c == 'M' /*77*/) || (c == 'm' /*109*/))
+          goto __START_75_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_47_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_48_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'L' /*76*/)) || (('N' /*78*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'l' /*108*/)) || (('n' /*110*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'M' /*77*/) || (c == 'm' /*109*/))
+          goto __START_75_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_48_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_49_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'S' /*83*/)) || (('U' /*85*/ <= c) && (c <= 'V' /*86*/)) || (('X' /*88*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 's' /*115*/)) || (('u' /*117*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'T' /*84*/) || (c == 't' /*116*/))
+          goto __START_76_;
+        else  /*0*/ if ((c == 'W' /*87*/))
+          goto __START_77_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_49_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_50_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'K' /*75*/)) || (('M' /*77*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'L' /*76*/))
+          goto __START_78_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_50_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_51_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'S' /*83*/)) || (('U' /*85*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 's' /*115*/)) || (('u' /*117*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'T' /*84*/) || (c == 't' /*116*/))
+          goto __START_76_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_51_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_52_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'E' /*69*/)) || (('G' /*71*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'F' /*70*/))
+          goto __START_79_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_52_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_53_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'C' /*67*/)) || (('E' /*69*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'c' /*99*/)) || (('e' /*101*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'D' /*68*/) || (c == 'd' /*100*/))
+          goto __START_80_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_OR_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_53_;
+        }
+        goto __accept_token_OR_;
+      __START_54_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'S' /*83*/)) || (('U' /*85*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 's' /*115*/)) || (('u' /*117*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'T' /*84*/) || (c == 't' /*116*/))
+          goto __START_81_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_54_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_55_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'C' /*67*/)) || (('E' /*69*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'D' /*68*/))
+          goto __START_82_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_55_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_56_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'T' /*84*/)) || (('V' /*86*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 't' /*116*/)) || (('v' /*118*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'U' /*85*/) || (c == 'u' /*117*/))
+          goto __START_83_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_56_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_57_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'D' /*68*/)) || (('F' /*70*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'd' /*100*/)) || (('f' /*102*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'E' /*69*/) || (c == 'e' /*101*/))
+          goto __START_84_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_57_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_58_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'L' /*76*/)) || (('N' /*78*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'j' /*106*/)) || (c == 'l' /*108*/) || (('n' /*110*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'M' /*77*/) || (c == 'm' /*109*/))
+          goto __START_75_;
+        else  /*0*/ if ((c == 'k' /*107*/))
+          goto __START_85_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_58_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_59_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'S' /*83*/)) || (('U' /*85*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 's' /*115*/)) || (('u' /*117*/ <= c) && (c <= 'v' /*118*/)) || (('x' /*120*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'T' /*84*/) || (c == 't' /*116*/))
+          goto __START_76_;
+        else  /*0*/ if ((c == 'w' /*119*/))
+          goto __START_77_;
+        if ((_ch-- == _eob) && (c == '\0')) {
+          if (_eof) {
+            if ((_ch != _start) && !_lta){ _lta = true; goto __accept_token_SYMBOL_; }
+            if (!wrap()) goto __eof_seen_;
+          }
+          if (_ch + 1 == _eob) _brefill();
+          goto __START_59_;
+        }
+        goto __accept_token_SYMBOL_;
+      __START_60_:
+        c = *_ch++;
+         /*0*/ if ((('0' /*48*/ <= c) && (c <= '9' /*57*/)) || (('A' /*65*/ <= c) && (c <= 'Z' /*90*/)) || (c == '_' /*95*/) || (('a' /*97*/ <= c) && (c <= 'k' /*107*/)) || (('m' /*109*/ <= c) && (c <= 'z' /*122*/)))
+          goto __START_18_;
+        else  /*0*/ if ((c == 'l' /*108*/))
+          goto __START_86_;
+        if ((_ch--