Skip to content
Snippets Groups Projects
Select Git revision
  • cc2462d6e59d699387a367c282090ee5c088cb72
  • master default protected
  • ia2
  • adql2.1-ia2
  • private_rows
5 results

MaxRecController.java

Blame
  • ADQLParser.java 175.32 KiB
    /* ADQLParser.java */
    /* Generated By:JavaCC: Do not edit this line. ADQLParser.java */
    package adql.parser;
    
    import java.util.Stack;
    import java.util.Vector;
    import java.util.ArrayList;
    import java.util.Collection;
    
    import java.io.FileReader;
    import java.io.IOException;
    
    import adql.db.exception.UnresolvedIdentifiersException;
    
    import adql.parser.IdentifierItems.IdentifierItem;
    
    import adql.parser.ADQLQueryFactory.JoinType;
    
    import adql.query.*;
    import adql.query.from.*;
    import adql.query.constraint.*;
    
    import adql.query.operand.*;
    
    import adql.query.operand.function.*;
    
    import adql.query.operand.function.geometry.*;
    import adql.query.operand.function.geometry.GeometryFunction.GeometryValue;
    
    import adql.translator.PostgreSQLTranslator;
    import adql.translator.TranslationException;
    
    /**
    * Parses an ADQL query thanks to the {@link ADQLParser#Query()} function.
    * 
    * <p>
    *   This parser is able, thanks to a {@link QueryChecker} object, to check each
    *   {@link ADQLQuery} just after its generation. It could be used to check the
    *   consistency between the ADQL query to parse and the "database" on which the
    *   query must be executed. By default, there is no {@link QueryChecker}. Thus
    *   you must extend {@link QueryChecker} to check semantically all generated
    *   ADQLQuery objects.
    * </p>
    * 
    * <p>
    *   To create an object representation of the given ADQL query, this parser uses
    *   a {@link ADQLQueryFactory} object. So if you want customize some object
    *   (ie. CONTAINS) of this representation you just have to extend the
    *   corresponding default object (ie. ContainsFunction) and to extend the
    *   corresponding function of {@link ADQLQueryFactory}
    *   (ie. createContains(...)).
    * </p>
    *
    * <p>Here are the key functions to use:</p>
    * <ul>
    * 	<li>{@link #parseQuery(java.lang.String)} (or any of its alternatives)
    * 		to parse an input ADQL query String and get its corresponding ADQL tree
    *   </li>
    *   <li>{@link #tryQuickFix(java.lang.String)} to try fixing the most common
    * 		issues with ADQL queries (e.g. Unicode confusable characters,
    * 		unescaped ADQL identifiers, SQL reserved keywords, ...)</li>
    * </ul>
    * 
    * <p><b><u>WARNING:</u>
    *   To modify this class it's strongly encouraged to modify the .jj file in the
    *   section between <i>PARSER_BEGIN</i> and <i>PARSER_END</i> and to re-compile
    *   it with JavaCC.
    * </b></p>
    *
    * @see QueryChecker
    * @see ADQLQueryFactory
    *
    * @author Gr&eacute;gory Mantelet (CDS;ARI)
    * @version 1.5-2 (10/2020)
    */
    public class ADQLParser implements ADQLParserConstants {
    
            /** Tools to build the object representation of the ADQL query. */
            private ADQLQueryFactory queryFactory = new ADQLQueryFactory();
    
            /** The stack of queries (because there may be some sub-queries). */
            private Stack<ADQLQuery> stackQuery = new Stack<ADQLQuery>();
    
            /** The object representation of the ADQL query to parse.
    	 * (ONLY USED DURING THE PARSING, else it is always <i>null</i>). */
            private ADQLQuery query = null;
    
            /** Checks each {@link ADQLQuery} (sub-query or not) just after their
    	 * generation. */
            private QueryChecker queryChecker = null;
    
            /** The first token of a table/column name. This token is extracted by
    	 * {@link #Identifier()}. */
            private Token currentIdentifierToken = null;
    
            /**
    	* Builds an ADQL parser without a query to parse.
    	*/
            public ADQLParser(){
                    this(new java.io.ByteArrayInputStream("".getBytes()));
                    setDebug(false);
            }
    
            /**
    	* Builds an ADQL parser without a query to parse but with a
    	* {@link QueryChecker} and a {@link ADQLQueryFactory}.
    	*
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	* @param factory	The object to use to build an object representation of
    	*               	the given ADQL query.
    	*/
            public ADQLParser(QueryChecker checker, ADQLQueryFactory factory) {
                    this();
    
                    queryChecker = checker;
    
                    if (factory != null)
                            queryFactory = factory;
            }
    
            /**
    	* Builds an ADQL parser without a query to parse but with a
    	* {@link QueryChecker}.
    	*
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	*/
            public ADQLParser(QueryChecker checker) {
                    this(checker, null);
            }
    
            /**
    	* Builds an ADQL parser without a query to parse but with a
    	* {@link ADQLQueryFactory}.
    	*
    	* @param factory	The object to use to build an object representation of
    	*               	the given ADQL query.
    	*/
            public ADQLParser(ADQLQueryFactory factory) {
                    this((QueryChecker)null, factory);
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	* @param factory	The object to use to build an object representation of
    	*               	the given ADQL query.
    	*/
            public ADQLParser(java.io.InputStream stream, QueryChecker checker, ADQLQueryFactory factory) {
                    this(stream);
                    setDebug(false);
    
                    setDebug(false);
    
                    queryChecker = checker;
    
                    if (factory != null)
                            queryFactory = factory;
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	*/
            public ADQLParser(java.io.InputStream stream, QueryChecker checker) {
                    this(stream, checker, null);
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param factory	The object to use to build an object representation of
    	*               	the given ADQL query.
    	*/
            public ADQLParser(java.io.InputStream stream, ADQLQueryFactory factory) {
                    this(stream, (QueryChecker)null, factory);
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param encoding	The supplied encoding.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	* @param factory	The object to use to build an object representation
    	*               	of the given ADQL query.
    	*/
            public ADQLParser(java.io.InputStream stream, String encoding, QueryChecker checker, ADQLQueryFactory factory) {
                    this(stream, encoding);
                    setDebug(false);
    
                    queryChecker = checker;
    
                    if (factory != null)
                            queryFactory = factory;
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param encoding	The supplied encoding.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	*/
            public ADQLParser(java.io.InputStream stream, String encoding, QueryChecker checker) {
                    this(stream, encoding, checker, null);
            }
    
            /**
    	* Builds a parser with a stream containing the query to parse.
    	*
    	* @param stream		The stream in which the ADQL query to parse is given.
    	* @param encoding	The supplied encoding.
    	* @param factory	The object to use to build an object representation
    	*               	of the given ADQL query.
    	*/
            public ADQLParser(java.io.InputStream stream, String encoding, ADQLQueryFactory factory) {
                    this(stream, encoding, null, factory);
            }
    
            /**
    	* Builds a parser with a reader containing the query to parse.
    	*
    	* @param reader		The reader in which the ADQL query to parse is given.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	* @param factory	The object to use to build an object representation
    	*               	of the given ADQL query.
    	*/
            public ADQLParser(java.io.Reader reader, QueryChecker checker, ADQLQueryFactory factory) {
                    this(reader);
                    setDebug(false);
    
                    setDebug(false);
    
                    queryChecker = checker;
    
                    if (factory != null)
                            queryFactory = factory;
            }
    
            /**
    	* Builds a parser with a reader containing the query to parse.
    	*
    	* @param reader		The reader in which the ADQL query to parse is given.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	*/
            public ADQLParser(java.io.Reader reader, QueryChecker checker) {
                    this(reader, checker, null);
            }
    
            /**
    	* Builds a parser with a reader containing the query to parse.
    	*
    	* @param reader		The reader in which the ADQL query to parse is given.
    	* @param factory	The object to use to build an object representation
    	*               	of the given ADQL query.
    	*/
            public ADQLParser(java.io.Reader reader, ADQLQueryFactory factory) {
                    this(reader, null, factory);
            }
    
            /**
    	* Builds a parser with another token manager.
    	*
    	* @param tm			The manager which associates a token to a numeric code.
    	* @param checker	The object to use to check each {@link ADQLQuery }.
    	* @param factory	The object to use to build an object representation
    	*               	of the given ADQL query.
    	*/
            public ADQLParser(ADQLParserTokenManager tm, QueryChecker checker, ADQLQueryFactory factory) {
                    this(tm);
                    setDebug(false);
    
                    setDebug(false);
    
                    queryChecker = checker;
    
                    if (factory != null)
                            queryFactory = factory;
            }
    
            /**
    	* Builds a parser with another token manager.
    	*
    	* @param tm			The manager which associates a token to a numeric code.
    	* @param checker	The object to use to check each {@link ADQLQuery}.
    	*/
            public ADQLParser(ADQLParserTokenManager tm, QueryChecker checker) {
                    this(tm, checker, null);
            }
    
            /**
    	* Builds a parser with another token manager.
    	*
    	* @param tm			The manager which associates a token to a numeric code.
    	* @param factory	The object to use to build an object representation of
    	*               	the given ADQL query.
    	*/
            public ADQLParser(ADQLParserTokenManager tm, ADQLQueryFactory factory) {
                    this(tm, null, factory);
            }
    
            /* ADDITIONAL GETTERS & SETTERS */
    
            public final void setDebug(boolean debug){
                    if (debug) enable_tracing();
                    else       disable_tracing();
            }
    
            public final QueryChecker getQueryChecker(){
                    return queryChecker;
            }
    
            public final void setQueryChecker(QueryChecker checker){
                    queryChecker = checker;
            }
    
            public final ADQLQueryFactory getQueryFactory(){
                    return queryFactory;
            }
    
            public final void setQueryFactory(ADQLQueryFactory factory){
                    queryFactory = (factory!=null)?factory:(new ADQLQueryFactory());
            }
    
            /* EXCEPTION HELPER FUNCTION */
    
            private final ParseException generateParseException(Exception ex){
                    if (!(ex instanceof ParseException)){
                            ParseException pex = new ParseException("["+ex.getClass().getName()+"] "+ex.getMessage());
                            pex.setStackTrace(ex.getStackTrace());
                            return pex;
                    }else
                            return (ParseException)ex;
            }
    
            /* QUERY PARSING FUNCTIONS */
    
            /**
    	 * Tell whether the given string is a valid ADQL regular identifier.
    	 *
    	 * <p>
    	 * 	According to the ADQL-2.0's BNF, a regular identifier (i.e. not delimited
    	 * 	; not between double quotes) must be a letter followed by a letter, digit
    	 * 	or underscore. So, the following regular expression:
    	 * </p>
    	 * <pre>[a-zA-Z]+[a-zA-Z0-9_]*</pre>
    	 *
    	 * <p>This is what this function tests on the given string.</p>
    	 *
    	 * @param idCandidate	The string to test.
    	 *
    	 * @return	<code>true</code> if the given string is a valid regular
    	 *        	identifier,
    	 *        	<code>false</code> otherwise.
    	 *
    	 * @see #testRegularIdentifier(adql.parser.Token)
    	 *
    	 * @since 1.5
    	 */
            public final boolean isRegularIdentifier(final String idCandidate) {
                    return idCandidate.matches("[a-zA-Z]+[a-zA-Z0-9_]*");
            }
    
            /**
    	 * Test the given token as an ADQL's regular identifier.
    	 *
    	 * <p>
    	 * 	This function uses {@link #isRegularIdentifier(java.lang.String)} to
    	 * 	test the given token's image. If the test fails, a
    	 * 	{@link adql.parser.ParseException} is thrown.
    	 * </p>
    	 *
    	 * @param token	The token to test.
    	 *
    	 * @throws ParseException	If the given token is not a valid ADQL regular
    	 *                       	identifier.
    	 *
    	 * @see #isRegularIdentifier(java.lang.String)
    	 *
    	 * @since 1.5
    	 */
            public final void testRegularIdentifier(final Token token) throws ParseException {
                    if (!isRegularIdentifier(token.image))
                            throw new ParseException("Invalid ADQL regular identifier: \u005c""+token.image+"\u005c"! If it aims to be a column/table name/alias, you should write it between double quotes.", new TextPosition(token));
            }
    
            /**
    	* Parses the query given at the creation of this parser or in the
    	* <i>ReInit</i> functions.
    	*
    	* @return 	The object representation of the given ADQL query.
    	* 
    	* @throws ParseException	If there is at least one syntactic error.
    	*
    	* @see ADQLParser#Query()
    	*/
            public final ADQLQuery parseQuery() throws ParseException {
                    stackQuery.clear();
                    query = null;
                    try {
                            return Query();
                    }catch(TokenMgrError tme) {
                            throw new ParseException(tme);
                    }
            }
    
            /**
    	* Parses the query given in parameter.
    	*
    	* @param q	The ADQL query to parse.
    	* 
    	* @return	The object representation of the given ADQL query.
    	* 
    	* @throws ParseException	If there is at least one syntactic error.
    	*
    	* @see ADQLParser#ReInit(java.io.InputStream)
    	* @see ADQLParser#setDebug(boolean)
    	* @see ADQLParser#Query()
    	*/
            public final ADQLQuery parseQuery(String q) throws ParseException {
                    stackQuery.clear();
                    query = null;
                    ReInit(new java.io.ByteArrayInputStream(q.getBytes()));
                    try {
                            return Query();
                    }catch(TokenMgrError tme) {
                            throw new ParseException(tme);
                    }
            }
    
            /**
    	* Parses the query contained in the stream given in parameter.
    	*
    	* @param stream		The stream which contains the ADQL query to parse.
    	* 
    	* @return	The object representation of the given ADQL query.
    	* 
    	* @throws ParseException	If there is at least one syntactic error.
    	*
    	* @see ADQLParser#ReInit(java.io.InputStream)
    	* @see ADQLParser#setDebug(boolean)
    	* @see ADQLParser#Query()
    	*/
            public final ADQLQuery parseQuery(java.io.InputStream stream) throws ParseException {
                    stackQuery.clear();
                    query = null;
                    ReInit(stream);
                    try {
                            return Query();
                    }catch(TokenMgrError tme) {
                            throw new ParseException(tme);
                    }
            }
    
            /* CORRECTION SUGGESTION */
    
            /**
    	 * Try fixing tokens/terms of the input ADQL query.
    	 *
    	 * <p>
    	 * 	<b>This function does not try to fix syntactical or semantical errors.</b>
    	 *  It just try to fix the most common issues in ADQL queries, such as:
    	 * </p>
    	 * <ul>
    	 * 	<li>some Unicode characters confusable with ASCII characters (like a
    	 * 		space, a dash, ...) ; this function replace them by their ASCII
    	 * 		alternative,</li>
    	 * 	<li>any of the following are double quoted:
    	 * 		<ul>
    	 * 			<li>non regular ADQL identifiers
    	 * 				(e.g. <code>_RAJ2000</code>),</li>
    	 * 			<li>ADQL function names used as identifiers
    	 * 				(e.g. <code>distance</code>)</li>
    	 * 			<li>and SQL reserved keywords
    	 * 				(e.g. <code>public</code>).</li>
    	 * 		</ul>
    	 * 	</li>
    	 * </ul>
    	 *
    	 * <p><i><b>Note 1:</b>
    	 * 	The given stream is NOT closed by this function even if the EOF is
    	 * 	reached. It is the responsibility of the caller to close it.
    	 * </i></p>
    	 *
    	 * <p><i><b>Note 2:</b>
    	 * 	This function does not use any instance variable of this parser
    	 * 	(especially the InputStream or Reader provided at initialisation or
    	 * 	ReInit).
    	 * </i></p>
    	 *
    	 * @param input	Stream containing the input ADQL query to fix.
    	 *
    	 * @return	The suggested correction of the input ADQL query.
    	 *
    	 * @throws java.io.IOException	If there is any error while reading from the
    	 *                            	given input stream.
    	 * @throws ParseException	If any unrecognised character is encountered,
    	 *                       	or if anything else prevented the tokenization
    	 *                       	   of some characters/words/terms.
    	 *
    	 * @see #tryQuickFix(java.lang.String)
    	 *
    	 * @since 1.5
    	 */
            public final String tryQuickFix(final java.io.InputStream input) throws java.io.IOException, ParseException {
                    // Fetch everything into a single string:
                    StringBuffer buf = new StringBuffer();
                    byte[] cBuf = new byte[1024];
                    int nbChar;
                    while((nbChar = input.read(cBuf)) > -1){
                            buf.append(new String(cBuf, 0, nbChar));
                    }
    
                    // Convert the buffer into a String and now try to fix it:
                    return tryQuickFix(buf.toString());
            }
    
            /**
    	 * Try fixing tokens/terms of the given ADQL query.
    	 *
    	 * <p>
    	 * 	<b>This function does not try to fix syntactical or semantical errors.</b>
    	 *  It just try to fix the most common issues in ADQL queries, such as:
    	 * </p>
    	 * <ul>
    	 * 	<li>some Unicode characters confusable with ASCII characters (like a
    	 * 		space, a dash, ...) ; this function replace them by their ASCII
    	 * 		alternative,</li>
    	 * 	<li>any of the following are double quoted:
    	 * 		<ul>
    	 * 			<li>non regular ADQL identifiers
    	 * 				(e.g. <code>_RAJ2000</code>),</li>
    	 * 			<li>ADQL function names used as identifiers
    	 * 				(e.g. <code>distance</code>)</li>
    	 * 			<li>and SQL reserved keywords
    	 * 				(e.g. <code>public</code>).</li>
    	 * 		</ul>
    	 * 	</li>
    	 * </ul>
    	 *
    	 * <p><i><b>Note:</b>
    	 * 	This function does not use any instance variable of this parser
    	 * 	(especially the InputStream or Reader provided at initialisation or
    	 * 	ReInit).
    	 * </i></p>
    	 *
    	 * @param adqlQuery	The input ADQL query to fix.
    	 *
    	 * @return	The suggested correction of the given ADQL query.
    	 *
    	 * @throws ParseException	If any unrecognised character is encountered,
    	 *                       	or if anything else prevented the tokenization
    	 *                       	   of some characters/words/terms.
    	 *
    	 * @since 1.5
    	 */
            public String tryQuickFix(String adqlQuery) throws ParseException {
                    StringBuffer suggestedQuery = new StringBuffer();
    
                    // 1. Replace all Unicode confusable characters:
                    adqlQuery = replaceUnicodeConfusables(adqlQuery);
    
                    /* 1.bis. Normalise new lines and tabulations
    		 *        (to simplify the column counting): */
                    adqlQuery = adqlQuery.replaceAll("(\u005cr\u005cn|\u005cr|\u005cn)", System.getProperty("line.separator")).replaceAll("\u005ct", "    ");
    
                    // 2. Analyse the query token by token:
                    ADQLParserTokenManager parser = new ADQLParserTokenManager(new SimpleCharStream(new java.io.ByteArrayInputStream(adqlQuery.getBytes())));
    
                    final String[] lines = adqlQuery.split(System.getProperty("line.separator"));
    
                    try{
                            String suggestedToken;
                            int lastLine = 1, lastCol = 1;
    
                            Token token = null, nextToken = parser.getNextToken();
                            // for all tokens until the EOF or EOQ:
                            do{
                                    // get the next token:
                                    token = nextToken;
                                    nextToken = (isEnd(token) ? null : parser.getNextToken());
    
                                    // 3. Double quote any suspect token:
                                    if (mustEscape(token, nextToken)){
                                            suggestedToken = "\u005c"" + token.image + "\u005c"";
                                    }else
                                            suggestedToken = token.image;
    
                                    /* 4. Append all space characters (and comments) before the
    				 *    token: */
                                    /* same line, just get the space characters between the last
    				 * token and the one to append: */
                                    if (lastLine == token.beginLine){
                                            if (token.kind == ADQLParserConstants.EOF)
                                                    suggestedQuery.append(lines[lastLine - 1].substring(lastCol - 1));
                                            else
                                                    suggestedQuery.append(lines[lastLine - 1].substring(lastCol - 1, token.beginColumn - (isEnd(token) ? 0 : 1)));
                                            lastCol = token.endColumn + 1;
                                    }
                                    // not the same line...
                                    else{
                                        /* append all remaining space characters until the position
    				     * of the token to append: */
                                            do{
                                                    suggestedQuery.append(lines[lastLine - 1].substring(lastCol - 1)).append('\u005cn');
                                                    lastLine++;
                                                    lastCol = 1;
                                            }while(lastLine < token.beginLine);
                                            /* if there are still space characters before the token,
    					 * append them as well: */
                                            if (lastCol < token.beginColumn)
                                                    suggestedQuery.append(lines[lastLine - 1].substring(lastCol - 1, token.beginColumn - 1));
                                            // finally, set the correct column position:
                                            lastCol = token.endColumn + 1;
                                    }
    
                                    // 5. Append the suggested token:
                                    suggestedQuery.append(suggestedToken);
    
                            }while(!isEnd(token));
    
                    }catch(TokenMgrError err){
                        // wrap such errors and propagate them:
                            throw new ParseException(err);
                    }
    
                    return suggestedQuery.toString();
            }
    
            /**
    	 * All of the most common Unicode confusable characters and their
    	 * ASCII/UTF-8 alternative.
    	 *
    	 * <p>
    	 * 	Keys of this map represent the ASCII character while the values are the
    	 * 	regular expression for all possible Unicode alternatives.
    	 * </p>
    	 *
    	 * <p><i><b>Note:</b>
    	 * 	All of them have been listed using
    	 * 	<a href="https://unicode.org/cldr/utility/confusables.jsp">Unicode Utilities: Confusables</a>.
    	 * </i></p>
    	 *
    	 * @since 1.5
    	 */
            protected final static java.util.Map<String, String> REGEX_UNICODE_CONFUSABLES = new java.util.HashMap<String, String>(10);
            /** Regular expression matching all Unicode alternatives for <code>-</code>.
    	 * @since 1.5 */
            protected final static String REGEX_DASH         = "[-\u02d7\u06d4\u2010\u2011\u2012\u2013\u2043\u2212\u2796\u2cba\ufe58\u2014\u2015\u207b\u208b\u0096\u058a\ufe63\uff0d]";
            /** Regular expression matching all Unicode alternatives for <code>_</code>.
    	 * @since 1.5 */
            protected final static String REGEX_UNDERSCORE   = "[_\u07fa\ufe4d\ufe4e\ufe4f]";
            /** Regular expression matching all Unicode alternatives for <code>'</code>.
    	 * @since 1.5 */
            protected final static String REGEX_QUOTE        = "['`\u00b4\u02b9\u02bb\u02bc\u02bd\u02be\u02c8\u02ca\u02cb\u02f4\u0374\u0384\u055a\u055d\u05d9\u05f3\u07f4\u07f5\u144a\u16cc\u1fbd\u1fbf\u1fef\u1ffd\u1ffe\u2018\u2019\u201b\u2032\u2035\ua78c\uff07\uff40]";
            /** Regular expression matching all Unicode alternatives for <code>"</code>.
    	 * @since 1.5 */
            protected final static String REGEX_DOUBLE_QUOTE = "[\u02ba\u02dd\u02ee\u02f6\u05f2\u05f4\u1cd3\u201c\u201d\u201f\u2033\u2036\u3003\uff02]";
            /** Regular expression matching all Unicode alternatives for <code>.</code>.
    	 * @since 1.5 */
            protected final static String REGEX_STOP         = "[.\u0660\u06f0\u0701\u0702\u2024\ua4f8\ua60e]";
            /** Regular expression matching all Unicode alternatives for <code>+</code>.
    	 * @since 1.5 */
            protected final static String REGEX_PLUS         = "[+\u16ed\u2795]";
            /** Regular expression matching all Unicode alternatives for <code> </code>.
    	 * @since 1.5 */
            protected final static String REGEX_SPACE        = "[ \u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f]";
            /** Regular expression matching all Unicode alternatives for <code>&lt;</code>.
    	 * @since 1.5 */
            protected final static String REGEX_LESS_THAN    = "[<\u02c2\u1438\u16b2\u2039\u276e]";
            /** Regular expression matching all Unicode alternatives for <code>&gt;</code>.
    	 * @since 1.5 */
            protected final static String REGEX_GREATER_THAN = "[>\u02c3\u1433\u203a\u276f]";
            /** Regular expression matching all Unicode alternatives for <code>=</code>.
    	 * @since 1.5 */
            protected final static String REGEX_EQUAL        = "[=\u1400\u2e40\u30a0\ua4ff]";
            static {
                    REGEX_UNICODE_CONFUSABLES.put("-", REGEX_DASH);
                    REGEX_UNICODE_CONFUSABLES.put("_", REGEX_UNDERSCORE);
                    REGEX_UNICODE_CONFUSABLES.put("'", REGEX_QUOTE);
                    REGEX_UNICODE_CONFUSABLES.put("\u005c"", REGEX_DOUBLE_QUOTE);
                    REGEX_UNICODE_CONFUSABLES.put(".", REGEX_STOP);
                    REGEX_UNICODE_CONFUSABLES.put("+", REGEX_PLUS);
                    REGEX_UNICODE_CONFUSABLES.put(" ", REGEX_SPACE);
                    REGEX_UNICODE_CONFUSABLES.put("<", REGEX_LESS_THAN);
                    REGEX_UNICODE_CONFUSABLES.put(">", REGEX_GREATER_THAN);
                    REGEX_UNICODE_CONFUSABLES.put("=", REGEX_EQUAL);
            }
    
            /**
    	 * Replace all Unicode characters that can be confused with other ASCI/UTF-8
    	 * characters (e.g. different spaces, dashes, ...) in their ASCII version.
    	 *
    	 * @param adqlQuery	The ADQL query string in which Unicode confusable
    	 *                 	characters must be replaced.
    	 *
    	 * @return	The same query without the most common Unicode confusable
    	 *        	characters.
    	 *
    	 * @since 1.5
    	 */
            protected String replaceUnicodeConfusables(final String adqlQuery){
                    String newAdqlQuery = adqlQuery;
                    for(java.util.Map.Entry<String, String> confusable : REGEX_UNICODE_CONFUSABLES.entrySet())
                            newAdqlQuery = newAdqlQuery.replaceAll(confusable.getValue(), confusable.getKey());
                    return newAdqlQuery;
            }
    
            /**
    	 * Tell whether the given token represents the end of an ADQL query.
    	 *
    	 * @param token	Token to analyze.
    	 *
    	 * @return	<code>true</code> if the given token represents a query end,
    	 *        	<code>false</code> otherwise.
    	 *
    	 * @since 1.5
    	 */
            protected boolean isEnd(final Token token){
                    return token.kind == ADQLParserConstants.EOF || token.kind == ADQLParserConstants.EOQ;
            }
    
            /**
    	 * Tell whether the given token must be double quoted.
    	 *
    	 * <p>
    	 * 	This function considers all the following as terms to double quote:
    	 * </p>
    	 * <ul>
    	 * 	<li>SQL reserved keywords</li>,
    	 * 	<li>unrecognised regular identifiers (e.g. neither a delimited nor a
    	 * 		valid ADQL regular identifier)</li>
    	 * 	<li>and ADQL function name without a parameters list.</li>
    	 * </ul>
    	 *
    	 * @param token		The token to analyze.
    	 * @param nextToken	The following token. (useful to detect the start of a
    	 *                 	function's parameters list)
    	 *
    	 * @return	<code>true</code> if the given token must be double quoted,
    	 *        	<code>false</code> to keep it as provided.
    	 *
    	 * @since 1.5
    	 */
            protected boolean mustEscape(final Token token, final Token nextToken){
                    switch(token.kind){
                            case ADQLParserConstants.SQL_RESERVED_WORD:
                                    return true;
                            case ADQLParserConstants.REGULAR_IDENTIFIER_CANDIDATE:
                                    return !isRegularIdentifier(token.image);
                            default:
                                    return isFunctionName(token) && (nextToken == null || nextToken.kind != ADQLParserConstants.LEFT_PAR);
                    }
            }
    
            /**
    	 * Tell whether the given token matches to an ADQL function name.
    	 *
    	 * @param token	The token to analyze.
    	 *
    	 * @return	<code>true</code> if the given token is an ADQL function name,
    	 *        	<code>false</code> otherwise.
    	 *
    	 * @since 1.5
    	 */
            protected boolean isFunctionName(final Token token){
                    switch(token.kind){
                            case ADQLParserConstants.COUNT:
                            case ADQLParserConstants.EXISTS:
                            case ADQLParserConstants.AVG:
                            case ADQLParserConstants.MAX:
                            case ADQLParserConstants.MIN:
                            case ADQLParserConstants.SUM:
                            case ADQLParserConstants.BOX:
                            case ADQLParserConstants.CENTROID:
                            case ADQLParserConstants.CIRCLE:
                            case ADQLParserConstants.POINT:
                            case ADQLParserConstants.POLYGON:
                            case ADQLParserConstants.REGION:
                            case ADQLParserConstants.CONTAINS:
                            case ADQLParserConstants.INTERSECTS:
                            case ADQLParserConstants.AREA:
                            case ADQLParserConstants.COORD1:
                            case ADQLParserConstants.COORD2:
                            case ADQLParserConstants.COORDSYS:
                            case ADQLParserConstants.DISTANCE:
                            case ADQLParserConstants.ABS:
                            case ADQLParserConstants.CEILING:
                            case ADQLParserConstants.DEGREES:
                            case ADQLParserConstants.EXP:
                            case ADQLParserConstants.FLOOR:
                            case ADQLParserConstants.LOG:
                            case ADQLParserConstants.LOG10:
                            case ADQLParserConstants.MOD:
                            case ADQLParserConstants.PI:
                            case ADQLParserConstants.POWER:
                            case ADQLParserConstants.RADIANS:
                            case ADQLParserConstants.RAND:
                            case ADQLParserConstants.ROUND:
                            case ADQLParserConstants.SQRT:
                            case ADQLParserConstants.TRUNCATE:
                            case ADQLParserConstants.ACOS:
                            case ADQLParserConstants.ASIN:
                            case ADQLParserConstants.ATAN:
                            case ADQLParserConstants.ATAN2:
                            case ADQLParserConstants.COS:
                            case ADQLParserConstants.COT:
                            case ADQLParserConstants.SIN:
                            case ADQLParserConstants.TAN:
                            case ADQLParserConstants.USING:
                                    return true;
                            default:
                                    return false;
                    }
            }
    
            /* MAIN PROGRAM */
    
            /**
    	* Gets the specified ADQL query and parses the given ADQL query. The SQL
    	* translation is then printed if the syntax is correct.
    	* 
    	* <p>
    	*     <b>ONLY the syntax is checked: the query is NOT EXECUTED !</b>
    	* </p>
    	*
    	* @param args
    	
    	* @throws Exception
    	*/
            public static final void main(String[] args) throws Exception {
                    final String USAGE = "Usage:\u005cn    adqlParser.jar [-d] [-v] [-e] [-a|-s] [-f] [<FILE>|<URL>]\u005cn\u005cnNOTE: If no file or URL is given, the ADQL query is expected in the standard\u005cn      input. This query must end with a ';' or <Ctrl+D>!\u005cn\u005cnParameters:\u005cn    -v or --verbose : Print the main steps of the parsing\u005cn    -d or --debug   : Print stack traces when a grave error occurs\u005cn    -e or --explain : Explain the ADQL parsing (or Expand the parsing tree)\u005cn    -a or --adql    : Display the understood ADQL query\u005cn    -s or --sql     : Ask the SQL translation of the given ADQL query\u005cn                      (SQL compatible with PostgreSQL)\u005cn    -f or --try-fix : Try fixing the most common ADQL query issues before\u005cn                      attempting to parse the query.\u005cn\u005cnReturn:\u005cn    By default: nothing if the query is correct. Otherwise a message explaining\u005cn                why the query is not correct is displayed.\u005cn    With the -s option, the SQL translation of the given ADQL query will be\u005cn    returned.\u005cn    With the -a option, the ADQL query is returned as it has been understood.\u005cn\u005cnExit status:\u005cn    0  OK !\u005cn    1  Parameter error (missing or incorrect parameter)\u005cn    2  File error (incorrect file/url, reading error, ...)\u005cn    3  Parsing error (syntactic or semantic error)\u005cn    4  Translation error (a problem has occurred during the translation of the\u005cn       given ADQL query in SQL).";
    
                    ADQLParser parser;
    
                    final String urlRegex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
    
                    String file = null, metaFile = null;
                    short mode = -1;
                    boolean verbose=false, debug=false, explain=false, tryFix=false;
    
                    // Parameters reading:
                    for(int i=0; i<args.length; i++){
                            if (args[i].equalsIgnoreCase("-d") || args[i].equalsIgnoreCase("--debug"))
                                    debug = true;
                            else if (args[i].equalsIgnoreCase("-v") || args[i].equalsIgnoreCase("--verbose"))
                                    verbose = true;
                            else if (args[i].equalsIgnoreCase("-e") || args[i].equalsIgnoreCase("--explain"))
                                    explain = true;
                            else if (args[i].equalsIgnoreCase("-a") || args[i].equalsIgnoreCase("--adql")){
                                    if (mode != -1){
                                            System.err.println("((!)) Too much parameter: you must choose between -s, -c, -a or nothing ((!))\u005cn"+USAGE);
                                            System.exit(1);
                                    }else
                                            mode = 1;
                            }else if (args[i].equalsIgnoreCase("-s") || args[i].equalsIgnoreCase("--sql")){
                                    if (mode != -1){
                                            System.err.println("((!)) Too much parameter: you must choose between -s, -c, -a or nothing ((!))\u005cn"+USAGE);
                                            System.exit(1);
                                    }else
                                            mode = 2;
                            }else if (args[i].equalsIgnoreCase("-f") || args[i].equalsIgnoreCase("--try-fix"))
                                    tryFix = true;
                            else if (args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("--help")){
                                    System.out.println(USAGE);
                                    System.exit(0);
                            }else if (args[i].startsWith("-")){
                                    System.err.println("((!)) Unknown parameter: \u005c""+args[i]+"\u005c" ((!))\u005cn"+USAGE);
                                    System.exit(1);
                            }else
                                    file = args[i].trim();
                    }
    
                    try{
    
                            // Try fixing the query, if asked:
                            if (tryFix) {
                                    if (verbose)
                                            System.out.println("((i)) Trying to automatically fix the query...");
    
                                    String query;
                                    java.io.InputStream in = null;
                                    try {
                                            // get the input stream...
                                            if (file == null || file.length() == 0)
                                                    in = System.in;
                                            else if (file.matches(urlRegex))
                                                    in = (new java.net.URL(file)).openStream();
                                            else
                                                    in = new java.io.FileInputStream(file);
    
                                            // ...and try fixing the query:
                                            query = (new ADQLParser()).tryQuickFix(in);
                                    } finally {
                                            // close the stream (if opened):
                                            if (in != null)
                                                    in.close();
                                            in = null;
                                    }
    
                                    if (verbose)
                                            System.out.println("((i)) SUGGESTED QUERY:\u005cn" + query);
    
                                    // Initialise the parser with this fixed query:
                                    parser = new ADQLParser(new java.io.ByteArrayInputStream(query.getBytes()));
                            }
                            // Otherwise, take the query as provided:
                            else {
                                    // Initialise the parser with the specified input:
                                    if (file == null || file.length() == 0)
                                            parser = new ADQLParser(System.in);
                                    else if (file.matches(urlRegex))
                                            parser = new ADQLParser((new java.net.URL(file)).openStream());
                                    else
                                            parser = new ADQLParser(new java.io.FileInputStream(file));
                            }
    
                            // Enable/Disable the debugging in function of the parameters:
                            parser.setDebug(explain);
    
                            // Query parsing:
                            try{
                                    if (verbose)    System.out.print("((i)) Parsing ADQL query...");
                                    ADQLQuery q = parser.parseQuery();
                                    if (verbose)    System.out.println("((i)) CORRECT ADQL QUERY ((i))");
                                    if (mode==2){
                                            PostgreSQLTranslator translator = new PostgreSQLTranslator();
                                            if (verbose)    System.out.print("((i)) Translating in SQL...");
                                            String sql = translator.translate(q);
                                            if (verbose)    System.out.println("ok");
                                            System.out.println(sql);
                                    }else if (mode==1){
                                            System.out.println(q.toADQL());
                                    }
                            }catch(UnresolvedIdentifiersException uie){
                                    System.err.println("((X)) "+uie.getNbErrors()+" unresolved identifiers:");
                                    for(ParseException pe : uie)
                                            System.err.println("\u005ct - at "+pe.getPosition()+": "+uie.getMessage());
                                    if (debug)              uie.printStackTrace(System.err);
                                    System.exit(3);
                            }catch(ParseException pe){
                                    System.err.println("((X)) Syntax error: "+pe.getMessage()+" ((X))");
                                    if (debug)              pe.printStackTrace(System.err);
                                    System.exit(3);
                            }catch(TranslationException te){
                                    if (verbose)    System.out.println("error");
                                    System.err.println("((X)) Translation error: "+te.getMessage()+" ((X))");
                                    if (debug)              te.printStackTrace(System.err);
                                    System.exit(4);
                            }
    
                    }catch(IOException ioe){
                            System.err.println("\u005cn((X)) Error while reading the file \u005c""+file+"\u005c": "+ioe.getMessage()+" ((X))");
                            if (debug)              ioe.printStackTrace(System.err);
                            System.exit(2);
                    }
    
        }
    
    /* ########## */
                                                            /* # SYNTAX # */
                                                            /* ########## */
    
    /* ******************* */
    /* GENERAL ADQL SYNTAX */
    /* ******************* */
    /**
    * Parses the ADQL query given at the parser creation or in the {@link ADQLParser#ReInit(java.io.InputStream)}
    * or in the <i>parseQuery</i> functions.
    *
    * @return					The object representation of the query.
    * @throws ParseException	If the query syntax is incorrect.
    */
      final public ADQLQuery Query() throws ParseException {
        trace_call("Query");
        try {ADQLQuery q = null;
          q = QueryExpression();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case 0:{
            jj_consume_token(0);
            break;
            }
          case EOQ:{
            jj_consume_token(EOQ);
            break;
            }
          default:
            jj_la1[0] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    // check the query:
                    if (queryChecker != null)
                            queryChecker.check(q);
    
                    {if ("" != null) return q;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Query");
        }
      }
    
      final public ADQLQuery QueryExpression() throws ParseException {
        trace_call("QueryExpression");
        try {TextPosition endPos = null;
    try{
                            // create the query:
                            query = queryFactory.createQuery();
                            stackQuery.push(query);
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
          Select();
          From();
    endPos = query.getFrom().getPosition();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case WHERE:{
            Where();
    endPos = query.getWhere().getPosition();
            break;
            }
          default:
            jj_la1[1] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case GROUP:{
            GroupBy();
    endPos = query.getGroupBy().getPosition();
            break;
            }
          default:
            jj_la1[2] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case HAVING:{
            Having();
    endPos = query.getHaving().getPosition();
            break;
            }
          default:
            jj_la1[3] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ORDER:{
            OrderBy();
    endPos = query.getOrderBy().getPosition();
            break;
            }
          default:
            jj_la1[4] = jj_gen;
            ;
          }
    // set the position of the query:
                    query.setPosition(new TextPosition(query.getSelect().getPosition(), endPos));
    
                    // get the previous query (!= null if the current query is a sub-query):
                    ADQLQuery previousQuery = stackQuery.pop();
                    if (stackQuery.isEmpty())
                            query = null;
                    else
                            query = stackQuery.peek();
    
                    {if ("" != null) return previousQuery;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("QueryExpression");
        }
      }
    
      final public ADQLQuery SubQueryExpression() throws ParseException {
        trace_call("SubQueryExpression");
        try {ADQLQuery q = null; Token start, end;
          start = jj_consume_token(LEFT_PAR);
          q = QueryExpression();
          end = jj_consume_token(RIGHT_PAR);
    q.setPosition(new TextPosition(start, end));
                    {if ("" != null) return q;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("SubQueryExpression");
        }
      }
    
      final public void Select() throws ParseException {
        trace_call("Select");
        try {ClauseSelect select = query.getSelect(); SelectItem item=null; Token start,t = null;
          start = jj_consume_token(SELECT);
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case QUANTIFIER:{
            t = jj_consume_token(QUANTIFIER);
    select.setDistinctColumns(t.image.equalsIgnoreCase("DISTINCT"));
            break;
            }
          default:
            jj_la1[5] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case TOP:{
            jj_consume_token(TOP);
            t = jj_consume_token(UNSIGNED_INTEGER);
    try{
                    select.setLimit(Integer.parseInt(t.image));
              }catch(NumberFormatException nfe){
                    {if (true) throw new ParseException("[l."+t.beginLine+";c."+t.beginColumn+"] The TOP limit (\u005c""+t.image+"\u005c") isn't a regular unsigned integer !");}
              }
            break;
            }
          default:
            jj_la1[6] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case OFFSET:{
            jj_consume_token(OFFSET);
            t = jj_consume_token(UNSIGNED_INTEGER);
    try{
                    select.setOffset(Integer.parseInt(t.image));
              }catch(NumberFormatException nfe){
                    {if (true) throw new ParseException("[l."+t.beginLine+";c."+t.beginColumn+"] The OFFSET limit (\u005c""+t.image+"\u005c") isn't a regular unsigned integer !");}
              }
            break;
            }
          default:
            jj_la1[7] = jj_gen;
            ;
          }
          item = SelectItem();
    select.add(item);
          label_1:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case COMMA:{
              ;
              break;
              }
            default:
              jj_la1[8] = jj_gen;
              break label_1;
            }
            jj_consume_token(COMMA);
            item = SelectItem();
    select.add(item);
          }
    TextPosition lastItemPos = query.getSelect().get(query.getSelect().size()-1).getPosition();
                    select.setPosition(new TextPosition(start.beginLine, start.beginColumn, lastItemPos.endLine, lastItemPos.endColumn));
        } finally {
          trace_return("Select");
        }
      }
    
      final public SelectItem SelectItem() throws ParseException {
        trace_call("SelectItem");
        try {IdentifierItems identifiers = new IdentifierItems(true); IdentifierItem id = null, label = null; ADQLOperand op = null; SelectItem item; Token starToken;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ASTERISK:{
            starToken = jj_consume_token(ASTERISK);
    item = new SelectAllColumns(query);
                        item.setPosition(new TextPosition(starToken));
                        {if ("" != null) return item;}
            break;
            }
          default:
            jj_la1[13] = jj_gen;
            if (jj_2_1(7)) {
              id = Identifier();
              jj_consume_token(DOT);
    identifiers.append(id);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                id = Identifier();
                jj_consume_token(DOT);
    identifiers.append(id);
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case DELIMITED_IDENTIFIER:
                case REGULAR_IDENTIFIER_CANDIDATE:{
                  id = Identifier();
                  jj_consume_token(DOT);
    identifiers.append(id);
                  break;
                  }
                default:
                  jj_la1[9] = jj_gen;
                  ;
                }
                break;
                }
              default:
                jj_la1[10] = jj_gen;
                ;
              }
              starToken = jj_consume_token(ASTERISK);
    try{
                                            item = new SelectAllColumns( queryFactory.createTable(identifiers, null) );
                                            TextPosition firstPos = identifiers.get(0).position;
                                            item.setPosition(new TextPosition(firstPos.beginLine, firstPos.beginColumn, starToken.endLine, (starToken.endColumn < 0) ? -1 : (starToken.endColumn + 1)));
                                            {if ("" != null) return item;}
                                    }catch(Exception ex) {
                                            {if (true) throw generateParseException(ex);}
                                    }
            } else {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case LEFT_PAR:
              case PLUS:
              case MINUS:
              case AVG:
              case MAX:
              case MIN:
              case SUM:
              case COUNT:
              case BOX:
              case CENTROID:
              case CIRCLE:
              case POINT:
              case POLYGON:
              case REGION:
              case CONTAINS:
              case INTERSECTS:
              case AREA:
              case COORD1:
              case COORD2:
              case COORDSYS:
              case DISTANCE:
              case ABS:
              case CEILING:
              case DEGREES:
              case EXP:
              case FLOOR:
              case LOG:
              case LOG10:
              case MOD:
              case PI:
              case POWER:
              case RADIANS:
              case RAND:
              case ROUND:
              case SQRT:
              case TRUNCATE:
              case ACOS:
              case ASIN:
              case ATAN:
              case ATAN2:
              case COS:
              case COT:
              case SIN:
              case TAN:
              case STRING_LITERAL:
              case SCIENTIFIC_NUMBER:
              case UNSIGNED_FLOAT:
              case UNSIGNED_INTEGER:
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                op = ValueExpression();
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case AS:
                case DELIMITED_IDENTIFIER:
                case REGULAR_IDENTIFIER_CANDIDATE:{
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case AS:{
                    jj_consume_token(AS);
                    break;
                    }
                  default:
                    jj_la1[11] = jj_gen;
                    ;
                  }
                  label = Identifier();
                  break;
                  }
                default:
                  jj_la1[12] = jj_gen;
                  ;
                }
                break;
                }
              default:
                jj_la1[14] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
            }
          }
    try{
                            item = queryFactory.createSelectItem(op, (label==null)?null:label.identifier);
                            if (label != null){
                                    item.setCaseSensitive(label.caseSensitivity);
                                    item.setPosition(new TextPosition(op.getPosition(), label.position));
                            }else
                                    item.setPosition(new TextPosition(op.getPosition()));
                            {if ("" != null) return item;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("SelectItem");
        }
      }
    
      final public void From() throws ParseException {
        trace_call("From");
        try {FromContent content = null, content2 = null;
          try {
            jj_consume_token(FROM);
            content = TableRef();
            label_2:
            while (true) {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case COMMA:{
                ;
                break;
                }
              default:
                jj_la1[15] = jj_gen;
                break label_2;
              }
              jj_consume_token(COMMA);
              content2 = TableRef();
    TextPosition startPos = content.getPosition(), endPos = content2.getPosition();
                       content = queryFactory.createJoin(JoinType.CROSS, content, content2);
                       content.setPosition(new TextPosition(startPos, endPos));
            }
    query.setFrom(content);
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        } finally {
          trace_return("From");
        }
      }
    
      final public void Where() throws ParseException {
        trace_call("Where");
        try {ClauseConstraints where = query.getWhere(); ADQLConstraint condition; Token start;
          start = jj_consume_token(WHERE);
          ConditionsList(where);
    TextPosition endPosition = where.getPosition();
              where.setPosition(new TextPosition(start.beginLine, start.beginColumn, endPosition.endLine, endPosition.endColumn));
        } finally {
          trace_return("Where");
        }
      }
    
      final public void GroupBy() throws ParseException {
        trace_call("GroupBy");
        try {ClauseADQL<ADQLColumn> groupBy = query.getGroupBy(); ADQLColumn colRef = null; Token start;
          start = jj_consume_token(GROUP);
          jj_consume_token(BY);
          colRef = Column();
    groupBy.add(colRef);
          label_3:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case COMMA:{
              ;
              break;
              }
            default:
              jj_la1[16] = jj_gen;
              break label_3;
            }
            jj_consume_token(COMMA);
            colRef = Column();
    groupBy.add(colRef);
          }
    groupBy.setPosition(new TextPosition(start.beginLine, start.beginColumn, colRef.getPosition().endLine, colRef.getPosition().endColumn));
        } finally {
          trace_return("GroupBy");
        }
      }
    
      final public void Having() throws ParseException {
        trace_call("Having");
        try {ClauseConstraints having = query.getHaving(); Token start;
          start = jj_consume_token(HAVING);
          ConditionsList(having);
    TextPosition endPosition = having.getPosition();
              having.setPosition(new TextPosition(start.beginLine, start.beginColumn, endPosition.endLine, endPosition.endColumn));
        } finally {
          trace_return("Having");
        }
      }
    
      final public void OrderBy() throws ParseException {
        trace_call("OrderBy");
        try {ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); ADQLOrder order = null; Token start;
          start = jj_consume_token(ORDER);
          jj_consume_token(BY);
          order = OrderItem();
    orderBy.add(order);
          label_4:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case COMMA:{
              ;
              break;
              }
            default:
              jj_la1[17] = jj_gen;
              break label_4;
            }
            jj_consume_token(COMMA);
            order = OrderItem();
    orderBy.add(order);
          }
    orderBy.setPosition(new TextPosition(start, token));
        } finally {
          trace_return("OrderBy");
        }
      }
    
    /* *************************** */
    /* COLUMN AND TABLE REFERENCES */
    /* *************************** */
      final public IdentifierItem Identifier() throws ParseException {
        trace_call("Identifier");
        try {Token t;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case REGULAR_IDENTIFIER_CANDIDATE:{
            t = jj_consume_token(REGULAR_IDENTIFIER_CANDIDATE);
    testRegularIdentifier(t);
                            {if ("" != null) return new IdentifierItem(t, false);}
            break;
            }
          case DELIMITED_IDENTIFIER:{
            t = jj_consume_token(DELIMITED_IDENTIFIER);
    {if ("" != null) return new IdentifierItem(t, true);}
            break;
            }
          default:
            jj_la1[18] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Identifier");
        }
      }
    
    /**
     * Extracts the name of a table with its possible catalog and schema prefixes.
     * 
     * @return A {@link IdentifierItems} which contains at most three items: catalogName, schemaName and tableName.
     */
      final public IdentifierItems TableName() throws ParseException {
        trace_call("TableName");
        try {IdentifierItems identifiers=new IdentifierItems(true); IdentifierItem id=null;
          id = Identifier();
    identifiers.append(id);
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case DOT:{
            jj_consume_token(DOT);
            id = Identifier();
    identifiers.append(id);
            break;
            }
          default:
            jj_la1[19] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case DOT:{
            jj_consume_token(DOT);
            id = Identifier();
    identifiers.append(id);
            break;
            }
          default:
            jj_la1[20] = jj_gen;
            ;
          }
    {if ("" != null) return identifiers;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("TableName");
        }
      }
    
    /**
     * Extracts the name of a column with its possible catalog, schema and table prefixes.
     * 
     * @return A {@link IdentifierItems} which contains at most four items: catalogName, schemaName, tableName and columnName.
     */
      final public IdentifierItems ColumnName() throws ParseException {
        trace_call("ColumnName");
        try {IdentifierItem id; IdentifierItems table=null, identifiers=new IdentifierItems(false);
          id = Identifier();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case DOT:{
            jj_consume_token(DOT);
            table = TableName();
            break;
            }
          default:
            jj_la1[21] = jj_gen;
            ;
          }
    identifiers.append(id);
                    if (table != null){
                            for(int i=0; i<table.size(); i++)
                                    identifiers.append(table.get(i));
                    }
                    {if ("" != null) return identifiers;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("ColumnName");
        }
      }
    
      final public ADQLColumn Column() throws ParseException {
        trace_call("Column");
        try {IdentifierItems identifiers;
          identifiers = ColumnName();
    try{
                            {if ("" != null) return queryFactory.createColumn(identifiers);}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Column");
        }
      }
    
      final public ADQLOrder OrderItem() throws ParseException {
        trace_call("OrderItem");
        try {IdentifierItem identifier = null; Token ind = null, desc = null;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case DELIMITED_IDENTIFIER:
          case REGULAR_IDENTIFIER_CANDIDATE:{
            identifier = Identifier();
            break;
            }
          case UNSIGNED_INTEGER:{
            ind = jj_consume_token(UNSIGNED_INTEGER);
            break;
            }
          default:
            jj_la1[22] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ASC:
          case DESC:{
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case ASC:{
              jj_consume_token(ASC);
              break;
              }
            case DESC:{
              desc = jj_consume_token(DESC);
              break;
              }
            default:
              jj_la1[23] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
            break;
            }
          default:
            jj_la1[24] = jj_gen;
            ;
          }
    try{
                            ADQLOrder order = null;
                            if (identifier != null){
                                    order = queryFactory.createOrder(identifier, desc!=null);
                                    order.setPosition(identifier.position);
                            }else{
                                    order = queryFactory.createOrder(Integer.parseInt(ind.image), desc!=null);
                                    order.setPosition(new TextPosition(ind));
                            }
                            {if ("" != null) return order;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("OrderItem");
        }
      }
    
      final public FromContent SimpleTableRef() throws ParseException {
        trace_call("SimpleTableRef");
        try {IdentifierItem alias = null; IdentifierItems identifiers = null; ADQLQuery subQuery = null; FromContent content = null; Token start,end;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case DELIMITED_IDENTIFIER:
            case REGULAR_IDENTIFIER_CANDIDATE:{
              identifiers = TableName();
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case AS:
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case AS:{
                  jj_consume_token(AS);
                  break;
                  }
                default:
                  jj_la1[25] = jj_gen;
                  ;
                }
                alias = Identifier();
                break;
                }
              default:
                jj_la1[26] = jj_gen;
                ;
              }
    content = queryFactory.createTable(identifiers, alias);
                              if (alias == null)
                                    content.setPosition(new TextPosition(identifiers.get(0).position, identifiers.get(identifiers.size()-1).position));
                              else
                                    content.setPosition(new TextPosition(identifiers.get(0).position, alias.position));
                              {if ("" != null) return content;}
              break;
              }
            default:
              jj_la1[28] = jj_gen;
              if (jj_2_2(2)) {
                subQuery = SubQueryExpression();
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case AS:{
                  jj_consume_token(AS);
                  break;
                  }
                default:
                  jj_la1[27] = jj_gen;
                  ;
                }
                alias = Identifier();
    content = queryFactory.createTable(subQuery, alias);
                              if (alias == null)
                                    content.setPosition(new TextPosition(subQuery.getPosition()));
                              else
                                    content.setPosition(new TextPosition(subQuery.getPosition(), alias.position));
                              {if ("" != null) return content;}
              } else {
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case LEFT_PAR:{
                  start = jj_consume_token(LEFT_PAR);
                  content = JoinedTable();
                  end = jj_consume_token(RIGHT_PAR);
    content.setPosition(new TextPosition(start, end));
                              {if ("" != null) return content;}
                  break;
                  }
                default:
                  jj_la1[29] = jj_gen;
                  jj_consume_token(-1);
                  throw new ParseException();
                }
              }
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("SimpleTableRef");
        }
      }
    
      final public FromContent TableRef() throws ParseException {
        trace_call("TableRef");
        try {FromContent content;
          content = SimpleTableRef();
          label_5:
          while (true) {
            if (jj_2_3(2)) {
              ;
            } else {
              break label_5;
            }
            content = JoinSpecification(content);
          }
    {if ("" != null) return content;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("TableRef");
        }
      }
    
      final public FromContent JoinedTable() throws ParseException {
        trace_call("JoinedTable");
        try {FromContent content;
          content = SimpleTableRef();
          label_6:
          while (true) {
            content = JoinSpecification(content);
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case NATURAL:
            case INNER:
            case RIGHT:
            case LEFT:
            case FULL:
            case JOIN:{
              ;
              break;
              }
            default:
              jj_la1[30] = jj_gen;
              break label_6;
            }
          }
    {if ("" != null) return content;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("JoinedTable");
        }
      }
    
      final public ADQLJoin JoinSpecification(FromContent leftTable) throws ParseException {
        trace_call("JoinSpecification");
        try {boolean natural = false; JoinType type = JoinType.INNER;  ClauseConstraints condition = new ClauseConstraints("ON"); ArrayList<ADQLColumn> lstColumns=new ArrayList<ADQLColumn>(); IdentifierItem id; FromContent rightTable; ADQLJoin join; Token lastPar;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case NATURAL:{
              jj_consume_token(NATURAL);
    natural=true;
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case INNER:
              case RIGHT:
              case LEFT:
              case FULL:{
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case INNER:{
                  jj_consume_token(INNER);
                  break;
                  }
                case RIGHT:
                case LEFT:
                case FULL:{
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case LEFT:{
                    jj_consume_token(LEFT);
    type = JoinType.OUTER_LEFT;
                    break;
                    }
                  case RIGHT:{
                    jj_consume_token(RIGHT);
    type = JoinType.OUTER_RIGHT;
                    break;
                    }
                  case FULL:{
                    jj_consume_token(FULL);
    type = JoinType.OUTER_FULL;
                    break;
                    }
                  default:
                    jj_la1[31] = jj_gen;
                    jj_consume_token(-1);
                    throw new ParseException();
                  }
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case OUTER:{
                    jj_consume_token(OUTER);
                    break;
                    }
                  default:
                    jj_la1[32] = jj_gen;
                    ;
                  }
                  break;
                  }
                default:
                  jj_la1[33] = jj_gen;
                  jj_consume_token(-1);
                  throw new ParseException();
                }
                break;
                }
              default:
                jj_la1[34] = jj_gen;
                ;
              }
              jj_consume_token(JOIN);
              rightTable = SimpleTableRef();
    join = queryFactory.createJoin(type, leftTable, rightTable);
                              join.setPosition(new TextPosition(leftTable.getPosition(), rightTable.getPosition()));
                              {if ("" != null) return join;}
              break;
              }
            case INNER:
            case RIGHT:
            case LEFT:
            case FULL:
            case JOIN:{
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case INNER:
              case RIGHT:
              case LEFT:
              case FULL:{
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case INNER:{
                  jj_consume_token(INNER);
                  break;
                  }
                case RIGHT:
                case LEFT:
                case FULL:{
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case LEFT:{
                    jj_consume_token(LEFT);
    type = JoinType.OUTER_LEFT;
                    break;
                    }
                  case RIGHT:{
                    jj_consume_token(RIGHT);
    type = JoinType.OUTER_RIGHT;
                    break;
                    }
                  case FULL:{
                    jj_consume_token(FULL);
    type = JoinType.OUTER_FULL;
                    break;
                    }
                  default:
                    jj_la1[35] = jj_gen;
                    jj_consume_token(-1);
                    throw new ParseException();
                  }
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case OUTER:{
                    jj_consume_token(OUTER);
                    break;
                    }
                  default:
                    jj_la1[36] = jj_gen;
                    ;
                  }
                  break;
                  }
                default:
                  jj_la1[37] = jj_gen;
                  jj_consume_token(-1);
                  throw new ParseException();
                }
                break;
                }
              default:
                jj_la1[38] = jj_gen;
                ;
              }
              jj_consume_token(JOIN);
              rightTable = SimpleTableRef();
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case ON:{
                jj_consume_token(ON);
                ConditionsList(condition);
    join = queryFactory.createJoin(type, leftTable, rightTable, condition);
                                      join.setPosition(new TextPosition(leftTable.getPosition(), condition.getPosition()));
                                      {if ("" != null) return join;}
                break;
                }
              case USING:{
                jj_consume_token(USING);
                jj_consume_token(LEFT_PAR);
                id = Identifier();
    lstColumns.add( queryFactory.createColumn(id) );
                label_7:
                while (true) {
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case COMMA:{
                    ;
                    break;
                    }
                  default:
                    jj_la1[39] = jj_gen;
                    break label_7;
                  }
                  jj_consume_token(COMMA);
                  id = Identifier();
    lstColumns.add( queryFactory.createColumn(id) );
                }
                lastPar = jj_consume_token(RIGHT_PAR);
    join = queryFactory.createJoin(type, leftTable, rightTable, lstColumns);
                                      join.setPosition(new TextPosition(leftTable.getPosition().beginLine, leftTable.getPosition().beginColumn, lastPar.endLine, (lastPar.endColumn < 0) ? -1 : (lastPar.endColumn + 1)));
                                      {if ("" != null) return join;}
                break;
                }
              default:
                jj_la1[40] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              break;
              }
            default:
              jj_la1[41] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("JoinSpecification");
        }
      }
    
    /* ****** */
    /* STRING */
    /* ****** */
      final public StringConstant String() throws ParseException {
        trace_call("String");
        try {Token t, start=null; String str=""; StringConstant cst;
          label_8:
          while (true) {
            t = jj_consume_token(STRING_LITERAL);
    str += t.image.substring(1, t.image.length()-1).replaceAll("''", "'");
                    if (start == null)
                            start = t;
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case STRING_LITERAL:{
              ;
              break;
              }
            default:
              jj_la1[42] = jj_gen;
              break label_8;
            }
          }
    try{
                      cst = queryFactory.createStringConstant(str);
                      cst.setPosition(new TextPosition(start, t));
                      {if ("" != null) return cst;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("String");
        }
      }
    
    /* ************* */
    /* NUMERIC TYPES */
    /* ************* */
      final public NumericConstant UnsignedNumeric() throws ParseException {
        trace_call("UnsignedNumeric");
        try {Token t; NumericConstant cst;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case SCIENTIFIC_NUMBER:{
            t = jj_consume_token(SCIENTIFIC_NUMBER);
            break;
            }
          case UNSIGNED_FLOAT:{
            t = jj_consume_token(UNSIGNED_FLOAT);
            break;
            }
          case UNSIGNED_INTEGER:{
            t = jj_consume_token(UNSIGNED_INTEGER);
            break;
            }
          default:
            jj_la1[43] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    try{
                      cst = queryFactory.createNumericConstant(t.image);
                      cst.setPosition(new TextPosition(t));
                      {if ("" != null) return cst;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("UnsignedNumeric");
        }
      }
    
      final public NumericConstant UnsignedFloat() throws ParseException {
        trace_call("UnsignedFloat");
        try {Token t; NumericConstant cst;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case UNSIGNED_INTEGER:{
            t = jj_consume_token(UNSIGNED_INTEGER);
            break;
            }
          case UNSIGNED_FLOAT:{
            t = jj_consume_token(UNSIGNED_FLOAT);
            break;
            }
          default:
            jj_la1[44] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    try{
                            cst = queryFactory.createNumericConstant(t.image);
                            cst.setPosition(new TextPosition(t));
                            {if ("" != null) return cst;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("UnsignedFloat");
        }
      }
    
      final public NumericConstant SignedInteger() throws ParseException {
        trace_call("SignedInteger");
        try {Token sign=null, number; NumericConstant cst;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case PLUS:
          case MINUS:{
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case PLUS:{
              sign = jj_consume_token(PLUS);
              break;
              }
            case MINUS:{
              sign = jj_consume_token(MINUS);
              break;
              }
            default:
              jj_la1[45] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
            break;
            }
          default:
            jj_la1[46] = jj_gen;
            ;
          }
          number = jj_consume_token(UNSIGNED_INTEGER);
    try{
                            if (sign == null){                              cst = queryFactory.createNumericConstant(number.image);
                                    cst.setPosition(new TextPosition(number));
                            }else{                          cst = queryFactory.createNumericConstant(sign.image+number.image);
                                    cst.setPosition(new TextPosition(sign, number));
                            }
                            {if ("" != null) return cst;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("SignedInteger");
        }
      }
    
    /* *********** */
    /* EXPRESSIONS */
    /* *********** */
      final public ADQLOperand NumericValueExpressionPrimary() throws ParseException {
        trace_call("NumericValueExpressionPrimary");
        try {ADQLColumn column; ADQLOperand op; Token left, right;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case SCIENTIFIC_NUMBER:
            case UNSIGNED_FLOAT:
            case UNSIGNED_INTEGER:{
              // unsigned_value_specification
                                op = UnsignedNumeric();
    {if ("" != null) return op;}
              break;
              }
            case DELIMITED_IDENTIFIER:
            case REGULAR_IDENTIFIER_CANDIDATE:{
              column = Column();
    column.setExpectedType('N'); {if ("" != null) return column;}
              break;
              }
            case AVG:
            case MAX:
            case MIN:
            case SUM:
            case COUNT:{
              op = SqlFunction();
    {if ("" != null) return op;}
              break;
              }
            case LEFT_PAR:{
              left = jj_consume_token(LEFT_PAR);
              op = NumericExpression();
              right = jj_consume_token(RIGHT_PAR);
    WrappedOperand wop = queryFactory.createWrappedOperand(op); wop.setPosition(new TextPosition(left, right)); {if ("" != null) return wop;}
              break;
              }
            default:
              jj_la1[47] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("NumericValueExpressionPrimary");
        }
      }
    
      final public ADQLOperand StringValueExpressionPrimary() throws ParseException {
        trace_call("StringValueExpressionPrimary");
        try {StringConstant expr; ADQLColumn column; ADQLOperand op; Token left, right;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case STRING_LITERAL:{
              // string
                                expr = String();
    {if ("" != null) return expr;}
              break;
              }
            case SCIENTIFIC_NUMBER:
            case UNSIGNED_FLOAT:
            case UNSIGNED_INTEGER:{
              op = UnsignedNumeric();
    {if ("" != null) return op;}
              break;
              }
            case AVG:
            case MAX:
            case MIN:
            case SUM:
            case COUNT:{
              op = SqlFunction();
    {if ("" != null) return op;}
              break;
              }
            case DELIMITED_IDENTIFIER:
            case REGULAR_IDENTIFIER_CANDIDATE:{
              column = Column();
    column.setExpectedType('*'); {if ("" != null) return column;}
              break;
              }
            case LEFT_PAR:{
              left = jj_consume_token(LEFT_PAR);
              op = ValueExpression();
              right = jj_consume_token(RIGHT_PAR);
    WrappedOperand wop = queryFactory.createWrappedOperand(op); wop.setPosition(new TextPosition(left, right)); {if ("" != null) return wop;}
              break;
              }
            default:
              jj_la1[48] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("StringValueExpressionPrimary");
        }
      }
    
      final public ADQLOperand ValueExpression() throws ParseException {
        trace_call("ValueExpression");
        try {ADQLOperand valueExpr = null; Token left, right;
          try {
            if (jj_2_4(2147483647)) {
              valueExpr = NumericExpression();
            } else if (jj_2_5(2147483647)) {
              valueExpr = StringExpression();
            } else if (jj_2_6(2147483647)) {
              left = jj_consume_token(LEFT_PAR);
              valueExpr = ValueExpression();
              right = jj_consume_token(RIGHT_PAR);
    valueExpr = queryFactory.createWrappedOperand(valueExpr); ((WrappedOperand)valueExpr).setPosition(new TextPosition(left, right));
            } else if (jj_2_7(2147483647)) {
              valueExpr = UserDefinedFunction();
            } else if (jj_2_8(2)) {
              valueExpr = GeometryValueFunction();
            } else if (jj_2_9(2147483647)) {
              valueExpr = Column();
            } else if (jj_2_10(2147483647)) {
              valueExpr = StringFactor();
            } else if (jj_2_11(3)) {
              valueExpr = Factor();
            } else {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                valueExpr = Column();
                break;
                }
              default:
                jj_la1[49] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
            }
    {if ("" != null) return valueExpr;}
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("ValueExpression");
        }
      }
    
      final public ADQLOperand NumericExpression() throws ParseException {
        trace_call("NumericExpression");
        try {Token sign=null; ADQLOperand leftOp, rightOp=null;
          leftOp = NumericTerm();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case PLUS:
          case MINUS:{
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case PLUS:{
              sign = jj_consume_token(PLUS);
              break;
              }
            case MINUS:{
              sign = jj_consume_token(MINUS);
              break;
              }
            default:
              jj_la1[50] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
            rightOp = NumericExpression();
            break;
            }
          default:
            jj_la1[51] = jj_gen;
            ;
          }
    if (sign == null)
                    {if ("" != null) return leftOp;}
            else{
                    try{
                            Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
                            operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
                            {if ("" != null) return operation;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
            }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("NumericExpression");
        }
      }
    
      final public ADQLOperand NumericTerm() throws ParseException {
        trace_call("NumericTerm");
        try {Token sign=null; ADQLOperand leftOp, rightOp=null;
          leftOp = Factor();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ASTERISK:
          case DIVIDE:{
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case ASTERISK:{
              sign = jj_consume_token(ASTERISK);
              break;
              }
            case DIVIDE:{
              sign = jj_consume_token(DIVIDE);
              break;
              }
            default:
              jj_la1[52] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
            rightOp = NumericTerm();
            break;
            }
          default:
            jj_la1[53] = jj_gen;
            ;
          }
    if (sign == null)
                    {if ("" != null) return leftOp;}
            else{
                    try{
                            Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
                            operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
                            {if ("" != null) return operation;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
            }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("NumericTerm");
        }
      }
    
      final public ADQLOperand Factor() throws ParseException {
        trace_call("Factor");
        try {boolean negative = false; Token minusSign = null; ADQLOperand op;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case PLUS:
          case MINUS:{
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case PLUS:{
              jj_consume_token(PLUS);
              break;
              }
            case MINUS:{
              minusSign = jj_consume_token(MINUS);
    negative = true;
              break;
              }
            default:
              jj_la1[54] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
            break;
            }
          default:
            jj_la1[55] = jj_gen;
            ;
          }
          if (jj_2_12(2)) {
            op = NumericFunction();
          } else {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case LEFT_PAR:
            case AVG:
            case MAX:
            case MIN:
            case SUM:
            case COUNT:
            case SCIENTIFIC_NUMBER:
            case UNSIGNED_FLOAT:
            case UNSIGNED_INTEGER:
            case DELIMITED_IDENTIFIER:
            case REGULAR_IDENTIFIER_CANDIDATE:{
              op = NumericValueExpressionPrimary();
              break;
              }
            default:
              jj_la1[56] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          }
    if (negative){
                            try{
                                    TextPosition position = op.getPosition();
                                    op = queryFactory.createNegativeOperand(op);
                                    NegativeOperand negativeOp = (NegativeOperand)op;
                                    if (minusSign != null)
                                            negativeOp.setPosition(new TextPosition(minusSign.beginLine, minusSign.beginColumn, position.endLine, position.endColumn));
                                    else
                                            negativeOp.setPosition(position);
                            }catch(Exception ex){
                                    {if (true) throw generateParseException(ex);}
                            }
                    }
    
                    {if ("" != null) return op;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Factor");
        }
      }
    
      final public ADQLOperand StringExpression() throws ParseException {
        trace_call("StringExpression");
        try {ADQLOperand leftOp; ADQLOperand rightOp = null;
          leftOp = StringFactor();
          label_9:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case CONCAT:{
              ;
              break;
              }
            default:
              jj_la1[57] = jj_gen;
              break label_9;
            }
            jj_consume_token(CONCAT);
            rightOp = StringFactor();
    if (!(leftOp instanceof Concatenation)){
                                    try{
                                            ADQLOperand temp = leftOp;
                                            leftOp = queryFactory.createConcatenation();
                                            ((Concatenation)leftOp).add(temp);
                                    }catch(Exception ex){
                                            {if (true) throw generateParseException(ex);}
                                    }
                            }
                            ((Concatenation)leftOp).add(rightOp);
          }
    if (leftOp instanceof Concatenation){
                            Concatenation concat = (Concatenation)leftOp;
                            concat.setPosition(new TextPosition(concat.get(0).getPosition(), concat.get(concat.size()-1).getPosition()));
                    }
              {if ("" != null) return leftOp;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("StringExpression");
        }
      }
    
      final public ADQLOperand StringFactor() throws ParseException {
        trace_call("StringFactor");
        try {ADQLOperand op;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case COORDSYS:{
            op = ExtractCoordSys();
            break;
            }
          default:
            jj_la1[58] = jj_gen;
            if (jj_2_13(2)) {
              op = UserDefinedFunction();
    ((UserDefinedFunction)op).setExpectedType('S');
            } else {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case LEFT_PAR:
              case AVG:
              case MAX:
              case MIN:
              case SUM:
              case COUNT:
              case STRING_LITERAL:
              case SCIENTIFIC_NUMBER:
              case UNSIGNED_FLOAT:
              case UNSIGNED_INTEGER:
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                op = StringValueExpressionPrimary();
                break;
                }
              default:
                jj_la1[59] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
            }
          }
    {if ("" != null) return op;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("StringFactor");
        }
      }
    
      final public GeometryValue<GeometryFunction> GeometryExpression() throws ParseException {
        trace_call("GeometryExpression");
        try {ADQLColumn col = null; GeometryFunction gf = null;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case DELIMITED_IDENTIFIER:
          case REGULAR_IDENTIFIER_CANDIDATE:{
            col = Column();
            break;
            }
          case BOX:
          case CENTROID:
          case CIRCLE:
          case POINT:
          case POLYGON:
          case REGION:{
            gf = GeometryValueFunction();
            break;
            }
          default:
            jj_la1[60] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    if (col != null){
                            col.setExpectedType('G');
                            {if ("" != null) return new GeometryValue<GeometryFunction>(col);}
                    }else
                            {if ("" != null) return new GeometryValue<GeometryFunction>(gf);}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("GeometryExpression");
        }
      }
    
    /* ********************************** */
    /* BOOLEAN EXPRESSIONS (WHERE clause) */
    /* ********************************** */
      final public ClauseConstraints ConditionsList(ClauseConstraints clause) throws ParseException {
        trace_call("ConditionsList");
        try {ADQLConstraint constraint = null; Token op = null; boolean notOp = false;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case NOT:{
              op = jj_consume_token(NOT);
    notOp = true;
              break;
              }
            default:
              jj_la1[61] = jj_gen;
              ;
            }
            constraint = Constraint();
    if (notOp){
                                    TextPosition oldPos = constraint.getPosition();
                                    constraint = queryFactory.createNot(constraint);
                                    ((NotConstraint)constraint).setPosition(new TextPosition(op.beginLine, op.beginColumn, oldPos.endLine, oldPos.endColumn));
                            }
                            notOp = false;
    
                            if (clause instanceof ADQLConstraint)
                                    clause.add(constraint);
                            else
                                    clause.add(constraint);
            label_10:
            while (true) {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case AND:
              case OR:{
                ;
                break;
                }
              default:
                jj_la1[62] = jj_gen;
                break label_10;
              }
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case AND:{
                op = jj_consume_token(AND);
                break;
                }
              case OR:{
                op = jj_consume_token(OR);
                break;
                }
              default:
                jj_la1[63] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case NOT:{
                jj_consume_token(NOT);
    notOp = true;
                break;
                }
              default:
                jj_la1[64] = jj_gen;
                ;
              }
              constraint = Constraint();
    if (notOp){
                                            TextPosition oldPos = constraint.getPosition();
                                            constraint = queryFactory.createNot(constraint);
                                            ((NotConstraint)constraint).setPosition(new TextPosition(op.beginLine, op.beginColumn, oldPos.endLine, oldPos.endColumn));
                                    }
                                    notOp = false;
    
                                    if (clause instanceof ADQLConstraint)
                                            clause.add(op.image, constraint);
                                    else
                                            clause.add(op.image, constraint);
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
    if (!clause.isEmpty()){
                            TextPosition start = clause.get(0).getPosition();
                            TextPosition end = clause.get(clause.size()-1).getPosition();
                            clause.setPosition(new TextPosition(start, end));
                    }
                    {if ("" != null) return clause;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("ConditionsList");
        }
      }
    
      final public ADQLConstraint Constraint() throws ParseException {
        trace_call("Constraint");
        try {ADQLConstraint constraint =  null; Token start, end;
          if (jj_2_14(2147483647)) {
            constraint = Predicate();
          } else {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case LEFT_PAR:{
              start = jj_consume_token(LEFT_PAR);
    try{
                                    constraint = queryFactory.createGroupOfConstraints();
                            }catch(Exception ex){
                                    {if (true) throw generateParseException(ex);}
                            }
              ConditionsList((ConstraintsGroup)constraint);
              end = jj_consume_token(RIGHT_PAR);
    ((ConstraintsGroup)constraint).setPosition(new TextPosition(start, end));
              break;
              }
            default:
              jj_la1[65] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          }
    {if ("" != null) return constraint;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Constraint");
        }
      }
    
      final public ADQLConstraint Predicate() throws ParseException {
        trace_call("Predicate");
        try {ADQLQuery q=null; ADQLColumn column=null; ADQLOperand strExpr1=null, strExpr2=null; ADQLOperand op; Token start, notToken = null, end; ADQLConstraint constraint = null;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case EXISTS:{
              start = jj_consume_token(EXISTS);
              q = SubQueryExpression();
    Exists e = queryFactory.createExists(q);
                              e.setPosition(new TextPosition(start.beginLine, start.beginColumn, q.getPosition().endLine, q.getPosition().endColumn));
                              {if ("" != null) return e;}
              break;
              }
            default:
              jj_la1[70] = jj_gen;
              if (jj_2_16(2147483647)) {
                column = Column();
                jj_consume_token(IS);
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case NOT:{
                  notToken = jj_consume_token(NOT);
                  break;
                  }
                default:
                  jj_la1[66] = jj_gen;
                  ;
                }
                end = jj_consume_token(NULL);
    IsNull in = queryFactory.createIsNull((notToken!=null), column);
                          in.setPosition(new TextPosition(column.getPosition().beginLine, column.getPosition().beginColumn, end.endLine, (end.endColumn < 0) ? -1 : (end.endColumn + 1)));
                          {if ("" != null) return in;}
              } else if (jj_2_17(2147483647)) {
                strExpr1 = StringExpression();
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case NOT:{
                  notToken = jj_consume_token(NOT);
                  break;
                  }
                default:
                  jj_la1[67] = jj_gen;
                  ;
                }
                jj_consume_token(LIKE);
                strExpr2 = StringExpression();
    Comparison comp = queryFactory.createComparison(strExpr1, (notToken==null)?ComparisonOperator.LIKE:ComparisonOperator.NOTLIKE, strExpr2);
                          comp.setPosition(new TextPosition(strExpr1.getPosition(), strExpr2.getPosition()));
                          {if ("" != null) return comp;}
              } else {
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case LEFT_PAR:
                case PLUS:
                case MINUS:
                case AVG:
                case MAX:
                case MIN:
                case SUM:
                case COUNT:
                case BOX:
                case CENTROID:
                case CIRCLE:
                case POINT:
                case POLYGON:
                case REGION:
                case CONTAINS:
                case INTERSECTS:
                case AREA:
                case COORD1:
                case COORD2:
                case COORDSYS:
                case DISTANCE:
                case ABS:
                case CEILING:
                case DEGREES:
                case EXP:
                case FLOOR:
                case LOG:
                case LOG10:
                case MOD:
                case PI:
                case POWER:
                case RADIANS:
                case RAND:
                case ROUND:
                case SQRT:
                case TRUNCATE:
                case ACOS:
                case ASIN:
                case ATAN:
                case ATAN2:
                case COS:
                case COT:
                case SIN:
                case TAN:
                case STRING_LITERAL:
                case SCIENTIFIC_NUMBER:
                case UNSIGNED_FLOAT:
                case UNSIGNED_INTEGER:
                case DELIMITED_IDENTIFIER:
                case REGULAR_IDENTIFIER_CANDIDATE:{
                  op = ValueExpression();
                  switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                  case EQUAL:
                  case NOT_EQUAL:
                  case LESS_THAN:
                  case LESS_EQUAL_THAN:
                  case GREATER_THAN:
                  case GREATER_EQUAL_THAN:{
                    constraint = ComparisonEnd(op);
                    break;
                    }
                  default:
                    jj_la1[68] = jj_gen;
                    if (jj_2_15(2)) {
                      constraint = BetweenEnd(op);
                    } else {
                      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                      case NOT:
                      case IN:{
                        constraint = InEnd(op);
                        break;
                        }
                      default:
                        jj_la1[69] = jj_gen;
                        jj_consume_token(-1);
                        throw new ParseException();
                      }
                    }
                  }
                  break;
                  }
                default:
                  jj_la1[71] = jj_gen;
                  jj_consume_token(-1);
                  throw new ParseException();
                }
              }
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
    {if ("" != null) return constraint;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Predicate");
        }
      }
    
      final public Comparison ComparisonEnd(ADQLOperand leftOp) throws ParseException {
        trace_call("ComparisonEnd");
        try {Token comp; ADQLOperand rightOp;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case EQUAL:{
            comp = jj_consume_token(EQUAL);
            break;
            }
          case NOT_EQUAL:{
            comp = jj_consume_token(NOT_EQUAL);
            break;
            }
          case LESS_THAN:{
            comp = jj_consume_token(LESS_THAN);
            break;
            }
          case LESS_EQUAL_THAN:{
            comp = jj_consume_token(LESS_EQUAL_THAN);
            break;
            }
          case GREATER_THAN:{
            comp = jj_consume_token(GREATER_THAN);
            break;
            }
          case GREATER_EQUAL_THAN:{
            comp = jj_consume_token(GREATER_EQUAL_THAN);
            break;
            }
          default:
            jj_la1[72] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          rightOp = ValueExpression();
    try{
                            Comparison comparison = queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp);
                            comparison.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
                            {if ("" != null) return comparison;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("ComparisonEnd");
        }
      }
    
      final public Between BetweenEnd(ADQLOperand leftOp) throws ParseException {
        trace_call("BetweenEnd");
        try {Token start,notToken=null; ADQLOperand min, max;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case NOT:{
            notToken = jj_consume_token(NOT);
            break;
            }
          default:
            jj_la1[73] = jj_gen;
            ;
          }
          start = jj_consume_token(BETWEEN);
          min = ValueExpression();
          jj_consume_token(AND);
          max = ValueExpression();
    try{
                            Between bet = queryFactory.createBetween((notToken!=null), leftOp, min, max);
                            if (notToken != null) start = notToken;
                            bet.setPosition(new TextPosition(start.beginLine, start.beginColumn, max.getPosition().endLine, max.getPosition().endColumn));
                            {if ("" != null) return bet;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("BetweenEnd");
        }
      }
    
      final public In InEnd(ADQLOperand leftOp) throws ParseException {
        trace_call("InEnd");
        try {Token not=null, start; ADQLQuery q = null; ADQLOperand item; Vector<ADQLOperand> items = new Vector<ADQLOperand>();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case NOT:{
            not = jj_consume_token(NOT);
            break;
            }
          default:
            jj_la1[74] = jj_gen;
            ;
          }
          start = jj_consume_token(IN);
          if (jj_2_18(2)) {
            q = SubQueryExpression();
          } else {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case LEFT_PAR:{
              jj_consume_token(LEFT_PAR);
              item = ValueExpression();
    items.add(item);
              label_11:
              while (true) {
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case COMMA:{
                  ;
                  break;
                  }
                default:
                  jj_la1[75] = jj_gen;
                  break label_11;
                }
                jj_consume_token(COMMA);
                item = ValueExpression();
    items.add(item);
              }
              jj_consume_token(RIGHT_PAR);
              break;
              }
            default:
              jj_la1[76] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          }
    try{
                            In in;
                            start = (not!=null) ? not : start;
                            if (q != null){
                                    in = queryFactory.createIn(leftOp, q, not!=null);
                                    in.setPosition(new TextPosition(start.beginLine, start.beginColumn, q.getPosition().endLine, q.getPosition().endColumn));
                            }else{
                                    ADQLOperand[] list = new ADQLOperand[items.size()];
                                    int i=0;
                                    for(ADQLOperand op : items)
                                            list[i++] = op;
                                    in = queryFactory.createIn(leftOp, list, not!=null);
                                    in.setPosition(new TextPosition(start.beginLine, start.beginColumn, list[list.length-1].getPosition().endLine, list[list.length-1].getPosition().endColumn));
                            }
                            {if ("" != null) return in;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("InEnd");
        }
      }
    
    /* ************* */
    /* SQL FUNCTIONS */
    /* ************* */
      final public SQLFunction SqlFunction() throws ParseException {
        trace_call("SqlFunction");
        try {Token fct, all=null, distinct=null, end; ADQLOperand op=null; SQLFunction funct = null;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case COUNT:{
              fct = jj_consume_token(COUNT);
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case QUANTIFIER:{
                distinct = jj_consume_token(QUANTIFIER);
                break;
                }
              default:
                jj_la1[77] = jj_gen;
                ;
              }
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case ASTERISK:{
                all = jj_consume_token(ASTERISK);
                break;
                }
              case LEFT_PAR:
              case PLUS:
              case MINUS:
              case AVG:
              case MAX:
              case MIN:
              case SUM:
              case COUNT:
              case BOX:
              case CENTROID:
              case CIRCLE:
              case POINT:
              case POLYGON:
              case REGION:
              case CONTAINS:
              case INTERSECTS:
              case AREA:
              case COORD1:
              case COORD2:
              case COORDSYS:
              case DISTANCE:
              case ABS:
              case CEILING:
              case DEGREES:
              case EXP:
              case FLOOR:
              case LOG:
              case LOG10:
              case MOD:
              case PI:
              case POWER:
              case RADIANS:
              case RAND:
              case ROUND:
              case SQRT:
              case TRUNCATE:
              case ACOS:
              case ASIN:
              case ATAN:
              case ATAN2:
              case COS:
              case COT:
              case SIN:
              case TAN:
              case STRING_LITERAL:
              case SCIENTIFIC_NUMBER:
              case UNSIGNED_FLOAT:
              case UNSIGNED_INTEGER:
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                op = ValueExpression();
                break;
                }
              default:
                jj_la1[78] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              end = jj_consume_token(RIGHT_PAR);
    funct = queryFactory.createSQLFunction((all!=null)?SQLFunctionType.COUNT_ALL:SQLFunctionType.COUNT, op, distinct != null && distinct.image.equalsIgnoreCase("distinct"));
                              funct.setPosition(new TextPosition(fct, end));
              break;
              }
            case AVG:
            case MAX:
            case MIN:
            case SUM:{
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case AVG:{
                fct = jj_consume_token(AVG);
                break;
                }
              case MAX:{
                fct = jj_consume_token(MAX);
                break;
                }
              case MIN:{
                fct = jj_consume_token(MIN);
                break;
                }
              case SUM:{
                fct = jj_consume_token(SUM);
                break;
                }
              default:
                jj_la1[79] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case QUANTIFIER:{
                distinct = jj_consume_token(QUANTIFIER);
                break;
                }
              default:
                jj_la1[80] = jj_gen;
                ;
              }
              op = ValueExpression();
              end = jj_consume_token(RIGHT_PAR);
    funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct"));
                              funct.setPosition(new TextPosition(fct, end));
              break;
              }
            default:
              jj_la1[81] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
    {if ("" != null) return funct;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("SqlFunction");
        }
      }
    
    /* ************** */
    /* ADQL FUNCTIONS */
    /* ************** */
      final public ADQLOperand[] Coordinates() throws ParseException {
        trace_call("Coordinates");
        try {ADQLOperand[] ops = new ADQLOperand[2];
          ops[0] = NumericExpression();
          jj_consume_token(COMMA);
          ops[1] = NumericExpression();
    {if ("" != null) return ops;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Coordinates");
        }
      }
    
      final public GeometryFunction GeometryFunction() throws ParseException {
        trace_call("GeometryFunction");
        try {Token fct=null, end; GeometryValue<GeometryFunction> gvf1, gvf2; GeometryValue<PointFunction> gvp1, gvp2; GeometryFunction gf = null; PointFunction p1=null, p2=null; ADQLColumn col1 = null, col2 = null;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case CONTAINS:
            case INTERSECTS:{
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case CONTAINS:{
                fct = jj_consume_token(CONTAINS);
                break;
                }
              case INTERSECTS:{
                fct = jj_consume_token(INTERSECTS);
                break;
                }
              default:
                jj_la1[82] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              jj_consume_token(LEFT_PAR);
              gvf1 = GeometryExpression();
              jj_consume_token(COMMA);
              gvf2 = GeometryExpression();
              end = jj_consume_token(RIGHT_PAR);
    if (fct.image.equalsIgnoreCase("contains"))
                                            gf = queryFactory.createContains(gvf1, gvf2);
                                    else
                                            gf = queryFactory.createIntersects(gvf1, gvf2);
              break;
              }
            case AREA:{
              fct = jj_consume_token(AREA);
              jj_consume_token(LEFT_PAR);
              gvf1 = GeometryExpression();
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createArea(gvf1);
              break;
              }
            case COORD1:{
              fct = jj_consume_token(COORD1);
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case POINT:{
                p1 = Point();
    gf = queryFactory.createCoord1(p1);
                break;
                }
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                col1 = Column();
    col1.setExpectedType('G'); gf = queryFactory.createCoord1(col1);
                break;
                }
              default:
                jj_la1[83] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case COORD2:{
              fct = jj_consume_token(COORD2);
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case POINT:{
                p1 = Point();
    gf = queryFactory.createCoord2(p1);
                break;
                }
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                col1 = Column();
    col1.setExpectedType('G'); gf = queryFactory.createCoord2(col1);
                break;
                }
              default:
                jj_la1[84] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case DISTANCE:{
              fct = jj_consume_token(DISTANCE);
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case POINT:{
                p1 = Point();
                break;
                }
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                col1 = Column();
                break;
                }
              default:
                jj_la1[85] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
    if (p1 != null)
                                                    gvp1 = new GeometryValue<PointFunction>(p1);
                                            else{
                                                    col1.setExpectedType('G');
                                                    gvp1 = new GeometryValue<PointFunction>(col1);
                                            }
              jj_consume_token(COMMA);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case POINT:{
                p2 = Point();
                break;
                }
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                col2 = Column();
                break;
                }
              default:
                jj_la1[86] = jj_gen;
                jj_consume_token(-1);
                throw new ParseException();
              }
    if (p2 != null)
                                                    gvp2 = new GeometryValue<PointFunction>(p2);
                                            else{
                                                    col2.setExpectedType('G');
                                                    gvp2 = new GeometryValue<PointFunction>(col2);
                                            }
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createDistance(gvp1, gvp2);
              break;
              }
            default:
              jj_la1[87] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
    gf.setPosition(new TextPosition(fct, end));
              {if ("" != null) return gf;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("GeometryFunction");
        }
      }
    
      final public ADQLOperand CoordinateSystem() throws ParseException {
        trace_call("CoordinateSystem");
        try {ADQLOperand coordSys=null;
          coordSys = StringExpression();
    {if ("" != null) return coordSys;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("CoordinateSystem");
        }
      }
    
      final public GeometryFunction GeometryValueFunction() throws ParseException {
        trace_call("GeometryValueFunction");
        try {Token fct=null, end=null; ADQLOperand coordSys; ADQLOperand width, height; ADQLOperand[] coords, tmp; Vector<ADQLOperand> vCoords; ADQLOperand op=null; GeometryValue<GeometryFunction> gvf = null; GeometryFunction gf = null;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case BOX:{
              fct = jj_consume_token(BOX);
              jj_consume_token(LEFT_PAR);
              coordSys = CoordinateSystem();
              jj_consume_token(COMMA);
              coords = Coordinates();
              jj_consume_token(COMMA);
              width = NumericExpression();
              jj_consume_token(COMMA);
              height = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createBox(coordSys, coords[0], coords[1], width, height);
              break;
              }
            case CENTROID:{
              fct = jj_consume_token(CENTROID);
              jj_consume_token(LEFT_PAR);
              gvf = GeometryExpression();
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createCentroid(gvf);
              break;
              }
            case CIRCLE:{
              fct = jj_consume_token(CIRCLE);
              jj_consume_token(LEFT_PAR);
              coordSys = CoordinateSystem();
              jj_consume_token(COMMA);
              coords = Coordinates();
              jj_consume_token(COMMA);
              width = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createCircle(coordSys, coords[0], coords[1], width);
              break;
              }
            case POINT:{
              gf = Point();
              break;
              }
            case POLYGON:{
              fct = jj_consume_token(POLYGON);
              jj_consume_token(LEFT_PAR);
              coordSys = CoordinateSystem();
    vCoords = new Vector<ADQLOperand>();
              jj_consume_token(COMMA);
              tmp = Coordinates();
    vCoords.add(tmp[0]); vCoords.add(tmp[1]);
              jj_consume_token(COMMA);
              tmp = Coordinates();
    vCoords.add(tmp[0]); vCoords.add(tmp[1]);
              jj_consume_token(COMMA);
              tmp = Coordinates();
    vCoords.add(tmp[0]); vCoords.add(tmp[1]);
              label_12:
              while (true) {
                switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
                case COMMA:{
                  ;
                  break;
                  }
                default:
                  jj_la1[88] = jj_gen;
                  break label_12;
                }
                jj_consume_token(COMMA);
                tmp = Coordinates();
    vCoords.add(tmp[0]); vCoords.add(tmp[1]);
              }
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createPolygon(coordSys, vCoords);
              break;
              }
            case REGION:{
              fct = jj_consume_token(REGION);
              jj_consume_token(LEFT_PAR);
              op = StringExpression();
              end = jj_consume_token(RIGHT_PAR);
    gf = queryFactory.createRegion(op);
              break;
              }
            default:
              jj_la1[89] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
    if (fct != null && end != null) // = !(gf instanceof Point)
                    gf.setPosition(new TextPosition(fct, end));
              {if ("" != null) return gf;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("GeometryValueFunction");
        }
      }
    
      final public PointFunction Point() throws ParseException {
        trace_call("Point");
        try {Token start, end; ADQLOperand coordSys; ADQLOperand[] coords;
          start = jj_consume_token(POINT);
          jj_consume_token(LEFT_PAR);
          coordSys = CoordinateSystem();
          jj_consume_token(COMMA);
          coords = Coordinates();
          end = jj_consume_token(RIGHT_PAR);
    try{
                            PointFunction pf = queryFactory.createPoint(coordSys, coords[0], coords[1]);
                            pf.setPosition(new TextPosition(start, end));
                            {if ("" != null) return pf;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("Point");
        }
      }
    
      final public GeometryFunction ExtractCoordSys() throws ParseException {
        trace_call("ExtractCoordSys");
        try {Token start, end; GeometryValue<GeometryFunction> gvf;
          start = jj_consume_token(COORDSYS);
          jj_consume_token(LEFT_PAR);
          gvf = GeometryExpression();
          end = jj_consume_token(RIGHT_PAR);
    try{
                            GeometryFunction gf = queryFactory.createExtractCoordSys(gvf);
                            gf.setPosition(new TextPosition(start, end));
                            {if ("" != null) return gf;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("ExtractCoordSys");
        }
      }
    
    /* ***************** */
    /* NUMERIC FUNCTIONS */
    /* ***************** */
      final public ADQLFunction NumericFunction() throws ParseException {
        trace_call("NumericFunction");
        try {ADQLFunction fct;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ABS:
          case CEILING:
          case DEGREES:
          case EXP:
          case FLOOR:
          case LOG:
          case LOG10:
          case MOD:
          case PI:
          case POWER:
          case RADIANS:
          case RAND:
          case ROUND:
          case SQRT:
          case TRUNCATE:{
            fct = MathFunction();
            break;
            }
          case ACOS:
          case ASIN:
          case ATAN:
          case ATAN2:
          case COS:
          case COT:
          case SIN:
          case TAN:{
            fct = TrigFunction();
            break;
            }
          case CONTAINS:
          case INTERSECTS:
          case AREA:
          case COORD1:
          case COORD2:
          case DISTANCE:{
            fct = GeometryFunction();
            break;
            }
          case REGULAR_IDENTIFIER_CANDIDATE:{
            fct = UserDefinedFunction();
    ((UserDefinedFunction)fct).setExpectedType('N');
            break;
            }
          default:
            jj_la1[90] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    {if ("" != null) return fct;}
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("NumericFunction");
        }
      }
    
      final public MathFunction MathFunction() throws ParseException {
        trace_call("MathFunction");
        try {Token fct=null, end; ADQLOperand param1=null, param2=null; NumericConstant integerValue = null;
          try {
            switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
            case ABS:{
              fct = jj_consume_token(ABS);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case CEILING:{
              fct = jj_consume_token(CEILING);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case DEGREES:{
              fct = jj_consume_token(DEGREES);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case EXP:{
              fct = jj_consume_token(EXP);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case FLOOR:{
              fct = jj_consume_token(FLOOR);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case LOG:{
              fct = jj_consume_token(LOG);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case LOG10:{
              fct = jj_consume_token(LOG10);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case MOD:{
              fct = jj_consume_token(MOD);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              jj_consume_token(COMMA);
              param2 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case PI:{
              fct = jj_consume_token(PI);
              jj_consume_token(LEFT_PAR);
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case POWER:{
              fct = jj_consume_token(POWER);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              jj_consume_token(COMMA);
              param2 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case RADIANS:{
              fct = jj_consume_token(RADIANS);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case RAND:{
              fct = jj_consume_token(RAND);
              jj_consume_token(LEFT_PAR);
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case LEFT_PAR:
              case PLUS:
              case MINUS:
              case AVG:
              case MAX:
              case MIN:
              case SUM:
              case COUNT:
              case CONTAINS:
              case INTERSECTS:
              case AREA:
              case COORD1:
              case COORD2:
              case DISTANCE:
              case ABS:
              case CEILING:
              case DEGREES:
              case EXP:
              case FLOOR:
              case LOG:
              case LOG10:
              case MOD:
              case PI:
              case POWER:
              case RADIANS:
              case RAND:
              case ROUND:
              case SQRT:
              case TRUNCATE:
              case ACOS:
              case ASIN:
              case ATAN:
              case ATAN2:
              case COS:
              case COT:
              case SIN:
              case TAN:
              case SCIENTIFIC_NUMBER:
              case UNSIGNED_FLOAT:
              case UNSIGNED_INTEGER:
              case DELIMITED_IDENTIFIER:
              case REGULAR_IDENTIFIER_CANDIDATE:{
                param1 = NumericExpression();
                break;
                }
              default:
                jj_la1[91] = jj_gen;
                ;
              }
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case ROUND:{
              fct = jj_consume_token(ROUND);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case COMMA:{
                jj_consume_token(COMMA);
                param2 = SignedInteger();
                break;
                }
              default:
                jj_la1[92] = jj_gen;
                ;
              }
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case SQRT:{
              fct = jj_consume_token(SQRT);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            case TRUNCATE:{
              fct = jj_consume_token(TRUNCATE);
              jj_consume_token(LEFT_PAR);
              param1 = NumericExpression();
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case COMMA:{
                jj_consume_token(COMMA);
                param2 = SignedInteger();
                break;
                }
              default:
                jj_la1[93] = jj_gen;
                ;
              }
              end = jj_consume_token(RIGHT_PAR);
              break;
              }
            default:
              jj_la1[94] = jj_gen;
              jj_consume_token(-1);
              throw new ParseException();
            }
    MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
                            mf.setPosition(new TextPosition(fct, end));
                            {if ("" != null) return mf;}
          } catch (Exception ex) {
    {if (true) throw generateParseException(ex);}
          }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("MathFunction");
        }
      }
    
      final public MathFunction TrigFunction() throws ParseException {
        trace_call("TrigFunction");
        try {Token fct=null, end; ADQLOperand param1=null, param2=null;
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case ACOS:{
            fct = jj_consume_token(ACOS);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case ASIN:{
            fct = jj_consume_token(ASIN);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case ATAN:{
            fct = jj_consume_token(ATAN);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case ATAN2:{
            fct = jj_consume_token(ATAN2);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            jj_consume_token(COMMA);
            param2 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case COS:{
            fct = jj_consume_token(COS);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case COT:{
            fct = jj_consume_token(COT);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case SIN:{
            fct = jj_consume_token(SIN);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          case TAN:{
            fct = jj_consume_token(TAN);
            jj_consume_token(LEFT_PAR);
            param1 = NumericExpression();
            end = jj_consume_token(RIGHT_PAR);
            break;
            }
          default:
            jj_la1[95] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
    try{
                            MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
                            mf.setPosition(new TextPosition(fct, end));
                            {if ("" != null) return mf;}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("TrigFunction");
        }
      }
    
      final public UserDefinedFunction UserDefinedFunction() throws ParseException {
        trace_call("UserDefinedFunction");
        try {Token fct, end; Vector<ADQLOperand> params = new Vector<ADQLOperand>(); ADQLOperand op;
          fct = jj_consume_token(REGULAR_IDENTIFIER_CANDIDATE);
          jj_consume_token(LEFT_PAR);
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case LEFT_PAR:
          case PLUS:
          case MINUS:
          case AVG:
          case MAX:
          case MIN:
          case SUM:
          case COUNT:
          case BOX:
          case CENTROID:
          case CIRCLE:
          case POINT:
          case POLYGON:
          case REGION:
          case CONTAINS:
          case INTERSECTS:
          case AREA:
          case COORD1:
          case COORD2:
          case COORDSYS:
          case DISTANCE:
          case ABS:
          case CEILING:
          case DEGREES:
          case EXP:
          case FLOOR:
          case LOG:
          case LOG10:
          case MOD:
          case PI:
          case POWER:
          case RADIANS:
          case RAND:
          case ROUND:
          case SQRT:
          case TRUNCATE:
          case ACOS:
          case ASIN:
          case ATAN:
          case ATAN2:
          case COS:
          case COT:
          case SIN:
          case TAN:
          case STRING_LITERAL:
          case SCIENTIFIC_NUMBER:
          case UNSIGNED_FLOAT:
          case UNSIGNED_INTEGER:
          case DELIMITED_IDENTIFIER:
          case REGULAR_IDENTIFIER_CANDIDATE:{
            op = ValueExpression();
    params.add(op);
            label_13:
            while (true) {
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case COMMA:{
                ;
                break;
                }
              default:
                jj_la1[96] = jj_gen;
                break label_13;
              }
              jj_consume_token(COMMA);
              op = ValueExpression();
    params.add(op);
            }
            break;
            }
          default:
            jj_la1[97] = jj_gen;
            ;
          }
          end = jj_consume_token(RIGHT_PAR);
    // Ensure the given function name is valid: 
                    if (!isRegularIdentifier(fct.image))
                            {if (true) throw new ParseException("Invalid (User Defined) Function name: \u005c""+fct.image+"\u005c"!", new TextPosition(fct));}
    
                    //System.out.println("INFO [ADQLParser]: \""+fct.image+"\" (from line "+fct.beginLine+" and column "+fct.beginColumn+" to line "+token.endLine+" and column "+(token.endColumn+1)+") is considered as an user defined function !");
    
                    try{
                            //  Build the parameters list:
                            ADQLOperand[] parameters = new ADQLOperand[params.size()];
                            for(int i=0; i<params.size(); i++)
                                    parameters[i] = params.get(i);
    
                            // Create the UDF function:
                            UserDefinedFunction udf = queryFactory.createUserDefinedFunction(fct.image, parameters);
                            udf.setPosition(new TextPosition(fct, end));
                            {if ("" != null) return udf;}
    
                    }catch(UnsupportedOperationException uoe){
                            /* This catch clause is just for backward compatibility:
    		  	 * if the createUserDefinedFunction(...) is overridden and
    		  	 * the function can not be identified a such exception may be thrown). */
                            {if (true) throw new ParseException(uoe.getMessage(), new TextPosition(fct, token));}
                    }catch(Exception ex){
                            {if (true) throw generateParseException(ex);}
                    }
        throw new Error("Missing return statement in function");
        } finally {
          trace_return("UserDefinedFunction");
        }
      }
    
      private boolean jj_2_1(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_1(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(0, xla); }
      }
    
      private boolean jj_2_2(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_2(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(1, xla); }
      }
    
      private boolean jj_2_3(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_3(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(2, xla); }
      }
    
      private boolean jj_2_4(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_4(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(3, xla); }
      }
    
      private boolean jj_2_5(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_5(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(4, xla); }
      }
    
      private boolean jj_2_6(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_6(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(5, xla); }
      }
    
      private boolean jj_2_7(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_7(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(6, xla); }
      }
    
      private boolean jj_2_8(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_8(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(7, xla); }
      }
    
      private boolean jj_2_9(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_9(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(8, xla); }
      }
    
      private boolean jj_2_10(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_10(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(9, xla); }
      }
    
      private boolean jj_2_11(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_11(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(10, xla); }
      }
    
      private boolean jj_2_12(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_12(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(11, xla); }
      }
    
      private boolean jj_2_13(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_13(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(12, xla); }
      }
    
      private boolean jj_2_14(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_14(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(13, xla); }
      }
    
      private boolean jj_2_15(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_15(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(14, xla); }
      }
    
      private boolean jj_2_16(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_16(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(15, xla); }
      }
    
      private boolean jj_2_17(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_17(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(16, xla); }
      }
    
      private boolean jj_2_18(int xla)
     {
        jj_la = xla; jj_lastpos = jj_scanpos = token;
        try { return !jj_3_18(); }
        catch(LookaheadSuccess ls) { return true; }
        finally { jj_save(17, xla); }
      }
    
      private boolean jj_3R_134()
     {
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_51()) return true;
        return false;
      }
    
      private boolean jj_3_2()
     {
        if (jj_3R_16()) return true;
        return false;
      }
    
      private boolean jj_3R_75()
     {
        if (jj_3R_79()) return true;
        return false;
      }
    
      private boolean jj_3R_27()
     {
        if (jj_3R_51()) return true;
        return false;
      }
    
      private boolean jj_3R_56()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_75()) {
        jj_scanpos = xsp;
        if (jj_3_2()) {
        jj_scanpos = xsp;
        if (jj_3R_76()) return true;
        }
        }
        return false;
      }
    
      private boolean jj_3_14()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(43)) {
        jj_scanpos = xsp;
        if (jj_3R_27()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_120()
     {
        if (jj_3R_51()) return true;
        Token xsp;
        while (true) {
          xsp = jj_scanpos;
          if (jj_3R_134()) { jj_scanpos = xsp; break; }
        }
        return false;
      }
    
      private boolean jj_3R_60()
     {
        if (jj_scan_token(DOT)) return true;
        if (jj_3R_79()) return true;
        return false;
      }
    
      private boolean jj_3R_22()
     {
        if (jj_3R_43()) return true;
        return false;
      }
    
      private boolean jj_3R_150()
     {
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_153()) return true;
        return false;
      }
    
      private boolean jj_3R_149()
     {
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_153()) return true;
        return false;
      }
    
      private boolean jj_3R_43()
     {
        if (jj_3R_14()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_60()) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3R_127()
     {
        if (jj_scan_token(DOT)) return true;
        if (jj_3R_14()) return true;
        return false;
      }
    
      private boolean jj_3R_126()
     {
        if (jj_scan_token(DOT)) return true;
        if (jj_3R_14()) return true;
        return false;
      }
    
      private boolean jj_3R_79()
     {
        if (jj_3R_14()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_126()) jj_scanpos = xsp;
        xsp = jj_scanpos;
        if (jj_3R_127()) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3R_31()
     {
        if (jj_scan_token(DELIMITED_IDENTIFIER)) return true;
        return false;
      }
    
      private boolean jj_3R_133()
     {
        if (jj_3R_21()) return true;
        return false;
      }
    
      private boolean jj_3R_30()
     {
        if (jj_scan_token(REGULAR_IDENTIFIER_CANDIDATE)) return true;
        return false;
      }
    
      private boolean jj_3R_26()
     {
        if (jj_scan_token(REGULAR_IDENTIFIER_CANDIDATE)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_120()) jj_scanpos = xsp;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_141()
     {
        if (jj_3R_112()) return true;
        return false;
      }
    
      private boolean jj_3R_14()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_30()) {
        jj_scanpos = xsp;
        if (jj_3R_31()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_132()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_119()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_132()) {
        jj_scanpos = xsp;
        if (jj_3R_133()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_106()
     {
        if (jj_scan_token(TAN)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_105()
     {
        if (jj_scan_token(SIN)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_58()
     {
        if (jj_3R_78()) return true;
        return false;
      }
    
      private boolean jj_3R_104()
     {
        if (jj_scan_token(COT)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3_13()
     {
        if (jj_3R_26()) return true;
        return false;
      }
    
      private boolean jj_3R_103()
     {
        if (jj_scan_token(COS)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_102()
     {
        if (jj_scan_token(ATAN2)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_57()
     {
        if (jj_3R_77()) return true;
        return false;
      }
    
      private boolean jj_3R_101()
     {
        if (jj_scan_token(ATAN)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_36()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_57()) {
        jj_scanpos = xsp;
        if (jj_3_13()) {
        jj_scanpos = xsp;
        if (jj_3R_58()) return true;
        }
        }
        return false;
      }
    
      private boolean jj_3R_100()
     {
        if (jj_scan_token(ASIN)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_99()
     {
        if (jj_scan_token(ACOS)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_64()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_99()) {
        jj_scanpos = xsp;
        if (jj_3R_100()) {
        jj_scanpos = xsp;
        if (jj_3R_101()) {
        jj_scanpos = xsp;
        if (jj_3R_102()) {
        jj_scanpos = xsp;
        if (jj_3R_103()) {
        jj_scanpos = xsp;
        if (jj_3R_104()) {
        jj_scanpos = xsp;
        if (jj_3R_105()) {
        jj_scanpos = xsp;
        if (jj_3R_106()) return true;
        }
        }
        }
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_46()
     {
        if (jj_3R_62()) return true;
        return false;
      }
    
      private boolean jj_3R_98()
     {
        if (jj_scan_token(TRUNCATE)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_150()) jj_scanpos = xsp;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_97()
     {
        if (jj_scan_token(SQRT)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_96()
     {
        if (jj_scan_token(ROUND)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_149()) jj_scanpos = xsp;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_95()
     {
        if (jj_scan_token(RAND)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_141()) jj_scanpos = xsp;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_94()
     {
        if (jj_scan_token(RADIANS)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_93()
     {
        if (jj_scan_token(POWER)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_92()
     {
        if (jj_scan_token(PI)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_91()
     {
        if (jj_scan_token(MOD)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_90()
     {
        if (jj_scan_token(LOG10)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_89()
     {
        if (jj_scan_token(LOG)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_88()
     {
        if (jj_scan_token(FLOOR)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_87()
     {
        if (jj_scan_token(EXP)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_52()
     {
        if (jj_scan_token(CONCAT)) return true;
        if (jj_3R_36()) return true;
        return false;
      }
    
      private boolean jj_3R_86()
     {
        if (jj_scan_token(DEGREES)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_85()
     {
        if (jj_scan_token(CEILING)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_84()
     {
        if (jj_scan_token(ABS)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_29()
     {
        if (jj_3R_36()) return true;
        Token xsp;
        while (true) {
          xsp = jj_scanpos;
          if (jj_3R_52()) { jj_scanpos = xsp; break; }
        }
        return false;
      }
    
      private boolean jj_3R_63()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_84()) {
        jj_scanpos = xsp;
        if (jj_3R_85()) {
        jj_scanpos = xsp;
        if (jj_3R_86()) {
        jj_scanpos = xsp;
        if (jj_3R_87()) {
        jj_scanpos = xsp;
        if (jj_3R_88()) {
        jj_scanpos = xsp;
        if (jj_3R_89()) {
        jj_scanpos = xsp;
        if (jj_3R_90()) {
        jj_scanpos = xsp;
        if (jj_3R_91()) {
        jj_scanpos = xsp;
        if (jj_3R_92()) {
        jj_scanpos = xsp;
        if (jj_3R_93()) {
        jj_scanpos = xsp;
        if (jj_3R_94()) {
        jj_scanpos = xsp;
        if (jj_3R_95()) {
        jj_scanpos = xsp;
        if (jj_3R_96()) {
        jj_scanpos = xsp;
        if (jj_3R_97()) {
        jj_scanpos = xsp;
        if (jj_3R_98()) return true;
        }
        }
        }
        }
        }
        }
        }
        }
        }
        }
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_61()
     {
        if (jj_scan_token(MINUS)) return true;
        return false;
      }
    
      private boolean jj_3R_50()
     {
        if (jj_3R_26()) return true;
        return false;
      }
    
      private boolean jj_3R_49()
     {
        if (jj_3R_65()) return true;
        return false;
      }
    
      private boolean jj_3R_48()
     {
        if (jj_3R_64()) return true;
        return false;
      }
    
      private boolean jj_3R_47()
     {
        if (jj_3R_63()) return true;
        return false;
      }
    
      private boolean jj_3R_25()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_47()) {
        jj_scanpos = xsp;
        if (jj_3R_48()) {
        jj_scanpos = xsp;
        if (jj_3R_49()) {
        jj_scanpos = xsp;
        if (jj_3R_50()) return true;
        }
        }
        }
        return false;
      }
    
      private boolean jj_3_12()
     {
        if (jj_3R_25()) return true;
        return false;
      }
    
      private boolean jj_3R_45()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(9)) {
        jj_scanpos = xsp;
        if (jj_3R_61()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_32()
     {
        if (jj_3R_14()) return true;
        if (jj_scan_token(DOT)) return true;
        return false;
      }
    
      private boolean jj_3R_137()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(11)) {
        jj_scanpos = xsp;
        if (jj_scan_token(12)) return true;
        }
        if (jj_3R_130()) return true;
        return false;
      }
    
      private boolean jj_3R_24()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_45()) jj_scanpos = xsp;
        xsp = jj_scanpos;
        if (jj_3_12()) {
        jj_scanpos = xsp;
        if (jj_3R_46()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_15()
     {
        if (jj_3R_14()) return true;
        if (jj_scan_token(DOT)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_32()) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3R_77()
     {
        if (jj_scan_token(COORDSYS)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_119()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_145()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_143()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_140()
     {
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        return false;
      }
    
      private boolean jj_3R_131()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(9)) {
        jj_scanpos = xsp;
        if (jj_scan_token(10)) return true;
        }
        if (jj_3R_112()) return true;
        return false;
      }
    
      private boolean jj_3R_59()
     {
        if (jj_scan_token(POINT)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_138()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_130()
     {
        if (jj_3R_24()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_137()) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3R_42()
     {
        if (jj_scan_token(REGION)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_29()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_19()
     {
        if (jj_3R_24()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(9)) {
        jj_scanpos = xsp;
        if (jj_scan_token(10)) {
        jj_scanpos = xsp;
        if (jj_scan_token(11)) {
        jj_scanpos = xsp;
        if (jj_scan_token(12)) return true;
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_20()
     {
        if (jj_3R_36()) return true;
        if (jj_scan_token(CONCAT)) return true;
        return false;
      }
    
      private boolean jj_3_1()
     {
        if (jj_3R_14()) return true;
        if (jj_scan_token(DOT)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_15()) jj_scanpos = xsp;
        if (jj_scan_token(ASTERISK)) return true;
        return false;
      }
    
      private boolean jj_3R_41()
     {
        if (jj_scan_token(POLYGON)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_138()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        Token xsp;
        while (true) {
          xsp = jj_scanpos;
          if (jj_3R_140()) { jj_scanpos = xsp; break; }
        }
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_72()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_40()
     {
        if (jj_3R_59()) return true;
        return false;
      }
    
      private boolean jj_3_10()
     {
        if (jj_3R_23()) return true;
        return false;
      }
    
      private boolean jj_3R_112()
     {
        if (jj_3R_130()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_131()) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3_9()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3_7()
     {
        if (jj_scan_token(REGULAR_IDENTIFIER_CANDIDATE)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3_6()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_39()
     {
        if (jj_scan_token(CIRCLE)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_138()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3_5()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(66)) {
        jj_scanpos = xsp;
        if (jj_3R_20()) return true;
        }
        return false;
      }
    
      private boolean jj_3_4()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_18()) {
        jj_scanpos = xsp;
        if (jj_3R_19()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_18()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(9)) {
        jj_scanpos = xsp;
        if (jj_scan_token(10)) return true;
        }
        return false;
      }
    
      private boolean jj_3R_38()
     {
        if (jj_scan_token(CENTROID)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_119()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3_11()
     {
        if (jj_3R_24()) return true;
        return false;
      }
    
      private boolean jj_3R_71()
     {
        if (jj_3R_36()) return true;
        return false;
      }
    
      private boolean jj_3R_70()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3_8()
     {
        if (jj_3R_21()) return true;
        return false;
      }
    
      private boolean jj_3R_69()
     {
        if (jj_3R_26()) return true;
        return false;
      }
    
      private boolean jj_3R_68()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_51()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_37()
     {
        if (jj_scan_token(BOX)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_138()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_139()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_67()
     {
        if (jj_3R_29()) return true;
        return false;
      }
    
      private boolean jj_3R_66()
     {
        if (jj_3R_112()) return true;
        return false;
      }
    
      private boolean jj_3R_152()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_125()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_51()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_144()
     {
        if (jj_3R_59()) return true;
        return false;
      }
    
      private boolean jj_3R_21()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_37()) {
        jj_scanpos = xsp;
        if (jj_3R_38()) {
        jj_scanpos = xsp;
        if (jj_3R_39()) {
        jj_scanpos = xsp;
        if (jj_3R_40()) {
        jj_scanpos = xsp;
        if (jj_3R_41()) {
        jj_scanpos = xsp;
        if (jj_3R_42()) return true;
        }
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_148()
     {
        if (jj_3R_51()) return true;
        return false;
      }
    
      private boolean jj_3R_142()
     {
        if (jj_3R_59()) return true;
        return false;
      }
    
      private boolean jj_3R_124()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_51()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_66()) {
        jj_scanpos = xsp;
        if (jj_3R_67()) {
        jj_scanpos = xsp;
        if (jj_3R_68()) {
        jj_scanpos = xsp;
        if (jj_3R_69()) {
        jj_scanpos = xsp;
        if (jj_3_8()) {
        jj_scanpos = xsp;
        if (jj_3R_70()) {
        jj_scanpos = xsp;
        if (jj_3R_71()) {
        jj_scanpos = xsp;
        if (jj_3_11()) {
        jj_scanpos = xsp;
        if (jj_3R_72()) return true;
        }
        }
        }
        }
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_147()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_123()
     {
        if (jj_3R_129()) return true;
        return false;
      }
    
      private boolean jj_3R_151()
     {
        if (jj_3R_59()) return true;
        return false;
      }
    
      private boolean jj_3R_138()
     {
        if (jj_3R_29()) return true;
        return false;
      }
    
      private boolean jj_3R_122()
     {
        if (jj_3R_128()) return true;
        return false;
      }
    
      private boolean jj_3R_121()
     {
        if (jj_3R_23()) return true;
        return false;
      }
    
      private boolean jj_3R_53()
     {
        if (jj_scan_token(SELECT)) return true;
        return false;
      }
    
      private boolean jj_3R_115()
     {
        if (jj_scan_token(FULL)) return true;
        return false;
      }
    
      private boolean jj_3R_146()
     {
        if (jj_3R_59()) return true;
        return false;
      }
    
      private boolean jj_3R_16()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_33()) return true;
        return false;
      }
    
      private boolean jj_3R_83()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_112()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_82()
     {
        if (jj_3R_129()) return true;
        return false;
      }
    
      private boolean jj_3R_78()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_121()) {
        jj_scanpos = xsp;
        if (jj_3R_122()) {
        jj_scanpos = xsp;
        if (jj_3R_123()) {
        jj_scanpos = xsp;
        if (jj_3R_124()) {
        jj_scanpos = xsp;
        if (jj_3R_125()) return true;
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_81()
     {
        if (jj_3R_22()) return true;
        return false;
      }
    
      private boolean jj_3R_80()
     {
        if (jj_3R_128()) return true;
        return false;
      }
    
      private boolean jj_3R_111()
     {
        if (jj_scan_token(DISTANCE)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_146()) {
        jj_scanpos = xsp;
        if (jj_3R_147()) return true;
        }
        if (jj_scan_token(COMMA)) return true;
        xsp = jj_scanpos;
        if (jj_3R_151()) {
        jj_scanpos = xsp;
        if (jj_3R_152()) return true;
        }
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_110()
     {
        if (jj_scan_token(COORD2)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_144()) {
        jj_scanpos = xsp;
        if (jj_3R_145()) return true;
        }
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_109()
     {
        if (jj_scan_token(COORD1)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_142()) {
        jj_scanpos = xsp;
        if (jj_3R_143()) return true;
        }
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_108()
     {
        if (jj_scan_token(AREA)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_119()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_118()
     {
        if (jj_scan_token(FULL)) return true;
        return false;
      }
    
      private boolean jj_3R_62()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_80()) {
        jj_scanpos = xsp;
        if (jj_3R_81()) {
        jj_scanpos = xsp;
        if (jj_3R_82()) {
        jj_scanpos = xsp;
        if (jj_3R_83()) return true;
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_107()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(61)) {
        jj_scanpos = xsp;
        if (jj_scan_token(62)) return true;
        }
        if (jj_scan_token(LEFT_PAR)) return true;
        if (jj_3R_119()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_119()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_33()
     {
        if (jj_3R_53()) return true;
        return false;
      }
    
      private boolean jj_3R_114()
     {
        if (jj_scan_token(RIGHT)) return true;
        return false;
      }
    
      private boolean jj_3R_154()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(9)) {
        jj_scanpos = xsp;
        if (jj_scan_token(10)) return true;
        }
        return false;
      }
    
      private boolean jj_3R_153()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_154()) jj_scanpos = xsp;
        if (jj_scan_token(UNSIGNED_INTEGER)) return true;
        return false;
      }
    
      private boolean jj_3R_65()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_107()) {
        jj_scanpos = xsp;
        if (jj_3R_108()) {
        jj_scanpos = xsp;
        if (jj_3R_109()) {
        jj_scanpos = xsp;
        if (jj_3R_110()) {
        jj_scanpos = xsp;
        if (jj_3R_111()) return true;
        }
        }
        }
        }
        return false;
      }
    
      private boolean jj_3R_139()
     {
        if (jj_3R_112()) return true;
        if (jj_scan_token(COMMA)) return true;
        if (jj_3R_112()) return true;
        return false;
      }
    
      private boolean jj_3R_136()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(50)) {
        jj_scanpos = xsp;
        if (jj_scan_token(51)) {
        jj_scanpos = xsp;
        if (jj_scan_token(52)) {
        jj_scanpos = xsp;
        if (jj_scan_token(53)) return true;
        }
        }
        }
        if (jj_scan_token(LEFT_PAR)) return true;
        xsp = jj_scanpos;
        if (jj_scan_token(20)) jj_scanpos = xsp;
        if (jj_3R_51()) return true;
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_135()
     {
        if (jj_scan_token(COUNT)) return true;
        if (jj_scan_token(LEFT_PAR)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(20)) jj_scanpos = xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(11)) {
        jj_scanpos = xsp;
        if (jj_3R_148()) return true;
        }
        if (jj_scan_token(RIGHT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3R_117()
     {
        if (jj_scan_token(RIGHT)) return true;
        return false;
      }
    
      private boolean jj_3R_128()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(95)) {
        jj_scanpos = xsp;
        if (jj_scan_token(96)) {
        jj_scanpos = xsp;
        if (jj_scan_token(97)) return true;
        }
        }
        return false;
      }
    
      private boolean jj_3R_129()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_135()) {
        jj_scanpos = xsp;
        if (jj_3R_136()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_113()
     {
        if (jj_scan_token(LEFT)) return true;
        return false;
      }
    
      private boolean jj_3R_73()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_113()) {
        jj_scanpos = xsp;
        if (jj_3R_114()) {
        jj_scanpos = xsp;
        if (jj_3R_115()) return true;
        }
        }
        return false;
      }
    
      private boolean jj_3R_54()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(26)) {
        jj_scanpos = xsp;
        if (jj_3R_73()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_44()
     {
        if (jj_scan_token(STRING_LITERAL)) return true;
        return false;
      }
    
      private boolean jj_3R_23()
     {
        Token xsp;
        if (jj_3R_44()) return true;
        while (true) {
          xsp = jj_scanpos;
          if (jj_3R_44()) { jj_scanpos = xsp; break; }
        }
        return false;
      }
    
      private boolean jj_3R_116()
     {
        if (jj_scan_token(LEFT)) return true;
        return false;
      }
    
      private boolean jj_3R_74()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_116()) {
        jj_scanpos = xsp;
        if (jj_3R_117()) {
        jj_scanpos = xsp;
        if (jj_3R_118()) return true;
        }
        }
        xsp = jj_scanpos;
        if (jj_scan_token(27)) jj_scanpos = xsp;
        return false;
      }
    
      private boolean jj_3_18()
     {
        if (jj_3R_16()) return true;
        return false;
      }
    
      private boolean jj_3R_55()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(26)) {
        jj_scanpos = xsp;
        if (jj_3R_74()) return true;
        }
        return false;
      }
    
      private boolean jj_3R_35()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_55()) jj_scanpos = xsp;
        if (jj_scan_token(JOIN)) return true;
        if (jj_3R_56()) return true;
        return false;
      }
    
      private boolean jj_3R_34()
     {
        if (jj_scan_token(NATURAL)) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_54()) jj_scanpos = xsp;
        if (jj_scan_token(JOIN)) return true;
        return false;
      }
    
      private boolean jj_3R_28()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(37)) jj_scanpos = xsp;
        if (jj_scan_token(BETWEEN)) return true;
        if (jj_3R_51()) return true;
        return false;
      }
    
      private boolean jj_3_15()
     {
        if (jj_3R_28()) return true;
        return false;
      }
    
      private boolean jj_3R_17()
     {
        Token xsp;
        xsp = jj_scanpos;
        if (jj_3R_34()) {
        jj_scanpos = xsp;
        if (jj_3R_35()) return true;
        }
        return false;
      }
    
      private boolean jj_3_17()
     {
        if (jj_3R_29()) return true;
        Token xsp;
        xsp = jj_scanpos;
        if (jj_scan_token(37)) jj_scanpos = xsp;
        if (jj_scan_token(LIKE)) return true;
        return false;
      }
    
      private boolean jj_3R_76()
     {
        if (jj_scan_token(LEFT_PAR)) return true;
        return false;
      }
    
      private boolean jj_3_3()
     {
        if (jj_3R_17()) return true;
        return false;
      }
    
      private boolean jj_3_16()
     {
        if (jj_3R_22()) return true;
        if (jj_scan_token(IS)) return true;
        return false;
      }
    
      /** Generated Token Manager. */
      public ADQLParserTokenManager token_source;
      SimpleCharStream jj_input_stream;
      /** Current token. */
      public Token token;
      /** Next token. */
      public Token jj_nt;
      private int jj_ntk;
      private Token jj_scanpos, jj_lastpos;
      private int jj_la;
      private int jj_gen;
      final private int[] jj_la1 = new int[98];
      static private int[] jj_la1_0;
      static private int[] jj_la1_1;
      static private int[] jj_la1_2;
      static private int[] jj_la1_3;
      static {
          jj_la1_init_0();
          jj_la1_init_1();
          jj_la1_init_2();
          jj_la1_init_3();
       }
       private static void jj_la1_init_0() {
          jj_la1_0 = new int[] {0x81,0x0,0x0,0x0,0x0,0x100000,0x200000,0x400000,0x40,0x0,0x0,0x1000000,0x1000000,0x800,0x608,0x40,0x40,0x40,0x0,0x20,0x20,0x20,0x0,0x0,0x0,0x1000000,0x1000000,0x1000000,0x0,0x8,0xf6000000,0x70000000,0x8000000,0x74000000,0x74000000,0x70000000,0x8000000,0x74000000,0x74000000,0x40,0x0,0xf6000000,0x0,0x0,0x0,0x600,0x600,0x8,0x8,0x0,0x600,0x600,0x1800,0x1800,0x600,0x600,0x8,0x100,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x7e000,0x0,0x0,0x608,0x7e000,0x0,0x0,0x40,0x8,0x100000,0xe08,0x0,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x0,0x608,0x40,0x40,0x0,0x0,0x40,0x608,};
       }
       private static void jj_la1_init_1() {
          jj_la1_1 = new int[] {0x0,0x4,0x2000,0x4000,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfffc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000,0x30000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0000,0x7c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0000,0x0,0x0,0x7c0000,0x1f800000,0x20,0x18,0x18,0x20,0x0,0x20,0x20,0x0,0x420,0x800,0xfffc0000,0x0,0x20,0x20,0x0,0x0,0x0,0xfffc0000,0x3c0000,0x0,0x7c0000,0x60000000,0x4000000,0x4000000,0x4000000,0x4000000,0xe0000000,0x0,0x1f800000,0xe0000000,0xe07c0000,0x0,0x0,0x0,0x0,0x0,0xfffc0000,};
       }
       private static void jj_la1_init_2() {
          jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc7ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000,0x80000000,0x0,0x0,0x0,0x80000000,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000000,0x0,0x4,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc7ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0xc7ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb,0x0,0x0,0x7fffffb,0x87fffffb,0x0,0x0,0x7fff0,0x7f80000,0x0,0xc7ffffff,};
       }
       private static void jj_la1_init_3() {
          jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60,0x60,0x0,0x60,0x0,0x63,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x62,0x0,0x0,0x0,0x60,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x0,0x0,0x63,0x63,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x63,0x0,0x0,0x63,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x63,0x0,0x0,0x0,0x0,0x0,0x0,0x63,0x0,0x0,0x0,0x0,0x60,0x60,0x60,0x60,0x0,0x0,0x0,0x40,0x63,0x0,0x0,0x0,0x0,0x0,0x63,};
       }
      final private JJCalls[] jj_2_rtns = new JJCalls[18];
      private boolean jj_rescan = false;
      private int jj_gc = 0;
    
      /** Constructor with InputStream. */
      public ADQLParser(java.io.InputStream stream) {
         this(stream, (String) null);
      }
      /** Constructor with InputStream and supplied encoding */
      public ADQLParser(java.io.InputStream stream, String encoding) {
        try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
        token_source = new ADQLParserTokenManager(jj_input_stream);
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      /** Reinitialise. */
      public void ReInit(java.io.InputStream stream) {
         ReInit(stream, null);
      }
      /** Reinitialise. */
      public void ReInit(java.io.InputStream stream, String encoding) {
        try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
        token_source.ReInit(jj_input_stream);
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      /** Constructor. */
      public ADQLParser(java.io.Reader stream) {
        jj_input_stream = new SimpleCharStream(stream, 1, 1);
        token_source = new ADQLParserTokenManager(jj_input_stream);
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      /** Reinitialise. */
      public void ReInit(java.io.Reader stream) {
        jj_input_stream.ReInit(stream, 1, 1);
        token_source.ReInit(jj_input_stream);
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      /** Constructor with generated Token Manager. */
      public ADQLParser(ADQLParserTokenManager tm) {
        token_source = tm;
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      /** Reinitialise. */
      public void ReInit(ADQLParserTokenManager tm) {
        token_source = tm;
        token = new Token();
        jj_ntk = -1;
        jj_gen = 0;
        for (int i = 0; i < 98; i++) jj_la1[i] = -1;
        for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
      }
    
      private Token jj_consume_token(int kind) throws ParseException {
        Token oldToken;
        if ((oldToken = token).next != null) token = token.next;
        else token = token.next = token_source.getNextToken();
        jj_ntk = -1;
        if (token.kind == kind) {
          jj_gen++;
          if (++jj_gc > 100) {
            jj_gc = 0;
            for (int i = 0; i < jj_2_rtns.length; i++) {
              JJCalls c = jj_2_rtns[i];
              while (c != null) {
                if (c.gen < jj_gen) c.first = null;
                c = c.next;
              }
            }
          }
          trace_token(token, "");
          return token;
        }
        token = oldToken;
        jj_kind = kind;
        throw generateParseException();
      }
    
      @SuppressWarnings("serial")
      static private final class LookaheadSuccess extends java.lang.Error { }
      final private LookaheadSuccess jj_ls = new LookaheadSuccess();
      private boolean jj_scan_token(int kind) {
        if (jj_scanpos == jj_lastpos) {
          jj_la--;
          if (jj_scanpos.next == null) {
            jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
          } else {
            jj_lastpos = jj_scanpos = jj_scanpos.next;
          }
        } else {
          jj_scanpos = jj_scanpos.next;
        }
        if (jj_rescan) {
          int i = 0; Token tok = token;
          while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
          if (tok != null) jj_add_error_token(kind, i);
        }
        if (jj_scanpos.kind != kind) return true;
        if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
        return false;
      }
    
    
    /** Get the next Token. */
      final public Token getNextToken() {
        if (token.next != null) token = token.next;
        else token = token.next = token_source.getNextToken();
        jj_ntk = -1;
        jj_gen++;
          trace_token(token, " (in getNextToken)");
        return token;
      }
    
    /** Get the specific Token. */
      final public Token getToken(int index) {
        Token t = token;
        for (int i = 0; i < index; i++) {
          if (t.next != null) t = t.next;
          else t = t.next = token_source.getNextToken();
        }
        return t;
      }
    
      private int jj_ntk_f() {
        if ((jj_nt=token.next) == null)
          return (jj_ntk = (token.next=token_source.getNextToken()).kind);
        else
          return (jj_ntk = jj_nt.kind);
      }
    
      private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
      private int[] jj_expentry;
      private int jj_kind = -1;
      private int[] jj_lasttokens = new int[100];
      private int jj_endpos;
    
      private void jj_add_error_token(int kind, int pos) {
        if (pos >= 100) return;
        if (pos == jj_endpos + 1) {
          jj_lasttokens[jj_endpos++] = kind;
        } else if (jj_endpos != 0) {
          jj_expentry = new int[jj_endpos];
          for (int i = 0; i < jj_endpos; i++) {
            jj_expentry[i] = jj_lasttokens[i];
          }
          jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
            int[] oldentry = (int[])(it.next());
            if (oldentry.length == jj_expentry.length) {
              for (int i = 0; i < jj_expentry.length; i++) {
                if (oldentry[i] != jj_expentry[i]) {
                  continue jj_entries_loop;
                }
              }
              jj_expentries.add(jj_expentry);
              break jj_entries_loop;
            }
          }
          if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
        }
      }
    
      /** Generate ParseException. */
      public ParseException generateParseException() {
        jj_expentries.clear();
        boolean[] la1tokens = new boolean[104];
        if (jj_kind >= 0) {
          la1tokens[jj_kind] = true;
          jj_kind = -1;
        }
        for (int i = 0; i < 98; i++) {
          if (jj_la1[i] == jj_gen) {
            for (int j = 0; j < 32; j++) {
              if ((jj_la1_0[i] & (1<<j)) != 0) {
                la1tokens[j] = true;
              }
              if ((jj_la1_1[i] & (1<<j)) != 0) {
                la1tokens[32+j] = true;
              }
              if ((jj_la1_2[i] & (1<<j)) != 0) {
                la1tokens[64+j] = true;
              }
              if ((jj_la1_3[i] & (1<<j)) != 0) {
                la1tokens[96+j] = true;
              }
            }
          }
        }
        for (int i = 0; i < 104; i++) {
          if (la1tokens[i]) {
            jj_expentry = new int[1];
            jj_expentry[0] = i;
            jj_expentries.add(jj_expentry);
          }
        }
        jj_endpos = 0;
        jj_rescan_token();
        jj_add_error_token(0, 0);
        int[][] exptokseq = new int[jj_expentries.size()][];
        for (int i = 0; i < jj_expentries.size(); i++) {
          exptokseq[i] = jj_expentries.get(i);
        }
        return new ParseException(token, exptokseq, tokenImage);
      }
    
      private int trace_indent = 0;
      private boolean trace_enabled = true;
    
    /** Enable tracing. */
      final public void enable_tracing() {
        trace_enabled = true;
      }
    
    /** Disable tracing. */
      final public void disable_tracing() {
        trace_enabled = false;
      }
    
      private void trace_call(String s) {
        if (trace_enabled) {
          for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
          System.out.println("Call:   " + s);
        }
        trace_indent = trace_indent + 2;
      }
    
      private void trace_return(String s) {
        trace_indent = trace_indent - 2;
        if (trace_enabled) {
          for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
          System.out.println("Return: " + s);
        }
      }
    
      private void trace_token(Token t, String where) {
        if (trace_enabled) {
          for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
          System.out.print("Consumed token: <" + tokenImage[t.kind]);
          if (t.kind != 0 && !tokenImage[t.kind].equals("\"" + t.image + "\"")) {
            System.out.print(": \"" + t.image + "\"");
          }
          System.out.println(" at line " + t.beginLine + " column " + t.beginColumn + ">" + where);
        }
      }
    
      private void trace_scan(Token t1, int t2) {
        if (trace_enabled) {
          for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
          System.out.print("Visited token: <" + tokenImage[t1.kind]);
          if (t1.kind != 0 && !tokenImage[t1.kind].equals("\"" + t1.image + "\"")) {
            System.out.print(": \"" + t1.image + "\"");
          }
          System.out.println(" at line " + t1.beginLine + " column " + t1.beginColumn + ">; Expected token: <" + tokenImage[t2] + ">");
        }
      }
    
      private void jj_rescan_token() {
        jj_rescan = true;
        for (int i = 0; i < 18; i++) {
        try {
          JJCalls p = jj_2_rtns[i];
          do {
            if (p.gen > jj_gen) {
              jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
              switch (i) {
                case 0: jj_3_1(); break;
                case 1: jj_3_2(); break;
                case 2: jj_3_3(); break;
                case 3: jj_3_4(); break;
                case 4: jj_3_5(); break;
                case 5: jj_3_6(); break;
                case 6: jj_3_7(); break;
                case 7: jj_3_8(); break;
                case 8: jj_3_9(); break;
                case 9: jj_3_10(); break;
                case 10: jj_3_11(); break;
                case 11: jj_3_12(); break;
                case 12: jj_3_13(); break;
                case 13: jj_3_14(); break;
                case 14: jj_3_15(); break;
                case 15: jj_3_16(); break;
                case 16: jj_3_17(); break;
                case 17: jj_3_18(); break;
              }
            }
            p = p.next;
          } while (p != null);
          } catch(LookaheadSuccess ls) { }
        }
        jj_rescan = false;
      }
    
      private void jj_save(int index, int xla) {
        JJCalls p = jj_2_rtns[index];
        while (p.gen > jj_gen) {
          if (p.next == null) { p = p.next = new JJCalls(); break; }
          p = p.next;
        }
        p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
      }
    
      static final class JJCalls {
        int gen;
        Token first;
        int arg;
        JJCalls next;
      }
    
    }