# FQLParser.java

    // $ANTLR 2.7.7 (20060906): "fql.g" -> "FQLParser.java"$

    /*
    ** Module   : FQLParser.java
    **            FQLParserTokenTypes.java
    **            FQLLexer.java
    ** Abstract :
    **
    ** Copyright (c) 2019, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- ---------------------------------Description---------------------------------
    ** 001 OM  20190913 WARNING, THIS IS A GENERATED FILE. DO NOT EDIT THIS FILE!!!
    **                  The original source file is fql.g!
    */

    package com.goldencode.p2j.persist.orm;

    import java.util.*;
    import java.text.*;
    import java.io.*;
    import antlr.*;
    import com.goldencode.p2j.util.logging.*;

    import antlr.TokenBuffer;
    import antlr.TokenStreamException;
    import antlr.TokenStreamIOException;
    import antlr.ANTLRException;
    import antlr.LLkParser;
    import antlr.Token;
    import antlr.TokenStream;
    import antlr.RecognitionException;
    import antlr.NoViableAltException;
    import antlr.MismatchedTokenException;
    import antlr.SemanticException;
    import antlr.ParserSharedInputState;
    import antlr.collections.impl.BitSet;
    import antlr.collections.AST;
    import java.util.Hashtable;
    import antlr.ASTFactory;
    import antlr.ASTPair;
    import antlr.collections.impl.ASTArray;

    /**
     * Creates an Abstract Syntax Tree (AST) representation of an FQL expression in infix notation
     * from an input stream of tokens (provided by the {@link FQLLexer}). More specifically, the
     * parser does the following:
     * <ul>
     *    <li> Drives the lexer by calling its' {@code nextToken} method. This method tokenizes the
     *         lexer's input stream of characters and returns the next found {@code Token} object.
     *    <li> Provides the {@link #expression} and {@link #statement} methods as an entry points.
     *    <li> Builds an AST (&quot;intermediate form representation&quot;) of all the recognized
     *         tokens. This AST is designed for subsequent processing by the FQL to SQL converter.
     *    <li> Handles the context sensitive aspects of symbol resolution.
     *    <li> To the extent that is possible while still generating a well structured tree, the
     *         parser has been structured to enforce syntactic correctness.
     * </ul>
     * <p>
     * This grammar is highly specific to ANTLR 2.7.x and it may not be valid in future versions of
     * ANTLR. This is due to the fact that the generated code and the grammar syntax of ANTLR can
     * change between versions. These factors are the most important constraints defining the
     * structure of the resulting grammar. As a result, it is possible that the grammar will require
     * changes to run in future versions of ANTLR.
     * <p>
     * <b>This is a generated file using ANTLR 2.7.4 and a grammar specified in {@code fql.g}.</b>
     */
    public class FQLParser extends antlr.LLkParser       implements FQLParserTokenTypes
     {

       /** Logger. */
       private static final CentralLogger LOG = CentralLogger.get(FQLParser.class);

       /** Name of the specialized AST class to use when parsing. */
       private static final Class<FQLAst> AST_CLASS = FQLAst.class;

       /** Provides an efficient reverse lookup of names to token types. */
       private static Map<String, Integer> tokenLookup = null;

       /** Next index value to be assigned to a query substitution node */
       private int nextSubstitutionIndex = 0;

       /**
        * Simple walker to print out the contents of an AST for debugging.
        *
        * @param    ast
        *           The current node to print.
        * @param    level
        *           The number of levels down from the root (0 == root node),
        *           which determines the indention level to print.
        */
       public static void visit(CommonAST ast, int level)
       {
          int          spaces = level * 3;
          StringBuilder sb    = new StringBuilder();

          // generate the indent based on the level from the root
          for (int i = 0; i < spaces; i++)
          {
             sb.append(' ');
          }

          // add our current node's text
          sb.append("[ ");
          sb.append(ast.getText());
          sb.append(" ] <");
          sb.append(_tokenNames[ast.getType()]);
          sb.append(">");

          // print out the current node
          System.out.println(sb);

          CommonAST child = (CommonAST) ast.getFirstChild();
          level++;

          // now visit all children
          while (child != null)
          {
             visit(child, level);
             child = (CommonAST) child.getNextSibling();
          }
       }

       /**
        * Translates a text representation of a parser token type into the
        * actual integer value.
        *
        * @param    tokenName
        *           The text representation of the parser token type.
        *
        * @return   A valid parser-defined integer token type value or -1 if
        *           no match was found.
        */
       public static int lookupTokenType(String tokenName)
       {
          // initialize map if necessary
          if (tokenLookup == null)
          {
             int len = _tokenNames.length;

             tokenLookup = new HashMap<>();

             // load the map with our lower-cased symbolic name as the key and
             // the wrapped int token type as the value
             for (int i = 0; i < len; i++)
             {
                tokenLookup.put(_tokenNames[i].toLowerCase(), i);
             }
          }

          Integer result = tokenLookup.get(tokenName.toLowerCase());

          return (result == null ? -1 : result);
       }

       /**
        * Translates an integer value of a parser token type into the associated
        * human readable text representation.
        *
        * @param    type
        *           The integer token type.
        *
        * @return   A valid parser-defined symbolic name or {@code null} if no match was found.
        */
       public static String lookupTokenName(int type)
       {
          if (type < 0 || type >= _tokenNames.length)
          {
             return null;
          }

          return _tokenNames[type];
       }

       /**
        * Implements special processing for {@code NULL} equality and inequality tests. If a
        * {@code NULL} token is detected on either side of either of the operators, the result will
        * be rooted at an {@code IS_NULL} (equality) or {@code NOT_NULL} (inequality) node. The
        * operand that is {@code NULL} will be dropped and the other operand will be the only child.
        * <p>
        * This is separated from the main processing and really is a kind of post-processing of the
        * entire tree.
        */
       public void convertNullTest(CommonAST ast)
       {
          int type = ast.getType();

          // process the current node, only equality and inequality are of interest
          if (type == EQUALS || type == NOT_EQ)
          {
             CommonAST first  = (CommonAST) ast.getFirstChild();
             CommonAST second = (CommonAST) first.getNextSibling();
             if (second == null)
             {
                LOG.severe(
                      "Something is wrong with " + ast + " token " + "@" + ast.getLine() + ":" + ast.getColumn());
                return;
             }

             int ftype = first.getType();
             int stype = second.getType();

             // detect comparisons with NULL and rewrite the sub-expression
             if (ftype == NULL || stype == NULL)
             {
                // special case that can be optimized easily
                if (ftype == NULL && stype == NULL)
                {
                   ast.setType(type == EQUALS ? BOOL_TRUE : BOOL_FALSE);
                   ast.removeChildren();
                }
                else
                {
                   // normal case: rewrite the token as our artificial unary
                   // operator
                   ast.setType(type == EQUALS ? IS_NULL : NOT_NULL);

                   // only leave the non-NULL child behind as the single operand
                   if (first.getType() == NULL)
                   {
                      ast.setFirstChild(second);
                   }
                   else
                   {
                      first.setNextSibling(null);
                   }
                }
             }
          }

          // either way, process all children using a recursive call
          CommonAST child = (CommonAST) ast.getFirstChild();

          while (child != null)
          {
             convertNullTest(child);
             child = (CommonAST) child.getNextSibling();
          }
       }

       /**
        * Parser error-reporting function.
        *
        * TODO:  reimplement to use logging...
        */
       public void reportError(RecognitionException exc)
       {
          super.reportError(exc);
       }

       private FqlToSqlConverter listener = null;
       public void setListener(FqlToSqlConverter fql)
       {
          this.listener = fql;
       }

       /**
        * Provides a command line interface for an end user to drive and/or test
        * the FQLParser class.
        * <p>
        * Syntax:
        * <pre>
        *    java FQLParser &lt;expression&gt;
        * </pre>
        *
        * @param   args
        *          List of command line arguments.
        */
       public static void main(String[] args)
       {
          if (args.length != 1)
          {
             LOG.severe("Syntax: java FQLParser <expression>");
             System.exit(-1);
          }

          try
          {
             StringReader expr   = new StringReader(args[0]);
             FQLLexer   lexer  = new FQLLexer(expr);
             FQLParser  parser = new FQLParser(lexer);

             BaseAST.setVerboseStringConversion(true, _tokenNames);

             parser.expression();

             FQLAst result = (FQLAst) parser.getAST();

             result.fixups(null, null);

             // print out report
             visit(result, 0);
          }
          catch (Exception excpt)
          {
             LOG.severe("", excpt);
          }
       }

    protected FQLParser(TokenBuffer tokenBuf, int k) {
      super(tokenBuf,k);
      tokenNames = _tokenNames;
      buildTokenTypeASTClassMap();
      astFactory = new ASTFactory(getTokenTypeToASTClassMap());
    }

    public FQLParser(TokenBuffer tokenBuf) {
      this(tokenBuf,3);
    }

    protected FQLParser(TokenStream lexer, int k) {
      super(lexer,k);
      tokenNames = _tokenNames;
      buildTokenTypeASTClassMap();
      astFactory = new ASTFactory(getTokenTypeToASTClassMap());
    }

    public FQLParser(TokenStream lexer) {
      this(lexer,3);
    }

    public FQLParser(ParserSharedInputState state) {
      super(state,3);
      tokenNames = _tokenNames;
      buildTokenTypeASTClassMap();
      astFactory = new ASTFactory(getTokenTypeToASTClassMap());
    }

    /** Matches all four FQL statements. This is the primary "entry point" for FQL expression parsing. */
    	public final void statement() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst statement_AST = null;

    		try {      // for error handling
    			astFactory.setASTNodeClass(AST_CLASS);
    			{
    			switch ( LA(1)) {
    			case FROM:
    			case SELECT:
    			{
    				selectStatement();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case INSERT:
    			{
    				insertStatement();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case UPDATE:
    			{
    				updateStatement();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case DELETE:
    			{
    				deleteStatement();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			statement_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_0);
    		}
    		returnAST = statement_AST;
    	}

    /** Matches the {@code SELECT} FQL statements. */
    	public final void selectStatement() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst selectStatement_AST = null;

    		try {      // for error handling
    			astFactory.makeASTRoot(currentAST, (FQLAst)astFactory.create(SELECT_STMT,"select statement"));
    			{
    			switch ( LA(1)) {
    			case SELECT:
    			{
    				select_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case FROM:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			from_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			if ((LA(1)==WHERE) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    				where_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			{
    			if ((LA(1)==GROUP) && (LA(2)==BY) && (_tokenSet_1.member(LA(3)))) {
    				groupBy_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			{
    			if ((LA(1)==ORDER) && (LA(2)==BY) && (_tokenSet_1.member(LA(3)))) {
    				orderBy_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			{
    			if ((LA(1)==SINGLE) && (_tokenSet_3.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    				FQLAst tmp1_AST = null;
    				tmp1_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp1_AST);
    				match(SINGLE);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			selectStatement_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = selectStatement_AST;
    	}

    /** Matches the {@code INSERT} FQL statements. */
    	public final void insertStatement() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst insertStatement_AST = null;

    		try {      // for error handling
    			astFactory.makeASTRoot(currentAST, (FQLAst)astFactory.create(INSERT_STMT,"insert statement"));
    			FQLAst tmp2_AST = null;
    			tmp2_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.addASTChild(currentAST, tmp2_AST);
    			match(INSERT);
    			match(INTO);
    			dmo();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			switch ( LA(1)) {
    			case LPARENS:
    			{
    				property_list();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case VALUES:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			{
    			values_list();
    			astFactory.addASTChild(currentAST, returnAST);
    			}
    			insertStatement_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_0);
    		}
    		returnAST = insertStatement_AST;
    	}

    /** Matches the {@code UPDATE} FQL statements. */
    	public final void updateStatement() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst updateStatement_AST = null;

    		try {      // for error handling
    			astFactory.makeASTRoot(currentAST, (FQLAst)astFactory.create(UPDATE_STMT,"update statement"));
    			FQLAst tmp4_AST = null;
    			tmp4_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.addASTChild(currentAST, tmp4_AST);
    			match(UPDATE);
    			dmo();
    			astFactory.addASTChild(currentAST, returnAST);
    			set_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			switch ( LA(1)) {
    			case WHERE:
    			{
    				where_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case EOF:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			updateStatement_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_0);
    		}
    		returnAST = updateStatement_AST;
    	}

    /** Matches the {@code DELETE} FQL statements. */
    	public final void deleteStatement() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst deleteStatement_AST = null;

    		try {      // for error handling
    			astFactory.makeASTRoot(currentAST, (FQLAst)astFactory.create(DELETE_STMT,"delete statement"));
    			FQLAst tmp5_AST = null;
    			tmp5_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.addASTChild(currentAST, tmp5_AST);
    			match(DELETE);
    			from_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			switch ( LA(1)) {
    			case WHERE:
    			{
    				where_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case EOF:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			deleteStatement_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_0);
    		}
    		returnAST = deleteStatement_AST;
    	}

    	public final void dmo() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst dmo_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.makeASTRoot(currentAST, s_AST);
    			match(SYMBOL);
    			s_AST.setType(DMO);
    			dmo_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_6);
    		}
    		returnAST = dmo_AST;
    	}

    /** Matches the optional list of properties/columns in a INSERT INTO statement. */
    	public final void property_list() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst property_list_AST = null;

    		try {      // for error handling
    			FQLAst tmp6_AST = null;
    			tmp6_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp6_AST);
    			match(LPARENS);
    			property();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop113:
    			do {
    				if ((LA(1)==COMMA)) {
    					match(COMMA);
    					property();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop113;
    				}

    			} while (true);
    			}
    			match(RPARENS);
    			property_list_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_7);
    		}
    		returnAST = property_list_AST;
    	}

    /** Matches the list of values in a INSERT INTO statement. */
    	public final void values_list() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst values_list_AST = null;

    		try {      // for error handling
    			FQLAst tmp9_AST = null;
    			tmp9_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp9_AST);
    			match(VALUES);
    			match(LPARENS);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop116:
    			do {
    				if ((LA(1)==COMMA)) {
    					match(COMMA);
    					expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop116;
    				}

    			} while (true);
    			}
    			match(RPARENS);
    			values_list_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_0);
    		}
    		returnAST = values_list_AST;
    	}

    /** Matches the SET phrase for an UPDATE statement. */
    	public final void set_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst set_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp13_AST = null;
    			tmp13_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp13_AST);
    			match(SET);
    			update_field();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop92:
    			do {
    				if ((LA(1)==COMMA)) {
    					match(COMMA);
    					update_field();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop92;
    				}

    			} while (true);
    			}
    			set_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_8);
    		}
    		returnAST = set_expr_AST;
    	}

    /**
     * Matches a where phrase embedded within a where clause as part of a subselect statement. Called
     * by {@link #selectStatement}, {@link #updateStatement}, and {@link #deleteStatement} rules.
     * Recursively calls {@link #expr} rule.
     */
    	public final void where_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst where_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp15_AST = null;
    			tmp15_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp15_AST);
    			match(WHERE);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			where_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = where_expr_AST;
    	}

    /**
     * Matches a from phrase embedded within a where clause as part of a select or subselect
     * statement. Called by {@link #selectStatement} and {@link #deleteStatement} rules.
     */
    	public final void from_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst from_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp16_AST = null;
    			tmp16_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp16_AST);
    			match(FROM);
    			dmo();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			if ((LA(1)==AS||LA(1)==SYMBOL) && (_tokenSet_9.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    				as_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			{
    			_loop69:
    			do {
    				if ((_tokenSet_10.member(LA(1))) && (LA(2)==JOIN||LA(2)==OUTER||LA(2)==SYMBOL) && (_tokenSet_11.member(LA(3)))) {
    					join_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else if ((LA(1)==JOIN) && (LA(2)==SYMBOL) && (LA(3)==AS||LA(3)==SYMBOL||LA(3)==LBRACKET)) {
    					join_extent();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop69;
    				}

    			} while (true);
    			}
    			{
    			_loop74:
    			do {
    				if ((LA(1)==COMMA) && (LA(2)==SYMBOL) && (_tokenSet_9.member(LA(3)))) {
    					match(COMMA);
    					dmo();
    					astFactory.addASTChild(currentAST, returnAST);
    					{
    					if ((LA(1)==AS||LA(1)==SYMBOL) && (_tokenSet_9.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    						as_expr();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    					}
    					else {
    						throw new NoViableAltException(LT(1), getFilename());
    					}

    					}
    					{
    					_loop73:
    					do {
    						if ((_tokenSet_10.member(LA(1))) && (LA(2)==JOIN||LA(2)==OUTER||LA(2)==SYMBOL) && (_tokenSet_11.member(LA(3)))) {
    							join_expr();
    							astFactory.addASTChild(currentAST, returnAST);
    						}
    						else if ((LA(1)==JOIN) && (LA(2)==SYMBOL) && (LA(3)==AS||LA(3)==SYMBOL||LA(3)==LBRACKET)) {
    							join_extent();
    							astFactory.addASTChild(currentAST, returnAST);
    						}
    						else {
    							break _loop73;
    						}

    					} while (true);
    					}
    				}
    				else {
    					break _loop74;
    				}

    			} while (true);
    			}
    			from_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = from_expr_AST;
    	}

    /**
     * Matches a select phrase embedded within a where clause as part of a subselect statement.
     * Called by {@link #selectStatement} rule.
     * <p>
     * At this moment we are unable to detect whether the SYMBOLS under SELECT are really {@code alias} or
     * {@code property}. It can be a alias/DMO (optionally with a package path) or a property
     * (optionally qualified with alias name). This needs to be done, at preprocessing time.
     * <p>
     * See {@code FqlToSqlConverter.processSelect(FQLAst)}.
     */
    	public final void select_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst select_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp18_AST = null;
    			tmp18_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp18_AST);
    			match(SELECT);
    			{
    			{
    			if ((LA(1)==SYMBOL) && (LA(2)==LPARENS) && (_tokenSet_12.member(LA(3)))) {
    				function();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((LA(1)==SYMBOL) && (LA(2)==FROM||LA(2)==COMMA||LA(2)==LBRACKET)) {
    				property();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((LA(1)==SYMBOL) && (LA(2)==LPARENS) && (LA(3)==RPARENS||LA(3)==MULTIPLY||LA(3)==SYMBOL)) {
    				aggregate();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_13.member(LA(1)))) {
    				literal();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			{
    			_loop80:
    			do {
    				if ((LA(1)==COMMA)) {
    					match(COMMA);
    					{
    					if ((LA(1)==SYMBOL) && (LA(2)==LPARENS) && (_tokenSet_12.member(LA(3)))) {
    						function();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else if ((LA(1)==SYMBOL) && (LA(2)==FROM||LA(2)==COMMA||LA(2)==LBRACKET)) {
    						property();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else if ((LA(1)==SYMBOL) && (LA(2)==LPARENS) && (LA(3)==RPARENS||LA(3)==MULTIPLY||LA(3)==SYMBOL)) {
    						aggregate();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else if ((_tokenSet_13.member(LA(1)))) {
    						literal();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else {
    						throw new NoViableAltException(LT(1), getFilename());
    					}

    					}
    				}
    				else {
    					break _loop80;
    				}

    			} while (true);
    			}
    			}
    			select_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_14);
    		}
    		returnAST = select_expr_AST;
    	}

    /** Matches a GROUP BY clause, including the optional HAVING clause. */
    	public final void groupBy_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst groupBy_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp20_AST = null;
    			tmp20_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp20_AST);
    			match(GROUP);
    			match(BY);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop97:
    			do {
    				if ((LA(1)==COMMA) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					match(COMMA);
    					expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop97;
    				}

    			} while (true);
    			}
    			{
    			if ((LA(1)==HAVING) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    				having_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			groupBy_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = groupBy_expr_AST;
    	}

    /**
     * Matches an ORDER-BY clause in a FQL statement.
     * <p>
     * Some dialects (PostgreSQL) allows complex expressions to be applied to properties.
     */
    	public final void orderBy_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst orderBy_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp23_AST = null;
    			tmp23_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp23_AST);
    			match(ORDER);
    			match(BY);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop102:
    			do {
    				if ((LA(1)==ASC) && (_tokenSet_3.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    					FQLAst tmp25_AST = null;
    					tmp25_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp25_AST);
    					match(ASC);
    				}
    				else if ((LA(1)==DESC) && (_tokenSet_3.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    					FQLAst tmp26_AST = null;
    					tmp26_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp26_AST);
    					match(DESC);
    				}
    				else {
    					break _loop102;
    				}

    			} while (true);
    			}
    			{
    			_loop106:
    			do {
    				if ((LA(1)==COMMA) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					match(COMMA);
    					expr();
    					astFactory.addASTChild(currentAST, returnAST);
    					{
    					_loop105:
    					do {
    						if ((LA(1)==ASC) && (_tokenSet_3.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    							FQLAst tmp28_AST = null;
    							tmp28_AST = (FQLAst)astFactory.create(LT(1));
    							astFactory.addASTChild(currentAST, tmp28_AST);
    							match(ASC);
    						}
    						else if ((LA(1)==DESC) && (_tokenSet_3.member(LA(2))) && (_tokenSet_4.member(LA(3)))) {
    							FQLAst tmp29_AST = null;
    							tmp29_AST = (FQLAst)astFactory.create(LT(1));
    							astFactory.addASTChild(currentAST, tmp29_AST);
    							match(DESC);
    						}
    						else {
    							break _loop105;
    						}

    					} while (true);
    					}
    				}
    				else {
    					break _loop106;
    				}

    			} while (true);
    			}
    			orderBy_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = orderBy_expr_AST;
    	}

    /**
     * Parses an FQL expression and creates an AST that is suitable for further processing. This is
     * the secondary "entry point" for FQL expression parsing. The AST node class is set here (to
     * {@link FQLAst}).
     * <p>
     * The AST is structured with operator nodes as the root nodes and each operator (unary or binary)
     * has the matching number of child nodes (1 or 2 respectively). Each child node is an operand and
     * the semantics of left and right operands (for binary operators) is maintained.
     * <p>
     * Non-operator nodes in the tree can be literals or FQL functions. The list of literals can be
     * seen in the {@link #literal} rule.
     * <p>
     * All of the following operators are supported and the precedence order follows that of SQL,
     * which we assume is the same precedence order used by FQL.
     * <pre>
     * lowest  logical OR              :  or
     *    |    conditional AND         :  and
     *    |    equality                :  =
     *    |    relational              :  &lt;, &gt;, &le;, &ge;
     *    |    additive                :  +, -
     *    |    multiplicative          :  *, /
     *    |    unary operators         :  -, not
     *    V    function call           :  function_name(...)
     * highest parentheses             :  (...)
     * </pre>
     * <p>
     * To handle the precedence issue, each precedence level (see the table above) is handled in a
     * separate rule. Starting at in this top level entry point, the lowest precedence rule is
     * referenced. This reference is made with an optional {@code OR} operator. If this operator is
     * present, it is the root of the resulting tree. This means it is the last operator to be
     * evaluated since its operands will be processed first. This is the proper definition of lowest
     * precedence. If this operator is present, then a second operand is expected.
     * <p>
     * Each precedence level is similarly constructed, the left operand being required, all operators
     * being optional and each operator choice an equal alternative. If any of the operators exists,
     * then it is the root of the subtree and a right operand is expected. This holds true for all
     * rules that process binary operators. Please note that this left-mandatory and optional right
     * side (operator + right operand) is critical for allowing an expression to be as simple as a
     * single variable, function call or literal. Alternatively, it can expand into a highly nested
     * set of recursively parsed expressions that all evaluate to a single scalar result.
     * <p>
     * At the bottom of the hierarchy of rules are unary operators, these are implemented as an
     * optional prefix operator and a mandatory right operand.
     * <p>
     * The final level is the primary expression. This is where the precedence operator parenthesis is
     * handled.  It also is where we allow a single literal, alias, or function reference.
     * <p>
     * The {@link #expr} rule is called as the only rule reference.
     * <p>
     */
    	public final void expression() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst expression_AST = null;
    		FQLAst e_AST = null;

    		try {      // for error handling
    			astFactory.setASTNodeClass(AST_CLASS);
    			expr();
    			e_AST = (FQLAst)returnAST;
    			astFactory.addASTChild(currentAST, returnAST);
    			expression_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_15);
    		}
    		returnAST = expression_AST;
    	}

    /**
     * Implements the lowest (1st) precedence level of expressions: {@code OR} (the logical OR
     * operator). Valid expressions can contain sub-expressions and this entry point is properly
     * recursive without causing any ambiguity.
     * <p>
     * This rule is designed to allow recursion (the highest precedence levels {@link #function} and
     * {@link #primary_expr} reference this rule again, allowing infinite nesting of sub-expressions,
     * with proper parsing, evaluation and tree building.
     * <p>
     * This method is called by the top level {@link #expression} rule. This method calls the
     * {@link #log_and_expr} rule.
     * <p>
     * Implements special processing for {@code NULL} equality and inequality tests. If a {@code NULL}
     * token is detected on either side of either of the operators, the result will be rooted at an
     * {@code IS_NULL} (equality) or {@code NOT_NULL} (inequality) node. The operand that is
     * {@code NULL} will be dropped and the other operand will be the only child. This must be
     * implemented after the entire tree is created and the method {@link #convertNullTest} is used
     * to implement this processing.
     */
    	public final void expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst expr_AST = null;

    		try {      // for error handling
    			{
    			log_and_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop20:
    			do {
    				if ((LA(1)==OR) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					FQLAst tmp30_AST = null;
    					tmp30_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp30_AST);
    					match(OR);
    					log_and_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop20;
    				}

    			} while (true);
    			}
    			}
    			expr_AST = (FQLAst)currentAST.root;

    			// convert all equality and inequality tests against the null literal into a special operator
    			convertNullTest((CommonAST) expr_AST);

    			expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = expr_AST;
    	}

    /**
     * Implements the 2nd lowest precedence level of expressions: {@code AND} (the logical AND operator).
     * <p>
     * This is only called by the {@link #expr} rule. This method calls the {@link #equality_expr} rule.
     */
    	public final void log_and_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst log_and_expr_AST = null;

    		try {      // for error handling
    			equality_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop23:
    			do {
    				if ((LA(1)==AND) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					FQLAst tmp31_AST = null;
    					tmp31_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp31_AST);
    					match(AND);
    					equality_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop23;
    				}

    			} while (true);
    			}
    			log_and_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = log_and_expr_AST;
    	}

    /**
     * Implements the 3rd lowest precedence level of expressions - the equality operators.
     * <p>
     * This is only called by the {@link #log_and_expr} rule. This method calls the {@link #compare_expr} rule.
     * <p>
     * Provides the following operators:
     * <pre>
     *    =        (equality)
     *    !=       (inequality)
     * </pre>
     */
    	public final void equality_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst equality_expr_AST = null;
    		Token  i = null;
    		FQLAst i_AST = null;

    		try {      // for error handling
    			compare_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop29:
    			do {
    				if ((LA(1)==EQUALS||LA(1)==NOT_EQ) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					{
    					{
    					switch ( LA(1)) {
    					case EQUALS:
    					{
    						FQLAst tmp32_AST = null;
    						tmp32_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp32_AST);
    						match(EQUALS);
    						break;
    					}
    					case NOT_EQ:
    					{
    						FQLAst tmp33_AST = null;
    						tmp33_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp33_AST);
    						match(NOT_EQ);
    						break;
    					}
    					default:
    					{
    						throw new NoViableAltException(LT(1), getFilename());
    					}
    					}
    					}
    					compare_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    					}
    				}
    				else if ((LA(1)==IS) && (LA(2)==NOT||LA(2)==NULL) && (_tokenSet_16.member(LA(3)))) {
    					i = LT(1);
    					i_AST = (FQLAst)astFactory.create(i);
    					astFactory.makeASTRoot(currentAST, i_AST);
    					match(IS);
    					i_AST.setType(IS_NULL);
    					{
    					switch ( LA(1)) {
    					case NOT:
    					{
    						match(NOT);
    						i_AST.setType(NOT_NULL);
    						break;
    					}
    					case NULL:
    					{
    						break;
    					}
    					default:
    					{
    						throw new NoViableAltException(LT(1), getFilename());
    					}
    					}
    					}
    					match(NULL);
    				}
    				else {
    					break _loop29;
    				}

    			} while (true);
    			}
    			equality_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = equality_expr_AST;
    	}

    /**
     * Implements the 4th lowest precedence level of expressions - the comparison operators.
     * <p>
     * This is only called by the {@link #equality_expr} rule. This method calls the {@link #concat_expr} rule.
     * <p>
     * Provides the following operators:
     * <pre>
     *    &gt;    (greater than)
     *    &lt;    (less than)
     *    &ge;   (greater than or equal to)
     *    &le;   (less than or equal to)
     *    like
     * </pre>
     */
    	public final void compare_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst compare_expr_AST = null;

    		try {      // for error handling
    			boolean isLike = false;
    			concat_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			if ((LA(1)==IN) && (LA(2)==LPARENS) && (_tokenSet_1.member(LA(3)))) {
    				FQLAst tmp36_AST = null;
    				tmp36_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.makeASTRoot(currentAST, tmp36_AST);
    				match(IN);
    				match(LPARENS);
    				expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				{
    				_loop33:
    				do {
    					if ((LA(1)==COMMA)) {
    						match(COMMA);
    						expr();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else {
    						break _loop33;
    					}

    				} while (true);
    				}
    				match(RPARENS);
    			}
    			else if (((LA(1) >= GT && LA(1) <= LIKE)) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    				{
    				switch ( LA(1)) {
    				case GT:
    				{
    					FQLAst tmp40_AST = null;
    					tmp40_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp40_AST);
    					match(GT);
    					break;
    				}
    				case LT:
    				{
    					FQLAst tmp41_AST = null;
    					tmp41_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp41_AST);
    					match(LT);
    					break;
    				}
    				case GTE:
    				{
    					FQLAst tmp42_AST = null;
    					tmp42_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp42_AST);
    					match(GTE);
    					break;
    				}
    				case LTE:
    				{
    					FQLAst tmp43_AST = null;
    					tmp43_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp43_AST);
    					match(LTE);
    					break;
    				}
    				case LIKE:
    				{
    					FQLAst tmp44_AST = null;
    					tmp44_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp44_AST);
    					match(LIKE);
    					isLike = true;
    					break;
    				}
    				default:
    				{
    					throw new NoViableAltException(LT(1), getFilename());
    				}
    				}
    				}
    				concat_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				{
    				if (((LA(1)==ESCAPE) && (LA(2)==STRING) && (_tokenSet_3.member(LA(3))))&&( isLike )) {
    					FQLAst tmp45_AST = null;
    					tmp45_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp45_AST);
    					match(ESCAPE);
    					FQLAst tmp46_AST = null;
    					tmp46_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp46_AST);
    					match(STRING);
    				}
    				else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    				}
    				else {
    					throw new NoViableAltException(LT(1), getFilename());
    				}

    				}
    			}
    			else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
    			}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}

    			}
    			compare_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = compare_expr_AST;
    	}

    /**
     * Implements the 5th lowest precedence level of expressions - concatenation.
     * <p>
     * This is only called by the {@link #compare_expr} rule. This method calls the {@link #sum_expr} rule.
     * <p>
     * Provides the following operator:
     * <pre>
     *    ||   (concatenation of two string operands)
     * </pre>
     */
    	public final void concat_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst concat_expr_AST = null;

    		try {      // for error handling
    			sum_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop38:
    			do {
    				if ((LA(1)==CONCAT) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					FQLAst tmp47_AST = null;
    					tmp47_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.makeASTRoot(currentAST, tmp47_AST);
    					match(CONCAT);
    					sum_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop38;
    				}

    			} while (true);
    			}
    			concat_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = concat_expr_AST;
    	}

    /**
     * Implements the 5th lowest precedence level of expressions - the additive operators.
     * <p>
     * This is only called by the {@link #compare_expr} rule. This method calls the {@link #prod_expr} rule.
     * <p>
     * Provides the following operators:
     * <pre>
     *    + (binary plus)
     *    - (binary minus)
     * </pre>
     */
    	public final void sum_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst sum_expr_AST = null;

    		try {      // for error handling
    			prod_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop42:
    			do {
    				if ((LA(1)==PLUS||LA(1)==MINUS) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					{
    					switch ( LA(1)) {
    					case PLUS:
    					{
    						FQLAst tmp48_AST = null;
    						tmp48_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp48_AST);
    						match(PLUS);
    						break;
    					}
    					case MINUS:
    					{
    						FQLAst tmp49_AST = null;
    						tmp49_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp49_AST);
    						match(MINUS);
    						break;
    					}
    					default:
    					{
    						throw new NoViableAltException(LT(1), getFilename());
    					}
    					}
    					}
    					prod_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop42;
    				}

    			} while (true);
    			}
    			sum_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = sum_expr_AST;
    	}

    /**
     * Implements the 6th lowest precedence level of expressions - the multiplicative operators.
     * <p>
     * This is only called by the {@link #sum_expr} rule. This method calls the {@link #un_expr} rule.
     * <p>
     * Provides the following operators:
     * <pre>
     *    * (multiply)
     *    / (divide)
     * </pre>
     */
    	public final void prod_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst prod_expr_AST = null;

    		try {      // for error handling
    			un_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			_loop46:
    			do {
    				if ((LA(1)==MULTIPLY||LA(1)==DIVIDE) && (_tokenSet_1.member(LA(2))) && (_tokenSet_2.member(LA(3)))) {
    					{
    					switch ( LA(1)) {
    					case MULTIPLY:
    					{
    						FQLAst tmp50_AST = null;
    						tmp50_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp50_AST);
    						match(MULTIPLY);
    						break;
    					}
    					case DIVIDE:
    					{
    						FQLAst tmp51_AST = null;
    						tmp51_AST = (FQLAst)astFactory.create(LT(1));
    						astFactory.makeASTRoot(currentAST, tmp51_AST);
    						match(DIVIDE);
    						break;
    					}
    					default:
    					{
    						throw new NoViableAltException(LT(1), getFilename());
    					}
    					}
    					}
    					un_expr();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else {
    					break _loop46;
    				}

    			} while (true);
    			}
    			prod_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = prod_expr_AST;
    	}

    /**
     * Implements the 7th lowest precedence level of expressions - the unary operators.
     * <p>
     * This is only called by the {@link #prod_expr} rule. This method calls the {@link #primary_expr} rule.
     * <p>
     * Provides the following operators:
     * <pre>
     *    -                  unary minus
     *    not                logical NOT
     * </pre>
     */
    	public final void un_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst un_expr_AST = null;
    		Token  m = null;
    		FQLAst m_AST = null;

    		try {      // for error handling
    			String cls = null;
    			{
    			{
    			switch ( LA(1)) {
    			case MINUS:
    			{
    				m = LT(1);
    				m_AST = (FQLAst)astFactory.create(m);
    				astFactory.makeASTRoot(currentAST, m_AST);
    				match(MINUS);
    				m_AST.setType( UN_MINUS );
    				break;
    			}
    			case NOT:
    			{
    				FQLAst tmp52_AST = null;
    				tmp52_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.makeASTRoot(currentAST, tmp52_AST);
    				match(NOT);
    				break;
    			}
    			case BOOL_FALSE:
    			case BOOL_TRUE:
    			case CASE:
    			case CAST:
    			case DEC_LITERAL:
    			case FROM:
    			case NULL:
    			case SELECT:
    			case LPARENS:
    			case STRING:
    			case SYMBOL:
    			case NUM_LITERAL:
    			case LONG_LITERAL:
    			case SUBST:
    			case POSITIONAL:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			primary_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			}
    			un_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = un_expr_AST;
    	}

    /**
     * Implements the 8th and highest precedence level of expressions, the parenthesis precedence
     * operators, {@link #literal}, {@link #function}, {@link #ternary}, {@link #property},
     * {@link #selectStatement}, and {@link #parentheses} rules.
     * <p>
     * This rule is different in structure from the previous levels, as the there is just a set of
     * alternatives and one of them allows direct recursion back to the {@code expr} expression point.
     * <p>
     * This is only called by the {@link #un_expr} rule.
     * <p>
     * See the rule {@link #expr} for more details.
     */
    	public final void primary_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst primary_expr_AST = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			{
    			switch ( LA(1)) {
    			case BOOL_FALSE:
    			case BOOL_TRUE:
    			case DEC_LITERAL:
    			case NULL:
    			case STRING:
    			case NUM_LITERAL:
    			case LONG_LITERAL:
    			case SUBST:
    			case POSITIONAL:
    			{
    				literal();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case CAST:
    			{
    				cast();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case CASE:
    			{
    				ternary();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case LPARENS:
    			{
    				parentheses();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case FROM:
    			case SELECT:
    			{
    				selectStatement();
    				s_AST = (FQLAst)returnAST;
    				astFactory.addASTChild(currentAST, returnAST);

    				s_AST.setType(SUBSELECT);
    				s_AST.setText("subselect");

    				break;
    			}
    			default:
    				if ((LA(1)==SYMBOL) && (LA(2)==LPARENS)) {
    					function();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    				else if ((LA(1)==SYMBOL) && (_tokenSet_17.member(LA(2)))) {
    					property();
    					astFactory.addASTChild(currentAST, returnAST);
    				}
    			else {
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			primary_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = primary_expr_AST;
    	}

    /**
     * Matches all variations of expression literals (constants).  This includes:
     * <pre>
     *    NUM_LITERAL
     *    LONG_LITERAL
     *    DEC_LITERAL
     *    STRING
     *    BOOL_TRUE
     *    BOOL_FALSE
     *    NULL
     *    SUBST
     *    POSITIONAL
     * </pre>
     */
    	public final void literal() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst literal_AST = null;

    		try {      // for error handling
    			switch ( LA(1)) {
    			case NUM_LITERAL:
    			{
    				FQLAst tmp53_AST = null;
    				tmp53_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp53_AST);
    				match(NUM_LITERAL);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case LONG_LITERAL:
    			{
    				FQLAst tmp54_AST = null;
    				tmp54_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp54_AST);
    				match(LONG_LITERAL);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case DEC_LITERAL:
    			{
    				FQLAst tmp55_AST = null;
    				tmp55_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp55_AST);
    				match(DEC_LITERAL);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case STRING:
    			{
    				FQLAst tmp56_AST = null;
    				tmp56_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp56_AST);
    				match(STRING);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case BOOL_TRUE:
    			{
    				FQLAst tmp57_AST = null;
    				tmp57_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp57_AST);
    				match(BOOL_TRUE);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case BOOL_FALSE:
    			{
    				FQLAst tmp58_AST = null;
    				tmp58_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp58_AST);
    				match(BOOL_FALSE);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case NULL:
    			{
    				FQLAst tmp59_AST = null;
    				tmp59_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp59_AST);
    				match(NULL);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case SUBST:
    			{
    				substitution();
    				astFactory.addASTChild(currentAST, returnAST);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			case POSITIONAL:
    			{
    				positional_param();
    				astFactory.addASTChild(currentAST, returnAST);
    				literal_AST = (FQLAst)currentAST.root;
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_18);
    		}
    		returnAST = literal_AST;
    	}

    /**
     * Matches a CAST FQL primary expression in which the value of an expression is converted to a specified type.
     * For the moment the data type is a loose symbol.
     */
    	public final void cast() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst cast_AST = null;
    		Token  datatype = null;
    		FQLAst datatype_AST = null;

    		try {      // for error handling
    			FQLAst tmp60_AST = null;
    			tmp60_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp60_AST);
    			match(CAST);
    			match(LPARENS);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			match(AS);
    			datatype = LT(1);
    			datatype_AST = (FQLAst)astFactory.create(datatype);
    			astFactory.addASTChild(currentAST, datatype_AST);
    			match(SYMBOL);
    			match(RPARENS);
    			cast_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = cast_AST;
    	}

    /**
     * Matches FQL function signatures: a SYMBOL followed by a parameter list in  parentheses. The
     * list may contain zero or more parameters, separated by commas. This rule is called by the
     * {@link #primary_expr} rule.
     */
    	public final void function() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst function_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.makeASTRoot(currentAST, s_AST);
    			match(SYMBOL);
    			match(LPARENS);
    			{
    			switch ( LA(1)) {
    			case BOOL_FALSE:
    			case BOOL_TRUE:
    			case CASE:
    			case CAST:
    			case DEC_LITERAL:
    			case FROM:
    			case NOT:
    			case NULL:
    			case SELECT:
    			case LPARENS:
    			case STRING:
    			case MINUS:
    			case SYMBOL:
    			case NUM_LITERAL:
    			case LONG_LITERAL:
    			case SUBST:
    			case POSITIONAL:
    			{
    				expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				{
    				_loop55:
    				do {
    					if ((LA(1)==COMMA)) {
    						match(COMMA);
    						expr();
    						astFactory.addASTChild(currentAST, returnAST);
    					}
    					else {
    						break _loop55;
    					}

    				} while (true);
    				}
    				break;
    			}
    			case RPARENS:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			match(RPARENS);
    			s_AST.setType(FUNCTION);
    			function_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_18);
    		}
    		returnAST = function_AST;
    	}

    /** Matches a ternary expression which uses the CASE WHEN construct in its ternary form. */
    	public final void ternary() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst ternary_AST = null;
    		Token  w = null;
    		FQLAst w_AST = null;

    		try {      // for error handling
    			match(CASE);
    			w = LT(1);
    			w_AST = (FQLAst)astFactory.create(w);
    			astFactory.makeASTRoot(currentAST, w_AST);
    			match(WHEN);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			match(THEN);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			match(ELSE);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			match(END);
    			w_AST.setType(TERNARY);
    			ternary_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = ternary_AST;
    	}

    /**
     * Matches a qualified or unqualified property name, with an optional {@link #subscript}. This
     * rule is called by the {@link #primary_expr} rule, but only after the {@link #function} rule is
     * invoked. This order is necessary to avoid ambiguity with the latter rule, which looks for a
     * leading SYMBOL * token.
     */
    	public final void property() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst property_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.makeASTRoot(currentAST, s_AST);
    			match(SYMBOL);
    			s_AST.setType(PROPERTY);
    			{
    			switch ( LA(1)) {
    			case LBRACKET:
    			{
    				subscript();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case EOF:
    			case AND:
    			case AS:
    			case ASC:
    			case CROSS:
    			case DESC:
    			case ELSE:
    			case END:
    			case ESCAPE:
    			case FROM:
    			case FULL:
    			case GROUP:
    			case HAVING:
    			case IN:
    			case INNER:
    			case IS:
    			case JOIN:
    			case LEFT:
    			case OR:
    			case ORDER:
    			case OUTER:
    			case RIGHT:
    			case SINGLE:
    			case THEN:
    			case WHERE:
    			case EQUALS:
    			case NOT_EQ:
    			case COMMA:
    			case RPARENS:
    			case GT:
    			case LT:
    			case GTE:
    			case LTE:
    			case LIKE:
    			case CONCAT:
    			case PLUS:
    			case MINUS:
    			case MULTIPLY:
    			case DIVIDE:
    			case SYMBOL:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			property_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_19);
    		}
    		returnAST = property_AST;
    	}

    /**
     * Matches a subexpression enclosed in parentheses. Called by {@link #primary_expr} rule;
     * recursively calls {@link #expr} rule.
     */
    	public final void parentheses() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst parentheses_AST = null;

    		try {      // for error handling
    			FQLAst tmp71_AST = null;
    			tmp71_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp71_AST);
    			match(LPARENS);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			match(RPARENS);
    			parentheses_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = parentheses_AST;
    	}

    /**
     * Matches FQL aggregate signatures: a SYMBOL followed by an expression in parentheses. The expression is
     * a column or '*' literal. Uses 'overload' the symbol as FUNCTION because the syntax is identical.
     * This rule is called by the {@link #select_expr} rule.
     */
    	public final void aggregate() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst aggregate_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.makeASTRoot(currentAST, s_AST);
    			match(SYMBOL);
    			match(LPARENS);
    			{
    			switch ( LA(1)) {
    			case SYMBOL:
    			{
    				property();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case MULTIPLY:
    			{
    				FQLAst tmp74_AST = null;
    				tmp74_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp74_AST);
    				match(MULTIPLY);
    				break;
    			}
    			case RPARENS:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			match(RPARENS);
    			s_AST.setType(FUNCTION);
    			aggregate_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_20);
    		}
    		returnAST = aggregate_AST;
    	}

    /**
     * Matches an alias for a data model object, which is simply a SYMBOL, optionally followed by a
     * property. This rule is called by the {@link #primary_expr} rule, but only after the
     * {@link #function} rule is invoked. This order is necessary to avoid ambiguity with the latter
     * rule, which looks for a leading SYMBOL token.
     */
    	public final void alias() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst alias_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.makeASTRoot(currentAST, s_AST);
    			match(SYMBOL);
    			s_AST.setType(ALIAS);
    			alias_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_21);
    		}
    		returnAST = alias_AST;
    	}

    /** Matches a {@link #property} subscript, for array-type properties. */
    	public final void subscript() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst subscript_AST = null;
    		Token  n = null;
    		FQLAst n_AST = null;

    		try {      // for error handling
    			FQLAst tmp76_AST = null;
    			tmp76_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp76_AST);
    			match(LBRACKET);
    			{
    			switch ( LA(1)) {
    			case NUM_LITERAL:
    			{
    				n = LT(1);
    				n_AST = (FQLAst)astFactory.create(n);
    				astFactory.addASTChild(currentAST, n_AST);
    				match(NUM_LITERAL);
    				break;
    			}
    			case POSITIONAL:
    			{
    				positional_param();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case SUBST:
    			{
    				substitution();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			match(RBRACKET);
    			subscript_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_19);
    		}
    		returnAST = subscript_AST;
    	}

    /**
     * Matches and pre-processes a positional parameter.
     * <p>
     * The positional parameters (Ex: {@code ?8}) are matched and then annotated with {@code index}
     * annotation which represent its index/order.
     */
    	public final void positional_param() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst positional_param_AST = null;
    		Token  pp = null;
    		FQLAst pp_AST = null;

    		try {      // for error handling
    			pp = LT(1);
    			pp_AST = (FQLAst)astFactory.create(pp);
    			astFactory.addASTChild(currentAST, pp_AST);
    			match(POSITIONAL);
    			pp_AST.putAnnotation("index", Long.parseLong(pp_AST.getText().substring(1)));
    			positional_param_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_22);
    		}
    		returnAST = positional_param_AST;
    	}

    /**
     * Matches a query substitution parameter placeholder. The "index" annotation is written to this
     * node; its value is the index of this placeholder among all such placeholders encountered in a
     * left to right traversal of the where clause.
     */
    	public final void substitution() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst substitution_AST = null;
    		Token  s = null;
    		FQLAst s_AST = null;

    		try {      // for error handling
    			s = LT(1);
    			s_AST = (FQLAst)astFactory.create(s);
    			astFactory.addASTChild(currentAST, s_AST);
    			match(SUBST);

    			// assign an index to this substitution parameter
    			s_AST.putAnnotation("index", Long.valueOf(nextSubstitutionIndex++));

    			substitution_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_22);
    		}
    		returnAST = substitution_AST;
    	}

    /**
     * Matches an as phrase, which is an optional assignment of an alias to a DMO at the end of a from
     * phrase. Called by {@link #from_expr} rule. This portion of the phrase is optional if no other
     * part of the subselect phrase references an alias for the DMO.
     */
    	public final void as_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst as_expr_AST = null;

    		try {      // for error handling
    			{
    			switch ( LA(1)) {
    			case AS:
    			{
    				match(AS);
    				break;
    			}
    			case SYMBOL:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			alias();
    			astFactory.addASTChild(currentAST, returnAST);
    			as_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_21);
    		}
    		returnAST = as_expr_AST;
    	}

    /**
     * Matches a join phrase embedded within a where clause as part of a subselect statement. Called
     * by {@link #from_expr} rule.
     */
    	public final void join_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst join_expr_AST = null;

    		try {      // for error handling
    			{
    			switch ( LA(1)) {
    			case FULL:
    			case LEFT:
    			case OUTER:
    			case RIGHT:
    			{
    				{
    				{
    				switch ( LA(1)) {
    				case LEFT:
    				{
    					FQLAst tmp79_AST = null;
    					tmp79_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp79_AST);
    					match(LEFT);
    					break;
    				}
    				case RIGHT:
    				{
    					FQLAst tmp80_AST = null;
    					tmp80_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp80_AST);
    					match(RIGHT);
    					break;
    				}
    				case FULL:
    				{
    					FQLAst tmp81_AST = null;
    					tmp81_AST = (FQLAst)astFactory.create(LT(1));
    					astFactory.addASTChild(currentAST, tmp81_AST);
    					match(FULL);
    					break;
    				}
    				case OUTER:
    				{
    					break;
    				}
    				default:
    				{
    					throw new NoViableAltException(LT(1), getFilename());
    				}
    				}
    				}
    				FQLAst tmp82_AST = null;
    				tmp82_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp82_AST);
    				match(OUTER);
    				}
    				break;
    			}
    			case INNER:
    			{
    				FQLAst tmp83_AST = null;
    				tmp83_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp83_AST);
    				match(INNER);
    				break;
    			}
    			case CROSS:
    			{
    				FQLAst tmp84_AST = null;
    				tmp84_AST = (FQLAst)astFactory.create(LT(1));
    				astFactory.addASTChild(currentAST, tmp84_AST);
    				match(CROSS);
    				break;
    			}
    			case JOIN:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			FQLAst tmp85_AST = null;
    			tmp85_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp85_AST);
    			match(JOIN);
    			dmo();
    			astFactory.addASTChild(currentAST, returnAST);
    			{
    			switch ( LA(1)) {
    			case AS:
    			case SYMBOL:
    			{
    				as_expr();
    				astFactory.addASTChild(currentAST, returnAST);
    				break;
    			}
    			case ON:
    			{
    				break;
    			}
    			default:
    			{
    				throw new NoViableAltException(LT(1), getFilename());
    			}
    			}
    			}
    			on_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			join_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = join_expr_AST;
    	}

    /** Special JOIN syntax between two OE tables ON a common property. */
    	public final void join_extent() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst join_extent_AST = null;
    		Token  j = null;
    		FQLAst j_AST = null;

    		try {      // for error handling
    			j = LT(1);
    			j_AST = (FQLAst)astFactory.create(j);
    			astFactory.makeASTRoot(currentAST, j_AST);
    			match(JOIN);
    			j_AST.putAnnotation("composite-join", true);
    			property();
    			astFactory.addASTChild(currentAST, returnAST);
    			as_expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			join_extent_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = join_extent_AST;
    	}

    /** Matches an {@code ON} condition (logical expression) used for JOIN-ing the tables. */
    	public final void on_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst on_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp86_AST = null;
    			tmp86_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp86_AST);
    			match(ON);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			on_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = on_expr_AST;
    	}

    /** Matches the property assign in an UPDATE statement.  WARNING: no alias is allowed here. */
    	public final void update_field() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst update_field_AST = null;

    		try {      // for error handling
    			property();
    			astFactory.addASTChild(currentAST, returnAST);
    			FQLAst tmp87_AST = null;
    			tmp87_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp87_AST);
    			match(EQUALS);
    			expression();
    			astFactory.addASTChild(currentAST, returnAST);
    			update_field_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_15);
    		}
    		returnAST = update_field_AST;
    	}

    /** Matches a HAVING clause. */
    	public final void having_expr() throws RecognitionException, TokenStreamException {

    		returnAST = null;
    		ASTPair currentAST = new ASTPair();
    		FQLAst having_expr_AST = null;

    		try {      // for error handling
    			FQLAst tmp88_AST = null;
    			tmp88_AST = (FQLAst)astFactory.create(LT(1));
    			astFactory.makeASTRoot(currentAST, tmp88_AST);
    			match(HAVING);
    			expr();
    			astFactory.addASTChild(currentAST, returnAST);
    			having_expr_AST = (FQLAst)currentAST.root;
    		}
    		catch (RecognitionException ex) {
    			reportError(ex);
    			recover(ex,_tokenSet_3);
    		}
    		returnAST = having_expr_AST;
    	}

    	public static final String[] _tokenNames = {
    		"<0>",
    		"EOF",
    		"<2>",
    		"NULL_TREE_LOOKAHEAD",
    		"ALIAS",
    		"AND",
    		"AS",
    		"ASC",
    		"BOOL_FALSE",
    		"BOOL_TRUE",
    		"BY",
    		"CASE",
    		"CAST",
    		"CROSS",
    		"DEC_LITERAL",
    		"DELETE",
    		"DESC",
    		"DMO",
    		"DOT",
    		"ELSE",
    		"END",
    		"ESCAPE",
    		"FROM",
    		"FULL",
    		"FUNCTION",
    		"GROUP",
    		"HAVING",
    		"IN",
    		"INDEX",
    		"INNER",
    		"INSERT",
    		"INTO",
    		"IS",
    		"IS_NULL",
    		"JOIN",
    		"LEFT",
    		"NOT_NULL",
    		"NOT",
    		"NULL",
    		"ON",
    		"OR",
    		"ORDER",
    		"OUTER",
    		"PROPERTY",
    		"RIGHT",
    		"SELECT",
    		"SET",
    		"SINGLE",
    		"SUBSCRIPT",
    		"SUBSELECT",
    		"TERNARY",
    		"THEN",
    		"UN_MINUS",
    		"UPDATE",
    		"VALUES",
    		"WHEN",
    		"WHERE",
    		"INSERT_STMT",
    		"DELETE_STMT",
    		"SELECT_STMT",
    		"UPDATE_STMT",
    		"EQUALS",
    		"NOT_EQ",
    		"LPARENS",
    		"COMMA",
    		"RPARENS",
    		"GT",
    		"LT",
    		"GTE",
    		"LTE",
    		"LIKE",
    		"STRING",
    		"CONCAT",
    		"PLUS",
    		"MINUS",
    		"MULTIPLY",
    		"DIVIDE",
    		"SYMBOL",
    		"LBRACKET",
    		"NUM_LITERAL",
    		"RBRACKET",
    		"LONG_LITERAL",
    		"SUBST",
    		"POSITIONAL",
    		"WS",
    		"VALID_1ST_IDENT",
    		"VALID_SYM_CHAR",
    		"LETTER",
    		"DIGIT",
    		"SYM_CHAR"
    	};

    	protected void buildTokenTypeASTClassMap() {
    		tokenTypeToASTClassMap=null;
    	};

    	private static final long[] mk_tokenSet_0() {
    		long[] data = { 2L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
    	private static final long[] mk_tokenSet_1() {
    		long[] data = { -9223336440161608960L, 959616L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
    	private static final long[] mk_tokenSet_2() {
    		long[] data = { -2195303138775696414L, 983039L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
    	private static final long[] mk_tokenSet_3() {
    		long[] data = { 6992004504366948578L, 8063L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
    	private static final long[] mk_tokenSet_4() {
    		long[] data = { -2231331935794659358L, 966655L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
    	private static final long[] mk_tokenSet_5() {
    		long[] data = { -2195302589019881502L, 983039L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
    	private static final long[] mk_tokenSet_6() {
    		long[] data = { -2213282215478353694L, 16255L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
    	private static final long[] mk_tokenSet_7() {
    		long[] data = { 18014398509481984L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_7 = new BitSet(mk_tokenSet_7());
    	private static final long[] mk_tokenSet_8() {
    		long[] data = { 72057594037927938L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_8 = new BitSet(mk_tokenSet_8());
    	private static final long[] mk_tokenSet_9() {
    		long[] data = { 6992004504366948578L, 16255L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_9 = new BitSet(mk_tokenSet_9());
    	private static final long[] mk_tokenSet_10() {
    		long[] data = { 22042317430784L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_10 = new BitSet(mk_tokenSet_10());
    	private static final long[] mk_tokenSet_11() {
    		long[] data = { 566935683136L, 8192L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_11 = new BitSet(mk_tokenSet_11());
    	private static final long[] mk_tokenSet_12() {
    		long[] data = { -9223336440161608960L, 959618L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_12 = new BitSet(mk_tokenSet_12());
    	private static final long[] mk_tokenSet_13() {
    		long[] data = { 274877924096L, 950400L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_13 = new BitSet(mk_tokenSet_13());
    	private static final long[] mk_tokenSet_14() {
    		long[] data = { 4194304L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_14 = new BitSet(mk_tokenSet_14());
    	private static final long[] mk_tokenSet_15() {
    		long[] data = { 72057594037927938L, 1L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_15 = new BitSet(mk_tokenSet_15());
    	private static final long[] mk_tokenSet_16() {
    		long[] data = { 6992004779244855522L, 8063L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_16 = new BitSet(mk_tokenSet_16());
    	private static final long[] mk_tokenSet_17() {
    		long[] data = { 6992004504366948578L, 24447L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_17 = new BitSet(mk_tokenSet_17());
    	private static final long[] mk_tokenSet_18() {
    		long[] data = { 6992004504371142882L, 8063L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_18 = new BitSet(mk_tokenSet_18());
    	private static final long[] mk_tokenSet_19() {
    		long[] data = { 6992004504371142882L, 16255L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_19 = new BitSet(mk_tokenSet_19());
    	private static final long[] mk_tokenSet_20() {
    		long[] data = { 4194304L, 1L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_20 = new BitSet(mk_tokenSet_20());
    	private static final long[] mk_tokenSet_21() {
    		long[] data = { 6992005054122762466L, 8063L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_21 = new BitSet(mk_tokenSet_21());
    	private static final long[] mk_tokenSet_22() {
    		long[] data = { 6992004504371142882L, 73599L, 0L, 0L};
    		return data;
    	}
    	public static final BitSet _tokenSet_22 = new BitSet(mk_tokenSet_22());

    	}