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());
	
	}