diff --git a/src/adql/db/DBChecker.java b/src/adql/db/DBChecker.java
index 5aeefc40a8375461df296db9e9205bba71c61db6..05c3b005c57202da8cf0f9fab44c963cdadf62b1 100644
--- a/src/adql/db/DBChecker.java
+++ b/src/adql/db/DBChecker.java
@@ -97,7 +97,7 @@ import adql.search.SimpleSearchHandler;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (05/2015)
+ * @version 1.4 (06/2015)
  */
 public class DBChecker implements QueryChecker {
 
@@ -215,8 +215,8 @@ public class DBChecker implements QueryChecker {
 					tmp[cnt++] = udf;
 			}
 			// make a copy of the array:
-                        this.allowedUdfs = new FunctionDef[cnt];
-                        System.arraycopy(tmp, 0, this.allowedUdfs, 0, cnt);
+			this.allowedUdfs = new FunctionDef[cnt];
+			System.arraycopy(tmp, 0, this.allowedUdfs, 0, cnt);
 
 			tmp = null;
 			// sort the values:
@@ -321,7 +321,7 @@ public class DBChecker implements QueryChecker {
 
 		// Make an adjusted array copy:
 		String[] copy = new String[cnt];
-                System.arraycopy(tmp, 0, copy, 0, cnt);
+		System.arraycopy(tmp, 0, copy, 0, cnt);
 
 		// Sort the values:
 		Arrays.sort(copy);
@@ -819,7 +819,7 @@ public class DBChecker implements QueryChecker {
 				if (match < 0){
 					// ...if the type of all parameters is resolved, add an error (no match is possible):
 					if (isAllParamTypesResolved(udf))
-						errors.addException(new UnresolvedFunctionException(udf));	// TODO Add the ADQLOperand position!
+						errors.addException(new UnresolvedFunctionException(udf));
 					// ...otherwise, try to resolved it later (when other UDFs will be mostly resolved):
 					else
 						toResolveLater.add(udf);
@@ -836,7 +836,7 @@ public class DBChecker implements QueryChecker {
 				match = binSearch.search(udf, allowedUdfs);
 				// if no match, add an error:
 				if (match < 0)
-					errors.addException(new UnresolvedFunctionException(udf));	// TODO Add the ADQLOperand position!
+					errors.addException(new UnresolvedFunctionException(udf));
 				// otherwise, metadata may be attached (particularly if the function is built automatically by the syntactic parser):
 				else if (udf instanceof DefaultUDF)
 					((DefaultUDF)udf).setDefinition(allowedUdfs[match]);
@@ -1003,7 +1003,7 @@ public class DBChecker implements QueryChecker {
 		try{
 			checkCoordinateSystem(STCS.parseCoordSys(coordSysStr), adqlCoordSys, errors);
 		}catch(ParseException pe){
-			errors.addException(new ParseException(pe.getMessage())); // TODO Missing object position!
+			errors.addException(new ParseException(pe.getMessage(), adqlCoordSys.getPosition()));
 		}
 	}
 
@@ -1017,8 +1017,21 @@ public class DBChecker implements QueryChecker {
 	 * @since 1.3
 	 */
 	protected void checkCoordinateSystem(final CoordSys coordSys, final ADQLOperand operand, final UnresolvedIdentifiersException errors){
-		if (coordSysRegExp != null && coordSys != null && !coordSys.toFullSTCS().matches(coordSysRegExp))
-			errors.addException(new ParseException("Coordinate system \"" + ((operand instanceof StringConstant) ? ((StringConstant)operand).getValue() : coordSys.toString()) + "\" (= \"" + coordSys.toFullSTCS() + "\") not allowed in this implementation."));	// TODO Missing object position! + List of accepted coordinate systems
+		if (coordSysRegExp != null && coordSys != null && !coordSys.toFullSTCS().matches(coordSysRegExp)){
+			StringBuffer buf = new StringBuffer();
+			if (allowedCoordSys != null){
+				for(String cs : allowedCoordSys){
+					if (buf.length() > 0)
+						buf.append(", ");
+					buf.append(cs);
+				}
+			}
+			if (buf.length() == 0)
+				buf.append("No coordinate system is allowed!");
+			else
+				buf.insert(0, "Allowed coordinate systems are: ");
+			errors.addException(new ParseException("Coordinate system \"" + ((operand instanceof StringConstant) ? ((StringConstant)operand).getValue() : coordSys.toString()) + "\" (= \"" + coordSys.toFullSTCS() + "\") not allowed in this implementation. " + buf.toString(), operand.getPosition()));
+		}
 	}
 
 	/**
@@ -1060,7 +1073,7 @@ public class DBChecker implements QueryChecker {
 				// check whether the regions (this one + the possible inner ones) and the coordinate systems are allowed:
 				checkRegion(region, (RegionFunction)result, binSearch, errors);
 			}catch(ParseException pe){
-				errors.addException(new ParseException(pe.getMessage())); // TODO Missing object position!
+				errors.addException(new ParseException(pe.getMessage(), result.getPosition()));
 			}
 		}
 	}
@@ -1155,17 +1168,17 @@ public class DBChecker implements QueryChecker {
 				case 'G':
 				case 'g':
 					if (!unknown.isGeometry())
-						errors.addException(new ParseException("Type mismatch! A geometry was expected instead of \"" + unknown.toADQL() + "\"."));	// TODO Add the ADQLOperand position!
+						errors.addException(new ParseException("Type mismatch! A geometry was expected instead of \"" + unknown.toADQL() + "\".", result.getPosition()));
 					break;
 				case 'N':
 				case 'n':
 					if (!unknown.isNumeric())
-						errors.addException(new ParseException("Type mismatch! A numeric value was expected instead of \"" + unknown.toADQL() + "\"."));	// TODO Add the ADQLOperand position!
+						errors.addException(new ParseException("Type mismatch! A numeric value was expected instead of \"" + unknown.toADQL() + "\".", result.getPosition()));
 					break;
 				case 'S':
 				case 's':
 					if (!unknown.isString())
-						errors.addException(new ParseException("Type mismatch! A string value was expected instead of \"" + unknown.toADQL() + "\"."));	// TODO Add the ADQLOperand position!
+						errors.addException(new ParseException("Type mismatch! A string value was expected instead of \"" + unknown.toADQL() + "\".", result.getPosition()));
 					break;
 			}
 		}
diff --git a/src/adql/db/STCS.java b/src/adql/db/STCS.java
index 716ef580fee037003b78b52d33fb75a183732fa8..b0befa1c724e886196a4a7f7d2b375981b3783df 100644
--- a/src/adql/db/STCS.java
+++ b/src/adql/db/STCS.java
@@ -1395,7 +1395,7 @@ public final class STCS {
 			if (nextToken().matches(numericRegExp))
 				return Double.parseDouble(token);
 			else
-				throw new ParseException("a numeric was expected!", new TextPosition(1, pos - token.length(), 1, pos));	// TODO Check the begin and end!
+				throw new ParseException("a numeric was expected!", new TextPosition(1, pos - token.length(), 1, pos));
 		}
 
 		/**
@@ -1415,7 +1415,7 @@ public final class STCS {
 				if (pe instanceof EOEException)
 					throw pe;
 				else
-					throw new ParseException("a coordinates pair (2 numerics separated by one or more spaces) was expected!", new TextPosition(1, startPos, 1, pos));	// TODO Check the begin and end!
+					throw new ParseException("a coordinates pair (2 numerics separated by one or more spaces) was expected!", new TextPosition(1, startPos, 1, pos));
 			}
 		}
 
diff --git a/src/adql/db/exception/UnresolvedFunctionException.java b/src/adql/db/exception/UnresolvedFunctionException.java
index befb5565061b0b9997916427e3cdba020eaf086b..4551159de43181a7323be4d509d600b1384669e7 100644
--- a/src/adql/db/exception/UnresolvedFunctionException.java
+++ b/src/adql/db/exception/UnresolvedFunctionException.java
@@ -20,13 +20,14 @@ package adql.db.exception;
  */
 
 import adql.parser.ParseException;
+import adql.query.TextPosition;
 import adql.query.operand.function.ADQLFunction;
 
 /**
  * Exception thrown when a function can not be resolved by the library.
  * 
  * @author Gr&eacute;gory Mantelet (ARI)
- * @version 1.3 (05/2015)
+ * @version 1.4 (06/2015)
  * @since 1.3
  */
 public class UnresolvedFunctionException extends ParseException {
@@ -41,7 +42,19 @@ public class UnresolvedFunctionException extends ParseException {
 	 * @param message	Description of the error.
 	 */
 	public UnresolvedFunctionException(final String message){
-		super(message);
+		this(message, (TextPosition)null);
+	}
+
+	/**
+	 * Build the exception with just a message.
+	 * 
+	 * @param message	Description of the error.
+	 * @param pos		Position of the unresolved function inside the ADQL query.
+	 * 
+	 * @since 1.4
+	 */
+	public UnresolvedFunctionException(final String message, final TextPosition pos){
+		super(message, pos);
 		functionInError = null;
 	}
 
@@ -52,7 +65,7 @@ public class UnresolvedFunctionException extends ParseException {
 	 * @param fct	The unresolved function.
 	 */
 	public UnresolvedFunctionException(final ADQLFunction fct){
-		super("Unresolved function: \"" + fct.toADQL() + "\"! No UDF has been defined or found with the signature: " + getFctSignature(fct) + "."); // TODO Add the position of the function in the ADQL query!
+		super("Unresolved function: \"" + fct.toADQL() + "\"! No UDF has been defined or found with the signature: " + getFctSignature(fct) + ".", fct.getPosition());
 		functionInError = fct;
 	}
 
@@ -64,7 +77,7 @@ public class UnresolvedFunctionException extends ParseException {
 	 * @param fct		The unresolved function.
 	 */
 	public UnresolvedFunctionException(final String message, final ADQLFunction fct){
-		super(message); // TODO Add the position of the function in the ADQL query!
+		super(message, (fct == null) ? null : fct.getPosition());
 		functionInError = fct;
 	}
 
diff --git a/src/adql/db/exception/UnresolvedIdentifiersException.java b/src/adql/db/exception/UnresolvedIdentifiersException.java
index 7a7ef3be0db7612f6d2cbacedae1224aa3c44f05..91ca1bc11e88c3feafa5813c115c80add35e8f8c 100644
--- a/src/adql/db/exception/UnresolvedIdentifiersException.java
+++ b/src/adql/db/exception/UnresolvedIdentifiersException.java
@@ -38,7 +38,7 @@ import adql.parser.ParseException;
  * </p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (04/2015)
+ * @version 1.4 (06/2015)
  * 
  * @see DBChecker
  */
@@ -66,16 +66,16 @@ public class UnresolvedIdentifiersException extends ParseException implements It
 			exceptions.add(pe);
 			if (pe instanceof UnresolvedColumnException){
 				String colName = ((UnresolvedColumnException)pe).getColumnName();
-				if (colName != null && colName.trim().length()>0)
+				if (colName != null && colName.trim().length() > 0)
 					addIdentifierName(colName + " " + pe.getPosition());
 			}else if (pe instanceof UnresolvedTableException){
 				String tableName = ((UnresolvedTableException)pe).getTableName();
-				if (tableName != null && tableName.trim().length()>0)
+				if (tableName != null && tableName.trim().length() > 0)
 					addIdentifierName(tableName + " " + pe.getPosition());
 			}else if (pe instanceof UnresolvedFunctionException){
 				String fctName = (((UnresolvedFunctionException)pe).getFunction() == null) ? null : ((UnresolvedFunctionException)pe).getFunction().getName() + "(...)";
-				if (fctName != null && fctName.trim().length()>0)
-					addIdentifierName(fctName /*+ " " + pe.getPosition()*/);	// TODO Add the position of the function in the ADQL query!
+				if (fctName != null && fctName.trim().length() > 0)
+					addIdentifierName(fctName + " " + pe.getPosition());
 			}else if (pe instanceof UnresolvedIdentifiersException)
 				addIdentifierName(((UnresolvedIdentifiersException)pe).unresolvedIdentifiers);
 		}
@@ -87,7 +87,7 @@ public class UnresolvedIdentifiersException extends ParseException implements It
 	 * @param name	Name (or description) of the identifier to add.
 	 */
 	private final void addIdentifierName(final String name){
-		if (name != null && name.trim().length()>0){
+		if (name != null && name.trim().length() > 0){
 			if (unresolvedIdentifiers == null)
 				unresolvedIdentifiers = "";
 			else
diff --git a/src/adql/db/exception/UnresolvedJoinException.java b/src/adql/db/exception/UnresolvedJoinException.java
index 162bcd03c05b07284b4e6387f1daa1b2da340f64..c73e464f3b367c1ed5fd4a95faaea19eadc96152 100644
--- a/src/adql/db/exception/UnresolvedJoinException.java
+++ b/src/adql/db/exception/UnresolvedJoinException.java
@@ -26,8 +26,8 @@ import adql.query.TextPosition;
  * This exception is thrown when a table between 2 tables can not be resolved,
  * and particularly because of the join condition (i.e. column names not found, ...).
  * 
- * @author Gr&eacute;gory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de
- * @version 1.3 (05/2015)
+ * @author Gr&eacute;gory Mantelet (ARI)
+ * @version 1.4 (06/2015)
  * @since 1.2
  */
 public class UnresolvedJoinException extends ParseException {
@@ -53,4 +53,15 @@ public class UnresolvedJoinException extends ParseException {
 		super(message, errorPosition);
 	}
 
+	/**
+	 * Set the position of the invalid JOIN.
+	 * 
+	 * @param pos	Position of the concerned JOIN inside the ADQL query.
+	 * 
+	 * @since 1.4
+	 */
+	public void setPosition(final TextPosition pos){
+		this.position = pos;
+	}
+
 }
diff --git a/src/adql/parser/ADQLParser.java b/src/adql/parser/ADQLParser.java
index c5833b4b09fd5f1a943ff4db2303d227d7d84540..80c3990169bc221aa59dbf115a59314770edf3f4 100644
--- a/src/adql/parser/ADQLParser.java
+++ b/src/adql/parser/ADQLParser.java
@@ -1,31 +1,53 @@
 /* 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 java.util.ArrayList;
+import java.util.Stack;
+import java.util.Vector;
 
 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.parser.IdentifierItems.IdentifierItem;
+import adql.query.ADQLOrder;
+import adql.query.ADQLQuery;
+import adql.query.ClauseADQL;
+import adql.query.ClauseConstraints;
+import adql.query.ClauseSelect;
+import adql.query.ColumnReference;
+import adql.query.SelectAllColumns;
+import adql.query.SelectItem;
+import adql.query.TextPosition;
+import adql.query.constraint.ADQLConstraint;
+import adql.query.constraint.Between;
+import adql.query.constraint.Comparison;
+import adql.query.constraint.ComparisonOperator;
+import adql.query.constraint.ConstraintsGroup;
+import adql.query.constraint.Exists;
+import adql.query.constraint.In;
+import adql.query.constraint.IsNull;
+import adql.query.constraint.NotConstraint;
+import adql.query.from.ADQLJoin;
+import adql.query.from.FromContent;
+import adql.query.operand.ADQLColumn;
+import adql.query.operand.ADQLOperand;
+import adql.query.operand.Concatenation;
+import adql.query.operand.NegativeOperand;
+import adql.query.operand.NumericConstant;
+import adql.query.operand.Operation;
+import adql.query.operand.OperationType;
+import adql.query.operand.StringConstant;
+import adql.query.operand.WrappedOperand;
+import adql.query.operand.function.ADQLFunction;
+import adql.query.operand.function.MathFunction;
+import adql.query.operand.function.MathFunctionType;
+import adql.query.operand.function.SQLFunction;
+import adql.query.operand.function.SQLFunctionType;
+import adql.query.operand.function.UserDefinedFunction;
+import adql.query.operand.function.geometry.GeometryFunction;
 import adql.query.operand.function.geometry.GeometryFunction.GeometryValue;
-
+import adql.query.operand.function.geometry.PointFunction;
 import adql.translator.PostgreSQLTranslator;
 import adql.translator.TranslationException;
 
@@ -49,101 +71,102 @@ import adql.translator.TranslationException;
 */
 public class ADQLParser implements ADQLParserConstants {
 
-        /** Tools to build the object representation of the ADQL query. */
-        private ADQLQueryFactory queryFactory = new ADQLQueryFactory();
+	/** 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 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;
+	/** 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 ADQLQuery (sub-query or not) just after their generation. */
-        private QueryChecker queryChecker = null;
+	/** Checks each 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;
+	/** 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);
-        }
+	public ADQLParser(){
+		this(new java.io.ByteArrayInputStream("".getBytes()));
+		setDebug(false);
+	}
 
-        /**
+	/**
 	* Builds an ADQL parser without a query to parse but with a QueryChecker and a ADQLQueryFactory.
 	*
 	* @param checker	The object to use to check each ADQLQuery.
 	* @param factory	The object to use to build an object representation of the given ADQL query.
 	*/
-        public ADQLParser(QueryChecker checker, ADQLQueryFactory factory) {
-                this();
+	public ADQLParser(QueryChecker checker, ADQLQueryFactory factory){
+		this();
 
-                queryChecker = checker;
+		queryChecker = checker;
 
-                if (factory != null)
-                        queryFactory = factory;
-        }
+		if (factory != null)
+			queryFactory = factory;
+	}
 
-        /**
+	/**
 	* Builds an ADQL parser without a query to parse but with a QueryChecker.
 	*
 	* @param checker	The object to use to check each ADQLQuery.
 	*/
-        public ADQLParser(QueryChecker checker) {
-                this(checker, null);
-        }
+	public ADQLParser(QueryChecker checker){
+		this(checker, null);
+	}
 
-        /**
+	/**
 	* Builds an ADQL parser without a query to parse but with a 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);
-        }
+	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 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);
+	public ADQLParser(java.io.InputStream stream, QueryChecker checker, ADQLQueryFactory factory){
+		this(stream);
+		setDebug(false);
 
-                setDebug(false);
+		setDebug(false);
 
-                queryChecker = checker;
+		queryChecker = checker;
 
-                if (factory != null)
-                        queryFactory = factory;
-        }
+		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 ADQLQuery.
 	*/
-        public ADQLParser(java.io.InputStream stream, QueryChecker checker) {
-                this(stream, checker, null);
-        }
+	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);
-        }
+	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.
@@ -151,114 +174,117 @@ public class ADQLParser implements ADQLParserConstants {
 	* @param checker		The object to use to check each 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);
+	public ADQLParser(java.io.InputStream stream, String encoding, QueryChecker checker, ADQLQueryFactory factory){
+		this(stream, encoding);
+		setDebug(false);
 
-                queryChecker = checker;
+		queryChecker = checker;
 
-                if (factory != null)
-                        queryFactory = factory;
-        }
+		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 ADQLQuery.
 	*/
-        public ADQLParser(java.io.InputStream stream, String encoding, QueryChecker checker) {
-                this(stream, encoding, checker, null);
-        }
+	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);
-        }
+	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 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);
+	public ADQLParser(java.io.Reader reader, QueryChecker checker, ADQLQueryFactory factory){
+		this(reader);
+		setDebug(false);
 
-                setDebug(false);
+		setDebug(false);
 
-                queryChecker = checker;
+		queryChecker = checker;
 
-                if (factory != null)
-                        queryFactory = factory;
-        }
+		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 ADQLQuery.
 	*/
-        public ADQLParser(java.io.Reader reader, QueryChecker checker) {
-                this(reader, checker, null);
-        }
+	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);
-        }
+	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 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);
+	public ADQLParser(ADQLParserTokenManager tm, QueryChecker checker, ADQLQueryFactory factory){
+		this(tm);
+		setDebug(false);
 
-                setDebug(false);
+		setDebug(false);
 
-                queryChecker = checker;
+		queryChecker = checker;
 
-                if (factory != null)
-                        queryFactory = factory;
-        }
+		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 ADQLQuery.
 	*/
-        public ADQLParser(ADQLParserTokenManager tm, QueryChecker checker) {
-                this(tm, checker, null);
-        }
+	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);
-        }
+	public ADQLParser(ADQLParserTokenManager tm, ADQLQueryFactory factory){
+		this(tm, null, factory);
+	}
 
-        /**
+	/**
 	* 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.
@@ -266,13 +292,13 @@ public class ADQLParser implements ADQLParserConstants {
 	*
 	* @see ADQLParser#Query()
 	*/
-        public final ADQLQuery parseQuery() throws ParseException {
-                stackQuery.clear();
-                query = null;
-                return Query();
-        }
+	public final ADQLQuery parseQuery() throws ParseException{
+		stackQuery.clear();
+		query = null;
+		return Query();
+	}
 
-        /**
+	/**
 	* Parses the query given in parameter.
 	*
 	* @param q					The ADQL query to parse.
@@ -283,14 +309,14 @@ public class ADQLParser implements ADQLParserConstants {
 	* @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()));
-                return Query();
-        }
-
-        /**
+	public final ADQLQuery parseQuery(String q) throws ParseException{
+		stackQuery.clear();
+		query = null;
+		ReInit(new java.io.ByteArrayInputStream(q.getBytes()));
+		return Query();
+	}
+
+	/**
 	* Parses the query contained in the stream given in parameter.
 	*
 	* @param stream				The stream which contains the ADQL query to parse.
@@ -301,44 +327,46 @@ public class ADQLParser implements ADQLParserConstants {
 	* @see ADQLParser#setDebug(boolean)
 	* @see ADQLParser#Query()
 	*/
-        public final ADQLQuery parseQuery(java.io.InputStream stream) throws ParseException {
-                stackQuery.clear();
-                query = null;
-                ReInit(stream);
-                return Query();
-        }
-
-        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());
-        }
-
-        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;
-        }
-
-        /**
+	public final ADQLQuery parseQuery(java.io.InputStream stream) throws ParseException{
+		stackQuery.clear();
+		query = null;
+		ReInit(stream);
+		return Query();
+	}
+
+	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());
+	}
+
+	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;
+	}
+
+	/**
 	* <p>Gets the specified ADQL query and parses the given ADQL query. The SQL translation is then printed if the syntax is correct.</p>
 	* <p><b>ONLY the syntax is checked: the query is NOT EXECUTED !</b></p>
 	* <p>Supplied parameters are: <ul><li>[-debug] -url http://...</li><li>[-debug] -file ...</li><li>[-debug] -query SELECT...</li></ul></p>
@@ -346,4988 +374,5603 @@ public class ADQLParser implements ADQLParserConstants {
 	* @param args
 	* @throws Exception
 	*/
-        public static final void main(String[] args) throws Exception {
-                final String USAGE = "Usage:\u005cn\u005ctadqlParser.jar [-d] [-v] [-e] [-a|-s] [<FILE>|<URL>]\u005cn\u005cnNOTE: If no file or URL is given, the ADQL query is expected in the standard input. This query must end with a ';' !\u005cn\u005cnParameters:\u005cn\u005ct-v or --verbose : Print the main steps of the parsing\u005cn\u005ct-d or --debug   : Print stack traces when a grave error occurs\u005cn\u005ct-e or --explain : Explain the ADQL parsing (or Expand the parsing tree)\u005cn\u005ct-a or --adql    : Display the understood ADQL query\u005cn\u005ct-s or --sql     : Ask the SQL translation of the given ADQL query (SQL compatible with PostgreSQL)\u005cn\u005cnReturn:\u005cn\u005ctBy default: nothing if the query is correct. Otherwise a message explaining why the query is not correct is displayed.\u005cn\u005ctWith the -s option, the SQL translation of the given ADQL query will be returned.\u005cn\u005ctWith the -a option, the ADQL query is returned as it has been understood.\u005cn\u005cnExit status:\u005cn\u005ct0\u005ctOK !\u005cn\u005ct1\u005ctParameter error (missing or incorrect parameter)\u005cn\u005ct2\u005ctFile error (incorrect file/url, reading error, ...)\u005cn\u005ct3\u005ctParsing error (syntactic or semantic error)\u005cn\u005ct4\u005ctTranslation error (a problem has occurred during the translation of the 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;
-
-                // 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("-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{
-
-                        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 FileReader(file));
-
-                        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():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 (true) return q;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("Query");
-    }
-  }
-
-  final public ADQLQuery QueryExpression() throws ParseException {
-    trace_call("QueryExpression");
-    try {
-                try{
-                        // create the query:
-                        query = queryFactory.createQuery();
-                        stackQuery.push(query);
-                }catch(Exception ex){
-                        {if (true) throw generateParseException(ex);}
-                }
-      Select();
-      From();
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case WHERE:
-        Where();
-        break;
-      default:
-        jj_la1[1] = jj_gen;
-        ;
-      }
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case GROUP_BY:
-        GroupBy();
-        break;
-      default:
-        jj_la1[2] = jj_gen;
-        ;
-      }
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case HAVING:
-        Having();
-        break;
-      default:
-        jj_la1[3] = jj_gen;
-        ;
-      }
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case ORDER_BY:
-        OrderBy();
-        break;
-      default:
-        jj_la1[4] = jj_gen;
-        ;
-      }
-                // 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 (true) 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;
-      jj_consume_token(LEFT_PAR);
-      q = QueryExpression();
-      jj_consume_token(RIGHT_PAR);
-         {if (true) 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 t = null;
-      jj_consume_token(SELECT);
-      switch ((jj_ntk==-1)?jj_ntk():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():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;
-        ;
-      }
-      item = SelectItem();
-                           select.add(item);
-      label_1:
-      while (true) {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case COMMA:
-          ;
-          break;
-        default:
-          jj_la1[7] = jj_gen;
-          break label_1;
-        }
-        jj_consume_token(COMMA);
-        item = SelectItem();
-                                    select.add(item);
-      }
-    } 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;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case ASTERISK:
-        jj_consume_token(ASTERISK);
-                              {if (true) return new SelectAllColumns(query);}
-        break;
-      default:
-        jj_la1[11] = jj_gen;
-        if (jj_2_1(7)) {
-          id = Identifier();
-          jj_consume_token(DOT);
-                                                identifiers.append(id);
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            id = Identifier();
-            jj_consume_token(DOT);
-                                                        identifiers.append(id);
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case DELIMITED_IDENTIFIER:
-            case REGULAR_IDENTIFIER:
-              id = Identifier();
-              jj_consume_token(DOT);
-                                                                identifiers.append(id);
-              break;
-            default:
-              jj_la1[8] = jj_gen;
-              ;
-            }
-            break;
-          default:
-            jj_la1[9] = jj_gen;
-            ;
-          }
-          jj_consume_token(ASTERISK);
-                                try{;
-                                        {if (true) return new SelectAllColumns( queryFactory.createTable(identifiers, null) );}
-                                }catch(Exception ex) {
-                                        {if (true) throw generateParseException(ex);}
-                                }
-        } else {
-          switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-          case SCIENTIFIC_NUMBER:
-          case UNSIGNED_FLOAT:
-          case UNSIGNED_INTEGER:
-            op = ValueExpression();
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case AS:
-              jj_consume_token(AS);
-              label = Identifier();
-              break;
-            default:
-              jj_la1[10] = jj_gen;
-              ;
-            }
-            break;
-          default:
-            jj_la1[12] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-        }
-      }
-                try{
-                        SelectItem item = queryFactory.createSelectItem(op, (label==null)?null:label.identifier);
-                        if (label != null)
-                                item.setCaseSensitive(label.caseSensitivity);
-                        {if (true) 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():jj_ntk) {
-          case COMMA:
-            ;
-            break;
-          default:
-            jj_la1[13] = jj_gen;
-            break label_2;
-          }
-          jj_consume_token(COMMA);
-          content2 = TableRef();
-                                               content = queryFactory.createJoin(JoinType.CROSS, content, content2);
-        }
-                  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;
-      jj_consume_token(WHERE);
-      ConditionsList(where);
-    } finally {
-      trace_return("Where");
-    }
-  }
-
-  final public void GroupBy() throws ParseException {
-    trace_call("GroupBy");
-    try {
-                 ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); ColumnReference colRef = null;
-      jj_consume_token(GROUP_BY);
-      colRef = ColumnRef();
-                                        groupBy.add(colRef);
-      label_3:
-      while (true) {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case COMMA:
-          ;
-          break;
-        default:
-          jj_la1[14] = jj_gen;
-          break label_3;
-        }
-        jj_consume_token(COMMA);
-        colRef = ColumnRef();
-                                       groupBy.add(colRef);
-      }
-    } finally {
-      trace_return("GroupBy");
-    }
-  }
-
-  final public void Having() throws ParseException {
-    trace_call("Having");
-    try {
-                ClauseConstraints having = query.getHaving();
-      jj_consume_token(HAVING);
-      ConditionsList(having);
-    } finally {
-      trace_return("Having");
-    }
-  }
-
-  final public void OrderBy() throws ParseException {
-    trace_call("OrderBy");
-    try {
-                 ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); ADQLOrder order = null;
-      jj_consume_token(ORDER_BY);
-      order = OrderItem();
-                                      orderBy.add(order);
-      label_4:
-      while (true) {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case COMMA:
-          ;
-          break;
-        default:
-          jj_la1[15] = jj_gen;
-          break label_4;
-        }
-        jj_consume_token(COMMA);
-        order = OrderItem();
-                                     orderBy.add(order);
-      }
-    } 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():jj_ntk) {
-      case REGULAR_IDENTIFIER:
-        t = jj_consume_token(REGULAR_IDENTIFIER);
-                  {if (true) return new IdentifierItem(t, false);}
-        break;
-      case DELIMITED_IDENTIFIER:
-        t = jj_consume_token(DELIMITED_IDENTIFIER);
-                  {if (true) return new IdentifierItem(t, true);}
-        break;
-      default:
-        jj_la1[16] = 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():jj_ntk) {
-      case DOT:
-        jj_consume_token(DOT);
-        id = Identifier();
-                                                     identifiers.append(id);
-        break;
-      default:
-        jj_la1[17] = jj_gen;
-        ;
-      }
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case DOT:
-        jj_consume_token(DOT);
-        id = Identifier();
-                                                     identifiers.append(id);
-        break;
-      default:
-        jj_la1[18] = jj_gen;
-        ;
-      }
-          {if (true) 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():jj_ntk) {
-      case DOT:
-        jj_consume_token(DOT);
-        table = TableName();
-        break;
-      default:
-        jj_la1[19] = jj_gen;
-        ;
-      }
-                identifiers.append(id);
-                if (table != null){
-                        for(int i=0; i<table.size(); i++)
-                                identifiers.append(table.get(i));
-                }
-                {if (true) 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 (true) 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 ColumnReference ColumnRef() throws ParseException {
-    trace_call("ColumnRef");
-    try {
-                              IdentifierItems identifiers = null; Token ind = null;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case DELIMITED_IDENTIFIER:
-      case REGULAR_IDENTIFIER:
-        identifiers = ColumnName();
-        break;
-      case UNSIGNED_INTEGER:
-        ind = jj_consume_token(UNSIGNED_INTEGER);
-        break;
-      default:
-        jj_la1[20] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-                try{
-                        ColumnReference colRef = null;
-                        if (identifiers != null)
-                                colRef = queryFactory.createColRef(identifiers);
-                        else
-                                colRef = queryFactory.createColRef(Integer.parseInt(ind.image), new TextPosition(ind));
-                        {if (true) return colRef;}
-                }catch(Exception ex){
-                        {if (true) throw generateParseException(ex);}
-                }
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("ColumnRef");
-    }
-  }
-
-  final public ADQLOrder OrderItem() throws ParseException {
-    trace_call("OrderItem");
-    try {
-                        IdentifierItems identifiers = null; Token ind = null, desc = null;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case DELIMITED_IDENTIFIER:
-      case REGULAR_IDENTIFIER:
-        identifiers = ColumnName();
-        break;
-      case UNSIGNED_INTEGER:
-        ind = jj_consume_token(UNSIGNED_INTEGER);
-        break;
-      default:
-        jj_la1[21] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case ASC:
-      case DESC:
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case ASC:
-          jj_consume_token(ASC);
-          break;
-        case DESC:
-          desc = jj_consume_token(DESC);
-          break;
-        default:
-          jj_la1[22] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-        break;
-      default:
-        jj_la1[23] = jj_gen;
-        ;
-      }
-                try{
-                        ADQLOrder order = null;
-                        if (identifiers != null)
-                                order = queryFactory.createOrder(identifiers, desc!=null);
-                        else
-                                order = queryFactory.createOrder(Integer.parseInt(ind.image), desc!=null, new TextPosition(ind));
-                        {if (true) 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;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case DELIMITED_IDENTIFIER:
-        case REGULAR_IDENTIFIER:
-          identifiers = TableName();
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case AS:
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case AS:
-              jj_consume_token(AS);
-              break;
-            default:
-              jj_la1[24] = jj_gen;
-              ;
-            }
-            alias = Identifier();
-            break;
-          default:
-            jj_la1[25] = jj_gen;
-            ;
-          }
-                          {if (true) return queryFactory.createTable(identifiers, alias);}
-          break;
-        default:
-          jj_la1[27] = jj_gen;
-          if (jj_2_2(2)) {
-            subQuery = SubQueryExpression();
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case AS:
-              jj_consume_token(AS);
-              break;
-            default:
-              jj_la1[26] = jj_gen;
-              ;
-            }
-            alias = Identifier();
-                          {if (true) return queryFactory.createTable(subQuery, alias);}
-          } else {
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case LEFT_PAR:
-              jj_consume_token(LEFT_PAR);
-              content = JoinedTable();
-              jj_consume_token(RIGHT_PAR);
-                          {if (true) return content;}
-              break;
-            default:
-              jj_la1[28] = 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 (true) 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():jj_ntk) {
-        case NATURAL:
-        case INNER:
-        case RIGHT:
-        case LEFT:
-        case FULL:
-        case JOIN:
-          ;
-          break;
-        default:
-          jj_la1[29] = jj_gen;
-          break label_6;
-        }
-      }
-          {if (true) 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;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case NATURAL:
-          jj_consume_token(NATURAL);
-                                   natural=true;
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case INNER:
-          case RIGHT:
-          case LEFT:
-          case FULL:
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case INNER:
-              jj_consume_token(INNER);
-              break;
-            case RIGHT:
-            case LEFT:
-            case FULL:
-              switch ((jj_ntk==-1)?jj_ntk():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[30] = jj_gen;
-                jj_consume_token(-1);
-                throw new ParseException();
-              }
-              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-              case OUTER:
-                jj_consume_token(OUTER);
-                break;
-              default:
-                jj_la1[31] = jj_gen;
-                ;
-              }
-              break;
-            default:
-              jj_la1[32] = jj_gen;
-              jj_consume_token(-1);
-              throw new ParseException();
-            }
-            break;
-          default:
-            jj_la1[33] = jj_gen;
-            ;
-          }
-          jj_consume_token(JOIN);
-          rightTable = TableRef();
-                          {if (true) return queryFactory.createJoin(type, leftTable, rightTable);}
-          break;
-        case INNER:
-        case RIGHT:
-        case LEFT:
-        case FULL:
-        case JOIN:
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case INNER:
-          case RIGHT:
-          case LEFT:
-          case FULL:
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case INNER:
-              jj_consume_token(INNER);
-              break;
-            case RIGHT:
-            case LEFT:
-            case FULL:
-              switch ((jj_ntk==-1)?jj_ntk():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[34] = jj_gen;
-                jj_consume_token(-1);
-                throw new ParseException();
-              }
-              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-              case OUTER:
-                jj_consume_token(OUTER);
-                break;
-              default:
-                jj_la1[35] = jj_gen;
-                ;
-              }
-              break;
-            default:
-              jj_la1[36] = jj_gen;
-              jj_consume_token(-1);
-              throw new ParseException();
-            }
-            break;
-          default:
-            jj_la1[37] = jj_gen;
-            ;
-          }
-          jj_consume_token(JOIN);
-          rightTable = TableRef();
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case ON:
-            jj_consume_token(ON);
-            ConditionsList(condition);
-                                  {if (true) return queryFactory.createJoin(type, leftTable, rightTable, condition);}
-            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():jj_ntk) {
-              case COMMA:
-                ;
-                break;
-              default:
-                jj_la1[38] = jj_gen;
-                break label_7;
-              }
-              jj_consume_token(COMMA);
-              id = Identifier();
-                                                          lstColumns.add( queryFactory.createColumn(id) );
-            }
-            jj_consume_token(RIGHT_PAR);
-                                  {if (true) return queryFactory.createJoin(type, leftTable, rightTable, lstColumns);}
-            break;
-          default:
-            jj_la1[39] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-          break;
-        default:
-          jj_la1[40] = 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 String String() throws ParseException {
-    trace_call("String");
-    try {
-                  Token t; String str="";
-      label_8:
-      while (true) {
-        t = jj_consume_token(STRING_LITERAL);
-                             str += t.image.substring(1,t.image.length()-1).replaceAll("''", "'");
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case STRING_LITERAL:
-          ;
-          break;
-        default:
-          jj_la1[41] = jj_gen;
-          break label_8;
-        }
-      }
-         {if (true) return str;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("String");
-    }
-  }
-
-/* ************* */
-/* NUMERIC TYPES */
-/* ************* */
-  final public String UnsignedNumeric() throws ParseException {
-    trace_call("UnsignedNumeric");
-    try {
-                           Token t;
-      switch ((jj_ntk==-1)?jj_ntk():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[42] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-         {if (true) return t.image;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("UnsignedNumeric");
-    }
-  }
-
-  final public String UnsignedFloat() throws ParseException {
-    trace_call("UnsignedFloat");
-    try {
-                         Token t;
-      switch ((jj_ntk==-1)?jj_ntk():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[43] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-         {if (true) return t.image;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("UnsignedFloat");
-    }
-  }
-
-  final public String SignedInteger() throws ParseException {
-    trace_call("SignedInteger");
-    try {
-                         Token sign=null, number;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case PLUS:
-      case MINUS:
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case PLUS:
-          sign = jj_consume_token(PLUS);
-          break;
-        case MINUS:
-          sign = jj_consume_token(MINUS);
-          break;
-        default:
-          jj_la1[44] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-        break;
-      default:
-        jj_la1[45] = jj_gen;
-        ;
-      }
-      number = jj_consume_token(UNSIGNED_INTEGER);
-         {if (true) return ((sign==null)?"":sign.image)+number.image;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("SignedInteger");
-    }
-  }
-
-/* *********** */
-/* EXPRESSIONS */
-/* *********** */
-  final public ADQLOperand NumericValueExpressionPrimary() throws ParseException {
-    trace_call("NumericValueExpressionPrimary");
-    try {
-                                              String expr; ADQLColumn column; ADQLOperand op;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case SCIENTIFIC_NUMBER:
-        case UNSIGNED_FLOAT:
-        case UNSIGNED_INTEGER:
-          // unsigned_value_specification
-                            expr = UnsignedNumeric();
-                                          {if (true) return queryFactory.createNumericConstant(expr);}
-          break;
-        case DELIMITED_IDENTIFIER:
-        case REGULAR_IDENTIFIER:
-          column = Column();
-                                   column.setExpectedType('N'); {if (true) return column;}
-          break;
-        case AVG:
-        case MAX:
-        case MIN:
-        case SUM:
-        case COUNT:
-          op = SqlFunction();
-                                    {if (true) return op;}
-          break;
-        case LEFT_PAR:
-          jj_consume_token(LEFT_PAR);
-          op = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-                                                                   {if (true) return queryFactory.createWrappedOperand(op);}
-          break;
-        default:
-          jj_la1[46] = 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 {
-                                             String expr; ADQLColumn column; ADQLOperand op;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case STRING_LITERAL:
-          // string
-                            expr = String();
-                                 {if (true) return queryFactory.createStringConstant(expr);}
-          break;
-        case DELIMITED_IDENTIFIER:
-        case REGULAR_IDENTIFIER:
-          column = Column();
-                                   column.setExpectedType('S'); {if (true) return column;}
-          break;
-        case LEFT_PAR:
-          jj_consume_token(LEFT_PAR);
-          op = StringExpression();
-          jj_consume_token(RIGHT_PAR);
-                                                                    {if (true) return queryFactory.createWrappedOperand(op);}
-          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("StringValueExpressionPrimary");
-    }
-  }
-
-  final public ADQLOperand ValueExpression() throws ParseException {
-    trace_call("ValueExpression");
-    try {
-                                ADQLOperand valueExpr = null;
-      try {
-        if (jj_2_4(2147483647)) {
-          valueExpr = NumericExpression();
-        } else if (jj_2_5(2147483647)) {
-          valueExpr = StringExpression();
-        } else if (jj_2_6(2147483647)) {
-          jj_consume_token(LEFT_PAR);
-          valueExpr = ValueExpression();
-          jj_consume_token(RIGHT_PAR);
-                                                                                             valueExpr = queryFactory.createWrappedOperand(valueExpr);
-        } else if (jj_2_7(2147483647)) {
-          valueExpr = UserDefinedFunction();
-        } else {
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case BOX:
-          case CENTROID:
-          case CIRCLE:
-          case POINT:
-          case POLYGON:
-          case REGION:
-            valueExpr = GeometryValueFunction();
-            break;
-          default:
-            jj_la1[48] = jj_gen;
-            if (jj_2_8(2147483647)) {
-              valueExpr = Column();
-            } else if (jj_2_9(2147483647)) {
-              valueExpr = StringFactor();
-            } else {
-              switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-              case REGULAR_IDENTIFIER:
-              case SCIENTIFIC_NUMBER:
-              case UNSIGNED_FLOAT:
-              case UNSIGNED_INTEGER:
-                valueExpr = Factor();
-                break;
-              default:
-                jj_la1[49] = jj_gen;
-                jj_consume_token(-1);
-                throw new ParseException();
-              }
-            }
-          }
-        }
-                 {if (true) 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():jj_ntk) {
-      case PLUS:
-      case MINUS:
-        switch ((jj_ntk==-1)?jj_ntk():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 (true) return leftOp;}
-        else{
-                try{
-                        {if (true) return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);}
-                }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():jj_ntk) {
-      case ASTERISK:
-      case DIVIDE:
-        switch ((jj_ntk==-1)?jj_ntk():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 (true) return leftOp;}
-        else{
-                try{
-                        {if (true) return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);}
-                }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;; ADQLOperand op;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case PLUS:
-      case MINUS:
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case PLUS:
-          jj_consume_token(PLUS);
-          break;
-        case MINUS:
-          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_10(2)) {
-        op = NumericFunction();
-      } else {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case LEFT_PAR:
-        case AVG:
-        case MAX:
-        case MIN:
-        case SUM:
-        case COUNT:
-        case DELIMITED_IDENTIFIER:
-        case REGULAR_IDENTIFIER:
-        case SCIENTIFIC_NUMBER:
-        case UNSIGNED_FLOAT:
-        case UNSIGNED_INTEGER:
-          op = NumericValueExpressionPrimary();
-          break;
-        default:
-          jj_la1[56] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-      }
-                if (negative){
-                        try{
-                                op = queryFactory.createNegativeOperand(op);
-                        }catch(Exception ex){
-                                {if (true) throw generateParseException(ex);}
-                        }
-                }
-
-                {if (true) 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():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 (true) 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():jj_ntk) {
-      case COORDSYS:
-        op = ExtractCoordSys();
-        break;
-      default:
-        jj_la1[58] = jj_gen;
-        if (jj_2_11(2)) {
-          op = UserDefinedFunction();
-                                                  ((UserDefinedFunction)op).setExpectedType('S');
-        } else {
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case LEFT_PAR:
-          case STRING_LITERAL:
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            op = StringValueExpressionPrimary();
-            break;
-          default:
-            jj_la1[59] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-        }
-      }
-         {if (true) 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():jj_ntk) {
-      case DELIMITED_IDENTIFIER:
-      case REGULAR_IDENTIFIER:
-        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 (true) return new GeometryValue<GeometryFunction>(col);}
-                }else
-                        {if (true) 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():jj_ntk) {
-        case NOT:
-          jj_consume_token(NOT);
-                        notOp = true;
-          break;
-        default:
-          jj_la1[61] = jj_gen;
-          ;
-        }
-        constraint = Constraint();
-                        if (notOp) constraint = queryFactory.createNot(constraint);
-                        notOp = false;
-                        if (clause instanceof ADQLConstraint)
-                                clause.add(constraint);
-                        else
-                                clause.add(constraint);
-        label_10:
-        while (true) {
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case AND:
-          case OR:
-            ;
-            break;
-          default:
-            jj_la1[62] = jj_gen;
-            break label_10;
-          }
-          switch ((jj_ntk==-1)?jj_ntk():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():jj_ntk) {
-          case NOT:
-            jj_consume_token(NOT);
-                                notOp = true;
-            break;
-          default:
-            jj_la1[64] = jj_gen;
-            ;
-          }
-          constraint = Constraint();
-                                if (notOp) constraint = queryFactory.createNot(constraint);
-                                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 (true) 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;
-      if (jj_2_12(2147483647)) {
-        constraint = Predicate();
-      } else {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case LEFT_PAR:
-          jj_consume_token(LEFT_PAR);
-                        try{
-                                constraint = queryFactory.createGroupOfConstraints();
-                        }catch(Exception ex){
-                                {if (true) throw generateParseException(ex);}
-                        }
-          ConditionsList((ConstraintsGroup)constraint);
-          jj_consume_token(RIGHT_PAR);
-          break;
-        default:
-          jj_la1[65] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-      }
-         {if (true) 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 notToken = null; ADQLConstraint constraint = null;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case EXISTS:
-          jj_consume_token(EXISTS);
-          q = SubQueryExpression();
-                                                    {if (true) return queryFactory.createExists(q);}
-          break;
-        default:
-          jj_la1[70] = jj_gen;
-          if (jj_2_14(2147483647)) {
-            column = Column();
-            jj_consume_token(IS);
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case NOT:
-              notToken = jj_consume_token(NOT);
-              break;
-            default:
-              jj_la1[66] = jj_gen;
-              ;
-            }
-            jj_consume_token(NULL);
-                                                                                         {if (true) return queryFactory.createIsNull((notToken!=null), column);}
-          } else if (jj_2_15(2147483647)) {
-            strExpr1 = StringExpression();
-            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-            case NOT:
-              notToken = jj_consume_token(NOT);
-              break;
-            default:
-              jj_la1[67] = jj_gen;
-              ;
-            }
-            jj_consume_token(LIKE);
-            strExpr2 = StringExpression();
-                                                                                                                                                 {if (true) return queryFactory.createComparison(strExpr1, (notToken==null)?ComparisonOperator.LIKE:ComparisonOperator.NOTLIKE, strExpr2);}
-          } else {
-            switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-            case REGULAR_IDENTIFIER:
-            case SCIENTIFIC_NUMBER:
-            case UNSIGNED_FLOAT:
-            case UNSIGNED_INTEGER:
-              op = ValueExpression();
-              switch ((jj_ntk==-1)?jj_ntk():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_13(2)) {
-                  constraint = BetweenEnd(op);
-                } else {
-                  switch ((jj_ntk==-1)?jj_ntk():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 (true) 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():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{
-                        {if (true) return queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp);}
-                }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 notToken=null; ADQLOperand min, max;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case NOT:
-        notToken = jj_consume_token(NOT);
-        break;
-      default:
-        jj_la1[73] = jj_gen;
-        ;
-      }
-      jj_consume_token(BETWEEN);
-      min = ValueExpression();
-      jj_consume_token(AND);
-      max = ValueExpression();
-                try{
-                        {if (true) return queryFactory.createBetween((notToken!=null), leftOp, min, max);}
-                }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; ADQLQuery q = null; ADQLOperand item; Vector<ADQLOperand> items = new Vector<ADQLOperand>();
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case NOT:
-        not = jj_consume_token(NOT);
-        break;
-      default:
-        jj_la1[74] = jj_gen;
-        ;
-      }
-      jj_consume_token(IN);
-      if (jj_2_16(2)) {
-        q = SubQueryExpression();
-      } else {
-        switch ((jj_ntk==-1)?jj_ntk():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():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{
-                        if (q != null)
-                                {if (true) return queryFactory.createIn(leftOp, q, not!=null);}
-                        else{
-                                ADQLOperand[] list = new ADQLOperand[items.size()];
-                                int i=0;
-                                for(ADQLOperand op : items)
-                                        list[i++] = op;
-                                {if (true) return queryFactory.createIn(leftOp, list, not!=null);}
-                        }
-                }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; ADQLOperand op=null; SQLFunction funct = null;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case COUNT:
-          jj_consume_token(COUNT);
-          jj_consume_token(LEFT_PAR);
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case QUANTIFIER:
-            distinct = jj_consume_token(QUANTIFIER);
-            break;
-          default:
-            jj_la1[77] = jj_gen;
-            ;
-          }
-          switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-          case SCIENTIFIC_NUMBER:
-          case UNSIGNED_FLOAT:
-          case UNSIGNED_INTEGER:
-            op = ValueExpression();
-            break;
-          default:
-            jj_la1[78] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-          jj_consume_token(RIGHT_PAR);
-                          funct = queryFactory.createSQLFunction((all!=null)?SQLFunctionType.COUNT_ALL:SQLFunctionType.COUNT, op, distinct != null && distinct.image.equalsIgnoreCase("distinct"));
-          break;
-        case AVG:
-        case MAX:
-        case MIN:
-        case SUM:
-          switch ((jj_ntk==-1)?jj_ntk():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():jj_ntk) {
-          case QUANTIFIER:
-            distinct = jj_consume_token(QUANTIFIER);
-            break;
-          default:
-            jj_la1[80] = jj_gen;
-            ;
-          }
-          op = ValueExpression();
-          jj_consume_token(RIGHT_PAR);
-                          funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct"));
-          break;
-        default:
-          jj_la1[81] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-      } catch (Exception ex) {
-                {if (true) throw generateParseException(ex);}
-      }
-          {if (true) 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 (true) 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 t=null; 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():jj_ntk) {
-        case CONTAINS:
-        case INTERSECTS:
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case CONTAINS:
-            t = jj_consume_token(CONTAINS);
-            break;
-          case INTERSECTS:
-            t = 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();
-          jj_consume_token(RIGHT_PAR);
-                                if (t.image.equalsIgnoreCase("contains"))
-                                        gf = queryFactory.createContains(gvf1, gvf2);
-                                else
-                                        gf = queryFactory.createIntersects(gvf1, gvf2);
-          break;
-        case AREA:
-          jj_consume_token(AREA);
-          jj_consume_token(LEFT_PAR);
-          gvf1 = GeometryExpression();
-          jj_consume_token(RIGHT_PAR);
-                                                                                   gf = queryFactory.createArea(gvf1);
-          break;
-        case COORD1:
-          jj_consume_token(COORD1);
-          jj_consume_token(LEFT_PAR);
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case POINT:
-            p1 = Point();
-                                                          gf = queryFactory.createCoord1(p1);
-            break;
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            col1 = Column();
-                                                                                                                col1.setExpectedType('G'); gf = queryFactory.createCoord1(col1);
-            break;
-          default:
-            jj_la1[83] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case COORD2:
-          jj_consume_token(COORD2);
-          jj_consume_token(LEFT_PAR);
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case POINT:
-            p1 = Point();
-                                                          gf = queryFactory.createCoord2(p1);
-            break;
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            col1 = Column();
-                                                                                                                col1.setExpectedType('G'); gf = queryFactory.createCoord2(col1);
-            break;
-          default:
-            jj_la1[84] = jj_gen;
-            jj_consume_token(-1);
-            throw new ParseException();
-          }
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case DISTANCE:
-          jj_consume_token(DISTANCE);
-          jj_consume_token(LEFT_PAR);
-          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-          case POINT:
-            p1 = Point();
-            break;
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            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():jj_ntk) {
-          case POINT:
-            p2 = Point();
-            break;
-          case DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-            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);
-                                        }
-          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);}
-      }
-          {if (true) 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 (true) return coordSys;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("CoordinateSystem");
-    }
-  }
-
-  final public GeometryFunction GeometryValueFunction() throws ParseException {
-    trace_call("GeometryValueFunction");
-    try {
-                                           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():jj_ntk) {
-        case BOX:
-          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();
-          jj_consume_token(RIGHT_PAR);
-                  gf = queryFactory.createBox(coordSys, coords[0], coords[1], width, height);
-          break;
-        case CENTROID:
-          jj_consume_token(CENTROID);
-          jj_consume_token(LEFT_PAR);
-          gvf = GeometryExpression();
-          jj_consume_token(RIGHT_PAR);
-                                                                                gf = queryFactory.createCentroid(gvf);
-          break;
-        case CIRCLE:
-          jj_consume_token(CIRCLE);
-          jj_consume_token(LEFT_PAR);
-          coordSys = CoordinateSystem();
-          jj_consume_token(COMMA);
-          coords = Coordinates();
-          jj_consume_token(COMMA);
-          width = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-                  gf = queryFactory.createCircle(coordSys, coords[0], coords[1], width);
-          break;
-        case POINT:
-          gf = Point();
-          break;
-        case POLYGON:
-          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():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]);
-          }
-          jj_consume_token(RIGHT_PAR);
-                    gf = queryFactory.createPolygon(coordSys, vCoords);
-          break;
-        case REGION:
-          jj_consume_token(REGION);
-          jj_consume_token(LEFT_PAR);
-          op = StringExpression();
-          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 (true) return gf;}
-    throw new Error("Missing return statement in function");
-    } finally {
-      trace_return("GeometryValueFunction");
-    }
-  }
-
-  final public PointFunction Point() throws ParseException {
-    trace_call("Point");
-    try {
-                        ADQLOperand coordSys; ADQLOperand[] coords;
-      jj_consume_token(POINT);
-      jj_consume_token(LEFT_PAR);
-      coordSys = CoordinateSystem();
-      jj_consume_token(COMMA);
-      coords = Coordinates();
-      jj_consume_token(RIGHT_PAR);
-                try{
-                        {if (true) return queryFactory.createPoint(coordSys, coords[0], coords[1]);}
-                }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 {
-                                     GeometryValue<GeometryFunction> gvf;
-      jj_consume_token(COORDSYS);
-      jj_consume_token(LEFT_PAR);
-      gvf = GeometryExpression();
-      jj_consume_token(RIGHT_PAR);
-                try{
-                        {if (true) return queryFactory.createExtractCoordSys(gvf);}
-                }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():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:
-        fct = UserDefinedFunction();
-                                      ((UserDefinedFunction)fct).setExpectedType('N');
-        break;
-      default:
-        jj_la1[90] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-         {if (true) 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; ADQLOperand param1=null, param2=null; String integerValue = null;
-      try {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case ABS:
-          fct = jj_consume_token(ABS);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case CEILING:
-          fct = jj_consume_token(CEILING);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case DEGREES:
-          fct = jj_consume_token(DEGREES);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case EXP:
-          fct = jj_consume_token(EXP);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case FLOOR:
-          fct = jj_consume_token(FLOOR);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case LOG:
-          fct = jj_consume_token(LOG);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case LOG10:
-          fct = jj_consume_token(LOG10);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          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();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case PI:
-          fct = jj_consume_token(PI);
-          jj_consume_token(LEFT_PAR);
-          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();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case RADIANS:
-          fct = jj_consume_token(RADIANS);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case RAND:
-          fct = jj_consume_token(RAND);
-          jj_consume_token(LEFT_PAR);
-          switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-          case REGULAR_IDENTIFIER:
-          case SCIENTIFIC_NUMBER:
-          case UNSIGNED_FLOAT:
-          case UNSIGNED_INTEGER:
-            param1 = NumericExpression();
-            break;
-          default:
-            jj_la1[91] = jj_gen;
-            ;
-          }
-          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():jj_ntk) {
-          case COMMA:
-            jj_consume_token(COMMA);
-            integerValue = SignedInteger();
-                                                                                                            param2 = queryFactory.createNumericConstant(integerValue);
-            break;
-          default:
-            jj_la1[92] = jj_gen;
-            ;
-          }
-          jj_consume_token(RIGHT_PAR);
-          break;
-        case SQRT:
-          fct = jj_consume_token(SQRT);
-          jj_consume_token(LEFT_PAR);
-          param1 = NumericExpression();
-          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():jj_ntk) {
-          case COMMA:
-            jj_consume_token(COMMA);
-            integerValue = SignedInteger();
-                                                                                                               param2 = queryFactory.createNumericConstant(integerValue);
-            break;
-          default:
-            jj_la1[93] = jj_gen;
-            ;
-          }
-          jj_consume_token(RIGHT_PAR);
-          break;
-        default:
-          jj_la1[94] = jj_gen;
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
-                        if (param1 != null)
-                                {if (true) return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);}
-                        else
-                                {if (true) return null;}
-      } 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; ADQLOperand param1=null, param2=null;
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case ACOS:
-        fct = jj_consume_token(ACOS);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case ASIN:
-        fct = jj_consume_token(ASIN);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case ATAN:
-        fct = jj_consume_token(ATAN);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        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();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case COS:
-        fct = jj_consume_token(COS);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case COT:
-        fct = jj_consume_token(COT);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case SIN:
-        fct = jj_consume_token(SIN);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      case TAN:
-        fct = jj_consume_token(TAN);
-        jj_consume_token(LEFT_PAR);
-        param1 = NumericExpression();
-        jj_consume_token(RIGHT_PAR);
-        break;
-      default:
-        jj_la1[95] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-                try{
-                        if (param1 != null)
-                                {if (true) return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);}
-                        else
-                                {if (true) return null;}
-                }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; Vector<ADQLOperand> params = new Vector<ADQLOperand>(); ADQLOperand op;
-      fct = jj_consume_token(REGULAR_IDENTIFIER);
-      jj_consume_token(LEFT_PAR);
-      switch ((jj_ntk==-1)?jj_ntk():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 DELIMITED_IDENTIFIER:
-      case REGULAR_IDENTIFIER:
-      case SCIENTIFIC_NUMBER:
-      case UNSIGNED_FLOAT:
-      case UNSIGNED_INTEGER:
-        op = ValueExpression();
-                                                                   params.add(op);
-        label_13:
-        while (true) {
-          switch ((jj_ntk==-1)?jj_ntk():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;
-        ;
-      }
-      jj_consume_token(RIGHT_PAR);
-                //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:
-                        {if (true) return queryFactory.createUserDefinedFunction(fct.image, parameters);}
-                }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_3R_145() {
-    if (jj_3R_109()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_163() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_185()) jj_scanpos = xsp;
-    if (jj_3R_186()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_187()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_148() {
-    if (jj_scan_token(TOP)) return true;
-    if (jj_scan_token(UNSIGNED_INTEGER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_147() {
-    if (jj_scan_token(QUANTIFIER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_48() {
-    if (jj_scan_token(SELECT)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_147()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_148()) jj_scanpos = xsp;
-    if (jj_3R_149()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_150()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_144() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_16() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_31()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_53() {
-    if (jj_3R_74()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_122() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_144()) {
-    jj_scanpos = xsp;
-    if (jj_3R_145()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_55() {
-    if (jj_3R_76()) return true;
-    return false;
-  }
-
-  private boolean jj_3_11() {
-    if (jj_3R_24()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_54() {
-    if (jj_3R_75()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_35() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_54()) {
-    jj_scanpos = xsp;
-    if (jj_3_11()) {
-    jj_scanpos = xsp;
-    if (jj_3R_55()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_133() {
-    if (jj_3R_155()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_132() {
-    if (jj_3R_154()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_131() {
-    if (jj_3R_153()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_130() {
-    if (jj_3R_152()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_123() {
-    if (jj_3R_46()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_146()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_47() {
-    if (jj_scan_token(CONCAT)) return true;
-    if (jj_3R_35()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_174() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_191()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_173() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_191()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_31() {
-    if (jj_3R_48()) return true;
-    if (jj_3R_129()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_130()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_131()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_132()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_133()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_27() {
-    if (jj_3R_35()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_47()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_73() {
-    if (jj_scan_token(MINUS)) return true;
-    return false;
-  }
-
-  private boolean jj_3_10() {
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_52() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(8)) {
-    jj_scanpos = xsp;
-    if (jj_3R_73()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_168() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(10)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(11)) return true;
-    }
-    if (jj_3R_135()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_112() {
-    if (jj_scan_token(FULL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_34() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_52()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3_10()) {
-    jj_scanpos = xsp;
-    if (jj_3R_53()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_24() {
-    if (jj_scan_token(REGULAR_IDENTIFIER)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_123()) jj_scanpos = xsp;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_156() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(8)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(9)) return true;
-    }
-    if (jj_3R_108()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_19() {
-    if (jj_3R_34()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(8)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(9)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(10)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(11)) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_172() {
-    if (jj_3R_108()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_20() {
-    if (jj_3R_35()) return true;
-    if (jj_scan_token(CONCAT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_135() {
-    if (jj_3R_34()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_168()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_100() {
-    if (jj_scan_token(TAN)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3_9() {
-    if (jj_3R_22()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_99() {
-    if (jj_scan_token(SIN)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3_8() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_98() {
-    if (jj_scan_token(COT)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_115() {
-    if (jj_scan_token(FULL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_97() {
-    if (jj_scan_token(COS)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3_7() {
-    if (jj_scan_token(REGULAR_IDENTIFIER)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_96() {
-    if (jj_scan_token(ATAN2)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3_6() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_95() {
-    if (jj_scan_token(ATAN)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) 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(63)) {
-    jj_scanpos = xsp;
-    if (jj_3R_20()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_94() {
-    if (jj_scan_token(ASIN)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) 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(8)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(9)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_93() {
-    if (jj_scan_token(ACOS)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_58() {
-    Token xsp;
-    xsp = jj_scanpos;
-    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()) {
-    jj_scanpos = xsp;
-    if (jj_3R_99()) {
-    jj_scanpos = xsp;
-    if (jj_3R_100()) return true;
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_69() {
-    if (jj_3R_34()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_68() {
-    if (jj_3R_35()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_67() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_108() {
-    if (jj_3R_135()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_156()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_92() {
-    if (jj_scan_token(TRUNCATE)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_174()) jj_scanpos = xsp;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_66() {
-    if (jj_3R_109()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_91() {
-    if (jj_scan_token(SQRT)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_65() {
-    if (jj_3R_24()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_90() {
-    if (jj_scan_token(ROUND)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_173()) jj_scanpos = xsp;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_64() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_46()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_89() {
-    if (jj_scan_token(RAND)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_172()) jj_scanpos = xsp;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_63() {
-    if (jj_3R_27()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_88() {
-    if (jj_scan_token(RADIANS)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_87() {
-    if (jj_scan_token(POWER)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_62() {
-    if (jj_3R_108()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_86() {
-    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_111() {
-    if (jj_scan_token(RIGHT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_85() {
-    if (jj_scan_token(MOD)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_84() {
-    if (jj_scan_token(LOG10)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_83() {
-    if (jj_scan_token(LOG)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_82() {
-    if (jj_scan_token(FLOOR)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_81() {
-    if (jj_scan_token(EXP)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_80() {
-    if (jj_scan_token(DEGREES)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_126() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_27()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_79() {
-    if (jj_scan_token(CEILING)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_125() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_78() {
-    if (jj_scan_token(ABS)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_46() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_62()) {
-    jj_scanpos = xsp;
-    if (jj_3R_63()) {
-    jj_scanpos = xsp;
-    if (jj_3R_64()) {
-    jj_scanpos = xsp;
-    if (jj_3R_65()) {
-    jj_scanpos = xsp;
-    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()) return true;
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_124() {
-    if (jj_3R_22()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_57() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_78()) {
-    jj_scanpos = xsp;
-    if (jj_3R_79()) {
-    jj_scanpos = xsp;
-    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()) {
-    jj_scanpos = xsp;
-    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()) return true;
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_121() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_120() {
-    if (jj_3R_143()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_41() {
-    if (jj_3R_24()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_76() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_124()) {
-    jj_scanpos = xsp;
-    if (jj_3R_125()) {
-    jj_scanpos = xsp;
-    if (jj_3R_126()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_40() {
-    if (jj_3R_59()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_114() {
-    if (jj_scan_token(RIGHT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_119() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_39() {
-    if (jj_3R_58()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_118() {
-    if (jj_3R_142()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_38() {
-    if (jj_3R_57()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_23() {
-    Token xsp;
-    xsp = jj_scanpos;
-    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()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_201() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_14()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_74() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_118()) {
-    jj_scanpos = xsp;
-    if (jj_3R_119()) {
-    jj_scanpos = xsp;
-    if (jj_3R_120()) {
-    jj_scanpos = xsp;
-    if (jj_3R_121()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_110() {
-    if (jj_scan_token(LEFT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_70() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_110()) {
-    jj_scanpos = xsp;
-    if (jj_3R_111()) {
-    jj_scanpos = xsp;
-    if (jj_3R_112()) return true;
-    }
-    }
-    xsp = jj_scanpos;
-    if (jj_scan_token(25)) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_75() {
-    if (jj_scan_token(COORDSYS)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_122()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_178() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_171() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_176() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_197() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(8)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(9)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_191() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_197()) jj_scanpos = xsp;
-    if (jj_scan_token(UNSIGNED_INTEGER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_49() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(24)) {
-    jj_scanpos = xsp;
-    if (jj_3R_70()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_141() {
-    if (jj_scan_token(REGION)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_27()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_158() {
-    if (jj_scan_token(POINT)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_169()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_142() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(99)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(100)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(101)) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_200() {
-    if (jj_scan_token(USING)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_14()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_201()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_113() {
-    if (jj_scan_token(LEFT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_140() {
-    if (jj_scan_token(POLYGON)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_169()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_171()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_71() {
-    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;
-    }
-    }
-    xsp = jj_scanpos;
-    if (jj_scan_token(25)) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_199() {
-    if (jj_scan_token(ON)) return true;
-    if (jj_3R_163()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_139() {
-    if (jj_3R_158()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_37() {
-    if (jj_scan_token(STRING_LITERAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_22() {
-    Token xsp;
-    if (jj_3R_37()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_37()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_138() {
-    if (jj_scan_token(CIRCLE)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_169()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_50() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(24)) {
-    jj_scanpos = xsp;
-    if (jj_3R_71()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_33() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_50()) jj_scanpos = xsp;
-    if (jj_scan_token(JOIN)) return true;
-    if (jj_3R_51()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_199()) {
-    jj_scanpos = xsp;
-    if (jj_3R_200()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_137() {
-    if (jj_scan_token(CENTROID)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_122()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_32() {
-    if (jj_scan_token(NATURAL)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_49()) jj_scanpos = xsp;
-    if (jj_scan_token(JOIN)) return true;
-    if (jj_3R_51()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_136() {
-    if (jj_scan_token(BOX)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_169()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_170()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_192() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(22)) jj_scanpos = xsp;
-    if (jj_3R_14()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_182() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_190() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(45)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(46)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_183() {
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_180() {
-    if (jj_3R_21()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_109() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_136()) {
-    jj_scanpos = xsp;
-    if (jj_3R_137()) {
-    jj_scanpos = xsp;
-    if (jj_3R_138()) {
-    jj_scanpos = xsp;
-    if (jj_3R_139()) {
-    jj_scanpos = xsp;
-    if (jj_3R_140()) {
-    jj_scanpos = xsp;
-    if (jj_3R_141()) return true;
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_181() {
-    if (jj_3R_158()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_177() {
-    if (jj_3R_158()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_175() {
-    if (jj_3R_158()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_17() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_32()) {
-    jj_scanpos = xsp;
-    if (jj_3R_33()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_169() {
-    if (jj_3R_27()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_198() {
-    if (jj_3R_17()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_117() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_193()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_193() {
-    if (jj_3R_72()) return true;
-    Token xsp;
-    if (jj_3R_198()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_198()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_179() {
-    if (jj_3R_158()) return true;
-    return false;
-  }
-
-  private boolean jj_3_3() {
-    if (jj_3R_17()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_116() {
-    if (jj_3R_77()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_192()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_51() {
-    if (jj_3R_72()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3_3()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3_2() {
-    if (jj_3R_16()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(22)) jj_scanpos = xsp;
-    if (jj_3R_14()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_105() {
-    if (jj_scan_token(DISTANCE)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_179()) {
-    jj_scanpos = xsp;
-    if (jj_3R_180()) return true;
-    }
-    if (jj_scan_token(COMMA)) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_181()) {
-    jj_scanpos = xsp;
-    if (jj_3R_182()) return true;
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_104() {
-    if (jj_scan_token(COORD2)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_177()) {
-    jj_scanpos = xsp;
-    if (jj_3R_178()) return true;
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_103() {
-    if (jj_scan_token(COORD1)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_175()) {
-    jj_scanpos = xsp;
-    if (jj_3R_176()) return true;
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_102() {
-    if (jj_scan_token(AREA)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_122()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_72() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_116()) {
-    jj_scanpos = xsp;
-    if (jj_3_2()) {
-    jj_scanpos = xsp;
-    if (jj_3R_117()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_101() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(58)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(59)) return true;
-    }
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_122()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_122()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_157() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_189() {
-    if (jj_3R_36()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_166() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_189()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(101)) return true;
-    }
-    xsp = jj_scanpos;
-    if (jj_3R_190()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_59() {
-    Token xsp;
-    xsp = jj_scanpos;
-    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()) return true;
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_160() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(47)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(48)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(49)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(50)) return true;
-    }
-    }
-    }
-    if (jj_scan_token(LEFT_PAR)) return true;
-    xsp = jj_scanpos;
-    if (jj_scan_token(19)) jj_scanpos = xsp;
-    if (jj_3R_46()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_170() {
-    if (jj_3R_108()) return true;
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_108()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_159() {
-    if (jj_scan_token(COUNT)) return true;
-    if (jj_scan_token(LEFT_PAR)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(19)) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(10)) {
-    jj_scanpos = xsp;
-    if (jj_3R_183()) return true;
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_188() {
-    if (jj_3R_36()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_164() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_188()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(101)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_56() {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_3R_77()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_143() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_159()) {
-    jj_scanpos = xsp;
-    if (jj_3R_160()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_21() {
-    if (jj_3R_36()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_36() {
-    if (jj_3R_14()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_56()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_128() {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_3R_14()) return true;
-    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_134() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_46()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_157()) { jj_scanpos = xsp; break; }
-    }
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3_16() {
-    if (jj_3R_16()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_107() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(35)) jj_scanpos = xsp;
-    if (jj_scan_token(IN)) return true;
-    xsp = jj_scanpos;
-    if (jj_3_16()) {
-    jj_scanpos = xsp;
-    if (jj_3R_134()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_77() {
-    if (jj_3R_14()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_127()) jj_scanpos = xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_128()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_29() {
-    if (jj_scan_token(DELIMITED_IDENTIFIER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_28() {
-    if (jj_scan_token(REGULAR_IDENTIFIER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_26() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(35)) jj_scanpos = xsp;
-    if (jj_scan_token(BETWEEN)) return true;
-    if (jj_3R_46()) return true;
-    if (jj_scan_token(AND)) return true;
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_61() {
-    if (jj_3R_107()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_14() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_28()) {
-    jj_scanpos = xsp;
-    if (jj_3R_29()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3_13() {
-    if (jj_3R_26()) return true;
-    return false;
-  }
-
-  private boolean jj_3_15() {
-    if (jj_3R_27()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(35)) jj_scanpos = xsp;
-    if (jj_scan_token(LIKE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_60() {
-    if (jj_3R_106()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_167() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_166()) return true;
-    return false;
-  }
-
-  private boolean jj_3_14() {
-    if (jj_3R_21()) return true;
-    if (jj_scan_token(IS)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_106() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(12)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(13)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(14)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(15)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(16)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(17)) return true;
-    }
-    }
-    }
-    }
-    }
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_155() {
-    if (jj_scan_token(ORDER_BY)) return true;
-    if (jj_3R_166()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_167()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_154() {
-    if (jj_scan_token(HAVING)) return true;
-    if (jj_3R_163()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_45() {
-    if (jj_3R_46()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_60()) {
-    jj_scanpos = xsp;
-    if (jj_3_13()) {
-    jj_scanpos = xsp;
-    if (jj_3R_61()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_44() {
-    if (jj_3R_27()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(35)) jj_scanpos = xsp;
-    if (jj_scan_token(LIKE)) return true;
-    if (jj_3R_27()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_165() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_164()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_43() {
-    if (jj_3R_21()) return true;
-    if (jj_scan_token(IS)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(35)) jj_scanpos = xsp;
-    if (jj_scan_token(NULL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_184() {
-    if (jj_scan_token(AS)) return true;
-    if (jj_3R_14()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_153() {
-    if (jj_scan_token(GROUP_BY)) return true;
-    if (jj_3R_164()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_165()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_42() {
-    if (jj_scan_token(EXISTS)) return true;
-    if (jj_3R_16()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_151() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_51()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_152() {
-    if (jj_scan_token(WHERE)) return true;
-    if (jj_3R_163()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_30() {
-    if (jj_3R_14()) return true;
-    if (jj_scan_token(DOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_25() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_42()) {
-    jj_scanpos = xsp;
-    if (jj_3R_43()) {
-    jj_scanpos = xsp;
-    if (jj_3R_44()) {
-    jj_scanpos = xsp;
-    if (jj_3R_45()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_129() {
-    if (jj_scan_token(FROM)) return true;
-    if (jj_3R_51()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_151()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3_12() {
-    if (jj_3R_25()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_162() {
-    if (jj_3R_46()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_184()) jj_scanpos = xsp;
-    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_30()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_195() {
-    if (jj_scan_token(LEFT_PAR)) return true;
-    if (jj_3R_163()) return true;
-    if (jj_scan_token(RIGHT_PAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_194() {
-    if (jj_3R_25()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_186() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_194()) {
-    jj_scanpos = xsp;
-    if (jj_3R_195()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_196() {
-    if (jj_scan_token(NOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_187() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(33)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(34)) return true;
-    }
-    xsp = jj_scanpos;
-    if (jj_3R_196()) jj_scanpos = xsp;
-    if (jj_3R_186()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_161() {
-    if (jj_scan_token(ASTERISK)) 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_185() {
-    if (jj_scan_token(NOT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_146() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_149() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_161()) {
-    jj_scanpos = xsp;
-    if (jj_3_1()) {
-    jj_scanpos = xsp;
-    if (jj_3R_162()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_150() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_149()) 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[] {0x41,0x0,0x0,0x0,0x0,0x80000,0x100000,0x20,0x0,0x0,0x400000,0x400,0x304,0x20,0x20,0x20,0x0,0x10,0x10,0x10,0x0,0x0,0x0,0x0,0x400000,0x400000,0x400000,0x0,0x4,0x3d800000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x20,0xc0000000,0x3d800000,0x0,0x0,0x0,0x300,0x300,0x4,0x4,0x0,0x304,0x300,0x300,0xc00,0xc00,0x300,0x300,0x4,0x80,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x3f000,0x0,0x0,0x304,0x3f000,0x0,0x0,0x20,0x4,0x80000,0x704,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x304,0x20,0x20,0x0,0x0,0x20,0x304,};
-   }
-   private static void jj_la1_init_1() {
-      jj_la1_1 = new int[] {0x0,0x1,0x400,0x800,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x3f00000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x80000000,0x0,0x3f00000,0x8,0x6,0x6,0x8,0x0,0x8,0x8,0x0,0x108,0x200,0xffff8000,0x0,0x8,0x8,0x0,0x0,0x0,0xffff8000,0x78000,0x0,0xf8000,0xc000000,0x800000,0x800000,0x800000,0x800000,0x7c000000,0x0,0x3f00000,0x7c000000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0xffff8000,};
-   }
-   private static void jj_la1_init_2() {
-      jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,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,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0xffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xffffff,0xffffff,0x0,0x0,0xfffe,0xff0000,0x0,0x20ffffff,};
-   }
-   private static void jj_la1_init_3() {
-      jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x0,0x0,0x3b,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x23,0x23,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x30,0x0,0x0,0x3b,0x3,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x3,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x3,0x3,0x3,0x3,0x0,0x0,0x0,0x2,0x3b,0x0,0x0,0x0,0x0,0x0,0x3b,};
-   }
-  final private JJCalls[] jj_2_rtns = new JJCalls[16];
-  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();
-  }
-
-  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() {
-    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[103];
-    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 < 103; 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 < 16; 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;
-          }
-        }
-        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;
-  }
+	public static final void main(String[] args) throws Exception{
+		final String USAGE = "Usage:\u005cn\u005ctadqlParser.jar [-d] [-v] [-e] [-a|-s] [<FILE>|<URL>]\u005cn\u005cnNOTE: If no file or URL is given, the ADQL query is expected in the standard input. This query must end with a ';' !\u005cn\u005cnParameters:\u005cn\u005ct-v or --verbose : Print the main steps of the parsing\u005cn\u005ct-d or --debug   : Print stack traces when a grave error occurs\u005cn\u005ct-e or --explain : Explain the ADQL parsing (or Expand the parsing tree)\u005cn\u005ct-a or --adql    : Display the understood ADQL query\u005cn\u005ct-s or --sql     : Ask the SQL translation of the given ADQL query (SQL compatible with PostgreSQL)\u005cn\u005cnReturn:\u005cn\u005ctBy default: nothing if the query is correct. Otherwise a message explaining why the query is not correct is displayed.\u005cn\u005ctWith the -s option, the SQL translation of the given ADQL query will be returned.\u005cn\u005ctWith the -a option, the ADQL query is returned as it has been understood.\u005cn\u005cnExit status:\u005cn\u005ct0\u005ctOK !\u005cn\u005ct1\u005ctParameter error (missing or incorrect parameter)\u005cn\u005ct2\u005ctFile error (incorrect file/url, reading error, ...)\u005cn\u005ct3\u005ctParsing error (syntactic or semantic error)\u005cn\u005ct4\u005ctTranslation error (a problem has occurred during the translation of the 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;
+
+		// 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("-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{
+
+			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 FileReader(file));
+
+			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() : 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 (true)
+					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() : jj_ntk){
+				case WHERE:
+					Where();
+					endPos = query.getWhere().getPosition();
+					break;
+				default:
+					jj_la1[1] = jj_gen;
+					;
+			}
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case GROUP_BY:
+					GroupBy();
+					endPos = query.getGroupBy().getPosition();
+					break;
+				default:
+					jj_la1[2] = jj_gen;
+					;
+			}
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case HAVING:
+					Having();
+					endPos = query.getHaving().getPosition();
+					break;
+				default:
+					jj_la1[3] = jj_gen;
+					;
+			}
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case ORDER_BY:
+					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 (true)
+					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 (true)
+					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() : 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() : 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;
+					;
+			}
+			item = SelectItem();
+			select.add(item);
+			label_1: while(true){
+				switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+					case COMMA:
+						;
+						break;
+					default:
+						jj_la1[7] = 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() : jj_ntk){
+				case ASTERISK:
+					starToken = jj_consume_token(ASTERISK);
+					item = new SelectAllColumns(query);
+					item.setPosition(new TextPosition(starToken));
+					{
+						if (true)
+							return item;
+					}
+					break;
+				default:
+					jj_la1[11] = jj_gen;
+					if (jj_2_1(7)){
+						id = Identifier();
+						jj_consume_token(DOT);
+						identifiers.append(id);
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								id = Identifier();
+								jj_consume_token(DOT);
+								identifiers.append(id);
+								switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+									case DELIMITED_IDENTIFIER:
+									case REGULAR_IDENTIFIER:
+										id = Identifier();
+										jj_consume_token(DOT);
+										identifiers.append(id);
+										break;
+									default:
+										jj_la1[8] = jj_gen;
+										;
+								}
+								break;
+							default:
+								jj_la1[9] = 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 (true)
+									return item;
+							}
+						}catch(Exception ex){
+							{
+								if (true)
+									throw generateParseException(ex);
+							}
+						}
+					}else{
+						switch((jj_ntk == -1) ? jj_ntk() : 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 DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+							case SCIENTIFIC_NUMBER:
+							case UNSIGNED_FLOAT:
+							case UNSIGNED_INTEGER:
+								op = ValueExpression();
+								switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+									case AS:
+										jj_consume_token(AS);
+										label = Identifier();
+										break;
+									default:
+										jj_la1[10] = jj_gen;
+										;
+								}
+								break;
+							default:
+								jj_la1[12] = 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 (true)
+						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() : jj_ntk){
+						case COMMA:
+							;
+							break;
+						default:
+							jj_la1[13] = 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<ColumnReference> groupBy = query.getGroupBy();
+			ColumnReference colRef = null;
+			Token start;
+			start = jj_consume_token(GROUP_BY);
+			colRef = ColumnRef();
+			groupBy.add(colRef);
+			label_3: while(true){
+				switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+					case COMMA:
+						;
+						break;
+					default:
+						jj_la1[14] = jj_gen;
+						break label_3;
+				}
+				jj_consume_token(COMMA);
+				colRef = ColumnRef();
+				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_BY);
+			order = OrderItem();
+			orderBy.add(order);
+			label_4: while(true){
+				switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+					case COMMA:
+						;
+						break;
+					default:
+						jj_la1[15] = 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() : jj_ntk){
+				case REGULAR_IDENTIFIER:
+					t = jj_consume_token(REGULAR_IDENTIFIER);
+					{
+						if (true)
+							return new IdentifierItem(t, false);
+					}
+					break;
+				case DELIMITED_IDENTIFIER:
+					t = jj_consume_token(DELIMITED_IDENTIFIER);
+					{
+						if (true)
+							return new IdentifierItem(t, true);
+					}
+					break;
+				default:
+					jj_la1[16] = 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() : jj_ntk){
+				case DOT:
+					jj_consume_token(DOT);
+					id = Identifier();
+					identifiers.append(id);
+					break;
+				default:
+					jj_la1[17] = jj_gen;
+					;
+			}
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case DOT:
+					jj_consume_token(DOT);
+					id = Identifier();
+					identifiers.append(id);
+					break;
+				default:
+					jj_la1[18] = jj_gen;
+					;
+			}
+			{
+				if (true)
+					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() : jj_ntk){
+				case DOT:
+					jj_consume_token(DOT);
+					table = TableName();
+					break;
+				default:
+					jj_la1[19] = jj_gen;
+					;
+			}
+			identifiers.append(id);
+			if (table != null){
+				for(int i = 0; i < table.size(); i++)
+					identifiers.append(table.get(i));
+			}
+			{
+				if (true)
+					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 (true)
+						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 ColumnReference ColumnRef() throws ParseException{
+		trace_call("ColumnRef");
+		try{
+			IdentifierItems identifiers = null;
+			Token ind = null;
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case DELIMITED_IDENTIFIER:
+				case REGULAR_IDENTIFIER:
+					identifiers = ColumnName();
+					break;
+				case UNSIGNED_INTEGER:
+					ind = jj_consume_token(UNSIGNED_INTEGER);
+					break;
+				default:
+					jj_la1[20] = jj_gen;
+					jj_consume_token(-1);
+					throw new ParseException();
+			}
+			try{
+				ColumnReference colRef = null;
+				if (identifiers != null)
+					colRef = queryFactory.createColRef(identifiers);
+				else
+					colRef = queryFactory.createColRef(Integer.parseInt(ind.image), new TextPosition(ind));
+				{
+					if (true)
+						return colRef;
+				}
+			}catch(Exception ex){
+				{
+					if (true)
+						throw generateParseException(ex);
+				}
+			}
+			throw new Error("Missing return statement in function");
+		}finally{
+			trace_return("ColumnRef");
+		}
+	}
+
+	final public ADQLOrder OrderItem() throws ParseException{
+		trace_call("OrderItem");
+		try{
+			IdentifierItems identifiers = null;
+			Token ind = null, desc = null;
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case DELIMITED_IDENTIFIER:
+				case REGULAR_IDENTIFIER:
+					identifiers = ColumnName();
+					break;
+				case UNSIGNED_INTEGER:
+					ind = jj_consume_token(UNSIGNED_INTEGER);
+					break;
+				default:
+					jj_la1[21] = jj_gen;
+					jj_consume_token(-1);
+					throw new ParseException();
+			}
+			switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+				case ASC:
+				case DESC:
+					switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+						case ASC:
+							jj_consume_token(ASC);
+							break;
+						case DESC:
+							desc = jj_consume_token(DESC);
+							break;
+						default:
+							jj_la1[22] = jj_gen;
+							jj_consume_token(-1);
+							throw new ParseException();
+					}
+					break;
+				default:
+					jj_la1[23] = jj_gen;
+					;
+			}
+			try{
+				ADQLOrder order = null;
+				if (identifiers != null){
+					order = queryFactory.createOrder(identifiers, desc != null);
+					order.setPosition(identifiers.getPosition());
+				}else{
+					order = queryFactory.createOrder(Integer.parseInt(ind.image), desc != null);
+					order.setPosition(new TextPosition(ind));
+				}
+				{
+					if (true)
+						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() : jj_ntk){
+					case DELIMITED_IDENTIFIER:
+					case REGULAR_IDENTIFIER:
+						identifiers = TableName();
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case AS:
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+									case AS:
+										jj_consume_token(AS);
+										break;
+									default:
+										jj_la1[24] = jj_gen;
+										;
+								}
+								alias = Identifier();
+								break;
+							default:
+								jj_la1[25] = 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 (true)
+								return content;
+						}
+						break;
+					default:
+						jj_la1[27] = jj_gen;
+						if (jj_2_2(2)){
+							subQuery = SubQueryExpression();
+							switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+								case AS:
+									jj_consume_token(AS);
+									break;
+								default:
+									jj_la1[26] = 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 (true)
+									return content;
+							}
+						}else{
+							switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+											return content;
+									}
+									break;
+								default:
+									jj_la1[28] = 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 (true)
+					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() : jj_ntk){
+					case NATURAL:
+					case INNER:
+					case RIGHT:
+					case LEFT:
+					case FULL:
+					case JOIN:
+						;
+						break;
+					default:
+						jj_la1[29] = jj_gen;
+						break label_6;
+				}
+			}
+			{
+				if (true)
+					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() : jj_ntk){
+					case NATURAL:
+						jj_consume_token(NATURAL);
+						natural = true;
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case INNER:
+							case RIGHT:
+							case LEFT:
+							case FULL:
+								switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+									case INNER:
+										jj_consume_token(INNER);
+										break;
+									case RIGHT:
+									case LEFT:
+									case FULL:
+										switch((jj_ntk == -1) ? jj_ntk() : 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[30] = jj_gen;
+												jj_consume_token(-1);
+												throw new ParseException();
+										}
+										switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+											case OUTER:
+												jj_consume_token(OUTER);
+												break;
+											default:
+												jj_la1[31] = jj_gen;
+												;
+										}
+										break;
+									default:
+										jj_la1[32] = jj_gen;
+										jj_consume_token(-1);
+										throw new ParseException();
+								}
+								break;
+							default:
+								jj_la1[33] = jj_gen;
+								;
+						}
+						jj_consume_token(JOIN);
+						rightTable = TableRef();
+						join = queryFactory.createJoin(type, leftTable, rightTable);
+						join.setPosition(new TextPosition(leftTable.getPosition(), rightTable.getPosition()));
+						{
+							if (true)
+								return join;
+						}
+						break;
+					case INNER:
+					case RIGHT:
+					case LEFT:
+					case FULL:
+					case JOIN:
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case INNER:
+							case RIGHT:
+							case LEFT:
+							case FULL:
+								switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+									case INNER:
+										jj_consume_token(INNER);
+										break;
+									case RIGHT:
+									case LEFT:
+									case FULL:
+										switch((jj_ntk == -1) ? jj_ntk() : 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[34] = jj_gen;
+												jj_consume_token(-1);
+												throw new ParseException();
+										}
+										switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+											case OUTER:
+												jj_consume_token(OUTER);
+												break;
+											default:
+												jj_la1[35] = jj_gen;
+												;
+										}
+										break;
+									default:
+										jj_la1[36] = jj_gen;
+										jj_consume_token(-1);
+										throw new ParseException();
+								}
+								break;
+							default:
+								jj_la1[37] = jj_gen;
+								;
+						}
+						jj_consume_token(JOIN);
+						rightTable = TableRef();
+						switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+										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() : jj_ntk){
+										case COMMA:
+											;
+											break;
+										default:
+											jj_la1[38] = 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 (true)
+										return join;
+								}
+								break;
+							default:
+								jj_la1[39] = jj_gen;
+								jj_consume_token(-1);
+								throw new ParseException();
+						}
+						break;
+					default:
+						jj_la1[40] = 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() : jj_ntk){
+					case STRING_LITERAL:
+						;
+						break;
+					default:
+						jj_la1[41] = jj_gen;
+						break label_8;
+				}
+			}
+			try{
+				cst = queryFactory.createStringConstant(str);
+				cst.setPosition(new TextPosition(start, t));
+				{
+					if (true)
+						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() : 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[42] = jj_gen;
+					jj_consume_token(-1);
+					throw new ParseException();
+			}
+			try{
+				cst = queryFactory.createNumericConstant(t.image);
+				cst.setPosition(new TextPosition(t));
+				{
+					if (true)
+						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() : 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[43] = jj_gen;
+					jj_consume_token(-1);
+					throw new ParseException();
+			}
+			try{
+				cst = queryFactory.createNumericConstant(t.image);
+				cst.setPosition(new TextPosition(t));
+				{
+					if (true)
+						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() : jj_ntk){
+				case PLUS:
+				case MINUS:
+					switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+						case PLUS:
+							sign = jj_consume_token(PLUS);
+							break;
+						case MINUS:
+							sign = jj_consume_token(MINUS);
+							break;
+						default:
+							jj_la1[44] = jj_gen;
+							jj_consume_token(-1);
+							throw new ParseException();
+					}
+					break;
+				default:
+					jj_la1[45] = 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 (true)
+						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() : jj_ntk){
+					case SCIENTIFIC_NUMBER:
+					case UNSIGNED_FLOAT:
+					case UNSIGNED_INTEGER:
+						// unsigned_value_specification
+						op = UnsignedNumeric();
+						{
+							if (true)
+								return op;
+						}
+						break;
+					case DELIMITED_IDENTIFIER:
+					case REGULAR_IDENTIFIER:
+						column = Column();
+						column.setExpectedType('N');
+						{
+							if (true)
+								return column;
+						}
+						break;
+					case AVG:
+					case MAX:
+					case MIN:
+					case SUM:
+					case COUNT:
+						op = SqlFunction();
+						{
+							if (true)
+								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 (true)
+								return wop;
+						}
+						break;
+					default:
+						jj_la1[46] = 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() : jj_ntk){
+					case STRING_LITERAL:
+						// string
+						expr = String();
+						{
+							if (true)
+								return expr;
+						}
+						break;
+					case DELIMITED_IDENTIFIER:
+					case REGULAR_IDENTIFIER:
+						column = Column();
+						column.setExpectedType('S');
+						{
+							if (true)
+								return column;
+						}
+						break;
+					case LEFT_PAR:
+						left = jj_consume_token(LEFT_PAR);
+						op = StringExpression();
+						right = jj_consume_token(RIGHT_PAR);
+						WrappedOperand wop = queryFactory.createWrappedOperand(op);
+						wop.setPosition(new TextPosition(left, right));
+						{
+							if (true)
+								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("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{
+					switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+						case BOX:
+						case CENTROID:
+						case CIRCLE:
+						case POINT:
+						case POLYGON:
+						case REGION:
+							valueExpr = GeometryValueFunction();
+							break;
+						default:
+							jj_la1[48] = jj_gen;
+							if (jj_2_8(2147483647)){
+								valueExpr = Column();
+							}else if (jj_2_9(2147483647)){
+								valueExpr = StringFactor();
+							}else{
+								switch((jj_ntk == -1) ? jj_ntk() : 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 DELIMITED_IDENTIFIER:
+									case REGULAR_IDENTIFIER:
+									case SCIENTIFIC_NUMBER:
+									case UNSIGNED_FLOAT:
+									case UNSIGNED_INTEGER:
+										valueExpr = Factor();
+										break;
+									default:
+										jj_la1[49] = jj_gen;
+										jj_consume_token(-1);
+										throw new ParseException();
+								}
+							}
+					}
+				}
+				{
+					if (true)
+						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() : jj_ntk){
+				case PLUS:
+				case MINUS:
+					switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+					return leftOp;
+			}else{
+				try{
+					Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+					operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
+					{
+						if (true)
+							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() : jj_ntk){
+				case ASTERISK:
+				case DIVIDE:
+					switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+					return leftOp;
+			}else{
+				try{
+					Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+					operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
+					{
+						if (true)
+							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() : jj_ntk){
+				case PLUS:
+				case MINUS:
+					switch((jj_ntk == -1) ? jj_ntk() : 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_10(2)){
+				op = NumericFunction();
+			}else{
+				switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+					case LEFT_PAR:
+					case AVG:
+					case MAX:
+					case MIN:
+					case SUM:
+					case COUNT:
+					case DELIMITED_IDENTIFIER:
+					case REGULAR_IDENTIFIER:
+					case SCIENTIFIC_NUMBER:
+					case UNSIGNED_FLOAT:
+					case UNSIGNED_INTEGER:
+						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 (true)
+					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() : 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 (true)
+					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() : jj_ntk){
+				case COORDSYS:
+					op = ExtractCoordSys();
+					break;
+				default:
+					jj_la1[58] = jj_gen;
+					if (jj_2_11(2)){
+						op = UserDefinedFunction();
+						((UserDefinedFunction)op).setExpectedType('S');
+					}else{
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case LEFT_PAR:
+							case STRING_LITERAL:
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								op = StringValueExpressionPrimary();
+								break;
+							default:
+								jj_la1[59] = jj_gen;
+								jj_consume_token(-1);
+								throw new ParseException();
+						}
+					}
+			}
+			{
+				if (true)
+					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() : jj_ntk){
+				case DELIMITED_IDENTIFIER:
+				case REGULAR_IDENTIFIER:
+					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 (true)
+						return new GeometryValue<GeometryFunction>(col);
+				}
+			}else{
+				if (true)
+					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() : 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() : jj_ntk){
+						case AND:
+						case OR:
+							;
+							break;
+						default:
+							jj_la1[62] = jj_gen;
+							break label_10;
+					}
+					switch((jj_ntk == -1) ? jj_ntk() : 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() : 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 (true)
+					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_12(2147483647)){
+				constraint = Predicate();
+			}else{
+				switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+					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() : 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 (true)
+								return e;
+						}
+						break;
+					default:
+						jj_la1[70] = jj_gen;
+						if (jj_2_14(2147483647)){
+							column = Column();
+							jj_consume_token(IS);
+							switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+									return in;
+							}
+						}else if (jj_2_15(2147483647)){
+							strExpr1 = StringExpression();
+							switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+									return comp;
+							}
+						}else{
+							switch((jj_ntk == -1) ? jj_ntk() : 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 DELIMITED_IDENTIFIER:
+								case REGULAR_IDENTIFIER:
+								case SCIENTIFIC_NUMBER:
+								case UNSIGNED_FLOAT:
+								case UNSIGNED_INTEGER:
+									op = ValueExpression();
+									switch((jj_ntk == -1) ? jj_ntk() : 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_13(2)){
+												constraint = BetweenEnd(op);
+											}else{
+												switch((jj_ntk == -1) ? jj_ntk() : 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 (true)
+					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() : 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 (true)
+						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() : 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 (true)
+						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() : jj_ntk){
+				case NOT:
+					not = jj_consume_token(NOT);
+					break;
+				default:
+					jj_la1[74] = jj_gen;
+					;
+			}
+			start = jj_consume_token(IN);
+			if (jj_2_16(2)){
+				q = SubQueryExpression();
+			}else{
+				switch((jj_ntk == -1) ? jj_ntk() : 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() : 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 (true)
+						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() : jj_ntk){
+					case COUNT:
+						fct = jj_consume_token(COUNT);
+						jj_consume_token(LEFT_PAR);
+						switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){
+							case QUANTIFIER:
+								distinct = jj_consume_token(QUANTIFIER);
+								break;
+							default:
+								jj_la1[77] = jj_gen;
+								;
+						}
+						switch((jj_ntk == -1) ? jj_ntk() : 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 DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+							case SCIENTIFIC_NUMBER:
+							case UNSIGNED_FLOAT:
+							case UNSIGNED_INTEGER:
+								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() : 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() : 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 (true)
+					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 (true)
+					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() : jj_ntk){
+					case CONTAINS:
+					case INTERSECTS:
+						switch((jj_ntk == -1) ? jj_ntk() : 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() : jj_ntk){
+							case POINT:
+								p1 = Point();
+								gf = queryFactory.createCoord1(p1);
+								break;
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								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() : jj_ntk){
+							case POINT:
+								p1 = Point();
+								gf = queryFactory.createCoord2(p1);
+								break;
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								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() : jj_ntk){
+							case POINT:
+								p1 = Point();
+								break;
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								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() : jj_ntk){
+							case POINT:
+								p2 = Point();
+								break;
+							case DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+								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 (true)
+					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 (true)
+					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() : 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() : 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 (true)
+					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 (true)
+						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 (true)
+						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() : 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:
+					fct = UserDefinedFunction();
+					((UserDefinedFunction)fct).setExpectedType('N');
+					break;
+				default:
+					jj_la1[90] = jj_gen;
+					jj_consume_token(-1);
+					throw new ParseException();
+			}
+			{
+				if (true)
+					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() : 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() : 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 DELIMITED_IDENTIFIER:
+							case REGULAR_IDENTIFIER:
+							case SCIENTIFIC_NUMBER:
+							case UNSIGNED_FLOAT:
+							case UNSIGNED_INTEGER:
+								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() : 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() : 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();
+				}
+				if (param1 != null){
+					MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
+					mf.setPosition(new TextPosition(fct, end));
+					{
+						if (true)
+							return mf;
+					}
+				}else{
+					if (true)
+						return null;
+				}
+			}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() : 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{
+				if (param1 != null){
+					MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
+					mf.setPosition(new TextPosition(fct, end));
+					{
+						if (true)
+							return mf;
+					}
+				}else{
+					if (true)
+						return null;
+				}
+			}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);
+			jj_consume_token(LEFT_PAR);
+			switch((jj_ntk == -1) ? jj_ntk() : 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 DELIMITED_IDENTIFIER:
+				case REGULAR_IDENTIFIER:
+				case SCIENTIFIC_NUMBER:
+				case UNSIGNED_FLOAT:
+				case UNSIGNED_INTEGER:
+					op = ValueExpression();
+					params.add(op);
+					label_13: while(true){
+						switch((jj_ntk == -1) ? jj_ntk() : 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);
+			//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 (true)
+						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_3R_104(){
+		if (jj_scan_token(FULL))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_44(){
+		if (jj_scan_token(SELECT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_146(){
+		if (jj_3R_137())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_101(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_123()){
+			jj_scanpos = xsp;
+			if (jj_3R_124()){
+				jj_scanpos = xsp;
+				if (jj_3R_125()){
+					jj_scanpos = xsp;
+					if (jj_3R_126()){
+						jj_scanpos = xsp;
+						if (jj_3R_127()){
+							jj_scanpos = xsp;
+							if (jj_3R_128())
+								return true;
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_152(){
+		if (jj_3R_42())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_144(){
+		if (jj_3R_137())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_113(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_149(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_112(){
+		if (jj_3R_130())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_150(){
+		if (jj_3R_137())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_70(){
+		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;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_16(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_31())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_111(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_135(){
+		if (jj_3R_27())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_110(){
+		if (jj_3R_129())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_148(){
+		if (jj_3R_137())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_107(){
+		if (jj_scan_token(FULL))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_68(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_110()){
+			jj_scanpos = xsp;
+			if (jj_3R_111()){
+				jj_scanpos = xsp;
+				if (jj_3R_112()){
+					jj_scanpos = xsp;
+					if (jj_3R_113())
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_99(){
+		if (jj_scan_token(DISTANCE))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_148()){
+			jj_scanpos = xsp;
+			if (jj_3R_149())
+				return true;
+		}
+		if (jj_scan_token(COMMA))
+			return true;
+		xsp = jj_scanpos;
+		if (jj_3R_150()){
+			jj_scanpos = xsp;
+			if (jj_3R_151())
+				return true;
+		}
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_98(){
+		if (jj_scan_token(COORD2))
+			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(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_97(){
+		if (jj_scan_token(COORD1))
+			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_96(){
+		if (jj_scan_token(AREA))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_114())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_103(){
+		if (jj_scan_token(RIGHT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_154(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(8)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(9))
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_31(){
+		if (jj_3R_44())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_95(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(58)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(59))
+				return true;
+		}
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_114())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_114())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			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_106(){
+		if (jj_scan_token(RIGHT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_55(){
+		Token xsp;
+		xsp = jj_scanpos;
+		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()){
+						jj_scanpos = xsp;
+						if (jj_3R_99())
+							return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_136(){
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_140(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(47)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(48)){
+				jj_scanpos = xsp;
+				if (jj_scan_token(49)){
+					jj_scanpos = xsp;
+					if (jj_scan_token(50))
+						return true;
+				}
+			}
+		}
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		xsp = jj_scanpos;
+		if (jj_scan_token(19))
+			jj_scanpos = xsp;
+		if (jj_3R_42())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_129(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(99)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(100)){
+				jj_scanpos = xsp;
+				if (jj_scan_token(101))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_139(){
+		if (jj_scan_token(COUNT))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(19))
+			jj_scanpos = xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(10)){
+			jj_scanpos = xsp;
+			if (jj_3R_152())
+				return true;
+		}
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_102(){
+		if (jj_scan_token(LEFT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_64(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_102()){
+			jj_scanpos = xsp;
+			if (jj_3R_103()){
+				jj_scanpos = xsp;
+				if (jj_3R_104())
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_45(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(24)){
+			jj_scanpos = xsp;
+			if (jj_3R_64())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_130(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_139()){
+			jj_scanpos = xsp;
+			if (jj_3R_140())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_37(){
+		if (jj_scan_token(STRING_LITERAL))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_22(){
+		Token xsp;
+		if (jj_3R_37())
+			return true;
+		while(true){
+			xsp = jj_scanpos;
+			if (jj_3R_37()){
+				jj_scanpos = xsp;
+				break;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_105(){
+		if (jj_scan_token(LEFT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_65(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_105()){
+			jj_scanpos = xsp;
+			if (jj_3R_106()){
+				jj_scanpos = xsp;
+				if (jj_3R_107())
+					return true;
+			}
+		}
+		xsp = jj_scanpos;
+		if (jj_scan_token(25))
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_46(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(24)){
+			jj_scanpos = xsp;
+			if (jj_3R_65())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_33(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_46())
+			jj_scanpos = xsp;
+		if (jj_scan_token(JOIN))
+			return true;
+		if (jj_3R_47())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_32(){
+		if (jj_scan_token(NATURAL))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_45())
+			jj_scanpos = xsp;
+		if (jj_scan_token(JOIN))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_16(){
+		if (jj_3R_16())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_17(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_32()){
+			jj_scanpos = xsp;
+			if (jj_3R_33())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_26(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(35))
+			jj_scanpos = xsp;
+		if (jj_scan_token(BETWEEN))
+			return true;
+		if (jj_3R_42())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_109(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_13(){
+		if (jj_3R_26())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_3(){
+		if (jj_3R_17())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_47(){
+		if (jj_3R_66())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_15(){
+		if (jj_3R_27())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(35))
+			jj_scanpos = xsp;
+		if (jj_scan_token(LIKE))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_14(){
+		if (jj_3R_21())
+			return true;
+		if (jj_scan_token(IS))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_2(){
+		if (jj_3R_16())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_108(){
+		if (jj_3R_71())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_133(){
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_42())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_66(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_108()){
+			jj_scanpos = xsp;
+			if (jj_3_2()){
+				jj_scanpos = xsp;
+				if (jj_3R_109())
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_25(){
+		if (jj_3R_42())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_12(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(41)){
+			jj_scanpos = xsp;
+			if (jj_3R_25())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_115(){
+		if (jj_3R_42())
+			return true;
+		Token xsp;
+		while(true){
+			xsp = jj_scanpos;
+			if (jj_3R_133()){
+				jj_scanpos = xsp;
+				break;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_52(){
+		if (jj_scan_token(DOT))
+			return true;
+		if (jj_3R_71())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_21(){
+		if (jj_3R_36())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_143(){
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_153())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_142(){
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_153())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_36(){
+		if (jj_3R_14())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_52())
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_120(){
+		if (jj_scan_token(DOT))
+			return true;
+		if (jj_3R_14())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_119(){
+		if (jj_scan_token(DOT))
+			return true;
+		if (jj_3R_14())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_71(){
+		if (jj_3R_14())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_119())
+			jj_scanpos = xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_120())
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_132(){
+		if (jj_3R_101())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_24(){
+		if (jj_scan_token(REGULAR_IDENTIFIER))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_115())
+			jj_scanpos = xsp;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_29(){
+		if (jj_scan_token(DELIMITED_IDENTIFIER))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_28(){
+		if (jj_scan_token(REGULAR_IDENTIFIER))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_141(){
+		if (jj_3R_100())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_14(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_28()){
+			jj_scanpos = xsp;
+			if (jj_3R_29())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_94(){
+		if (jj_scan_token(TAN))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_131(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_93(){
+		if (jj_scan_token(SIN))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_114(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_131()){
+			jj_scanpos = xsp;
+			if (jj_3R_132())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_92(){
+		if (jj_scan_token(COT))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_91(){
+		if (jj_scan_token(COS))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_90(){
+		if (jj_scan_token(ATAN2))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_51(){
+		if (jj_3R_70())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_89(){
+		if (jj_scan_token(ATAN))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			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_88(){
+		if (jj_scan_token(ASIN))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_50(){
+		if (jj_3R_69())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_87(){
+		if (jj_scan_token(ACOS))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_35(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_50()){
+			jj_scanpos = xsp;
+			if (jj_3_11()){
+				jj_scanpos = xsp;
+				if (jj_3R_51())
+					return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_54(){
+		Token xsp;
+		xsp = jj_scanpos;
+		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())
+										return true;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_49(){
+		if (jj_3R_68())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_86(){
+		if (jj_scan_token(TRUNCATE))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_143())
+			jj_scanpos = xsp;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_85(){
+		if (jj_scan_token(SQRT))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_84(){
+		if (jj_scan_token(ROUND))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_142())
+			jj_scanpos = xsp;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_83(){
+		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_82(){
+		if (jj_scan_token(RADIANS))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_81(){
+		if (jj_scan_token(POWER))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_80(){
+		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_79(){
+		if (jj_scan_token(MOD))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_78(){
+		if (jj_scan_token(LOG10))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_77(){
+		if (jj_scan_token(LOG))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_76(){
+		if (jj_scan_token(FLOOR))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_75(){
+		if (jj_scan_token(EXP))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_43(){
+		if (jj_scan_token(CONCAT))
+			return true;
+		if (jj_3R_35())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_74(){
+		if (jj_scan_token(DEGREES))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_73(){
+		if (jj_scan_token(CEILING))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_72(){
+		if (jj_scan_token(ABS))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_27(){
+		if (jj_3R_35())
+			return true;
+		Token xsp;
+		while(true){
+			xsp = jj_scanpos;
+			if (jj_3R_43()){
+				jj_scanpos = xsp;
+				break;
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_53(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_72()){
+			jj_scanpos = xsp;
+			if (jj_3R_73()){
+				jj_scanpos = xsp;
+				if (jj_3R_74()){
+					jj_scanpos = xsp;
+					if (jj_3R_75()){
+						jj_scanpos = xsp;
+						if (jj_3R_76()){
+							jj_scanpos = xsp;
+							if (jj_3R_77()){
+								jj_scanpos = xsp;
+								if (jj_3R_78()){
+									jj_scanpos = xsp;
+									if (jj_3R_79()){
+										jj_scanpos = xsp;
+										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()){
+														jj_scanpos = xsp;
+														if (jj_3R_84()){
+															jj_scanpos = xsp;
+															if (jj_3R_85()){
+																jj_scanpos = xsp;
+																if (jj_3R_86())
+																	return true;
+															}
+														}
+													}
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_67(){
+		if (jj_scan_token(MINUS))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_41(){
+		if (jj_3R_24())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_40(){
+		if (jj_3R_55())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_39(){
+		if (jj_3R_54())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_38(){
+		if (jj_3R_53())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_23(){
+		Token xsp;
+		xsp = jj_scanpos;
+		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())
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_30(){
+		if (jj_3R_14())
+			return true;
+		if (jj_scan_token(DOT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_10(){
+		if (jj_3R_23())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_48(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(8)){
+			jj_scanpos = xsp;
+			if (jj_3R_67())
+				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_30())
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_134(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(10)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(11))
+				return true;
+		}
+		if (jj_3R_121())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_34(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_48())
+			jj_scanpos = xsp;
+		xsp = jj_scanpos;
+		if (jj_3_10()){
+			jj_scanpos = xsp;
+			if (jj_3R_49())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_69(){
+		if (jj_scan_token(COORDSYS))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_114())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_147(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_145(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_138(){
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_19(){
+		if (jj_3R_34())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(8)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(9)){
+				jj_scanpos = xsp;
+				if (jj_scan_token(10)){
+					jj_scanpos = xsp;
+					if (jj_scan_token(11))
+						return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_122(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(8)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(9))
+				return true;
+		}
+		if (jj_3R_100())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_20(){
+		if (jj_3R_35())
+			return true;
+		if (jj_scan_token(CONCAT))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_137(){
+		if (jj_scan_token(POINT))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_135())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_121(){
+		if (jj_3R_34())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_134())
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_128(){
+		if (jj_scan_token(REGION))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_27())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_9(){
+		if (jj_3R_22())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3_8(){
+		if (jj_3R_21())
+			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_3_7(){
+		if (jj_scan_token(REGULAR_IDENTIFIER))
+			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_3_5(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_scan_token(63)){
+			jj_scanpos = xsp;
+			if (jj_3R_20())
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_127(){
+		if (jj_scan_token(POLYGON))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_135())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		Token xsp;
+		while(true){
+			xsp = jj_scanpos;
+			if (jj_3R_138()){
+				jj_scanpos = xsp;
+				break;
+			}
+		}
+		if (jj_scan_token(RIGHT_PAR))
+			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(8)){
+			jj_scanpos = xsp;
+			if (jj_scan_token(9))
+				return true;
+		}
+		return false;
+	}
+
+	private boolean jj_3R_63(){
+		if (jj_3R_34())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_126(){
+		if (jj_3R_137())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_62(){
+		if (jj_3R_35())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_61(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_100(){
+		if (jj_3R_121())
+			return true;
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_122())
+			jj_scanpos = xsp;
+		return false;
+	}
+
+	private boolean jj_3R_60(){
+		if (jj_3R_101())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_59(){
+		if (jj_3R_24())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_58(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_42())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_57(){
+		if (jj_3R_27())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_125(){
+		if (jj_scan_token(CIRCLE))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_135())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_56(){
+		if (jj_3R_100())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_124(){
+		if (jj_scan_token(CENTROID))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_114())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_118(){
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_27())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_123(){
+		if (jj_scan_token(BOX))
+			return true;
+		if (jj_scan_token(LEFT_PAR))
+			return true;
+		if (jj_3R_135())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_136())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(COMMA))
+			return true;
+		if (jj_3R_100())
+			return true;
+		if (jj_scan_token(RIGHT_PAR))
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_117(){
+		if (jj_3R_21())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_42(){
+		Token xsp;
+		xsp = jj_scanpos;
+		if (jj_3R_56()){
+			jj_scanpos = xsp;
+			if (jj_3R_57()){
+				jj_scanpos = xsp;
+				if (jj_3R_58()){
+					jj_scanpos = xsp;
+					if (jj_3R_59()){
+						jj_scanpos = xsp;
+						if (jj_3R_60()){
+							jj_scanpos = xsp;
+							if (jj_3R_61()){
+								jj_scanpos = xsp;
+								if (jj_3R_62()){
+									jj_scanpos = xsp;
+									if (jj_3R_63())
+										return true;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	private boolean jj_3R_116(){
+		if (jj_3R_22())
+			return true;
+		return false;
+	}
+
+	private boolean jj_3R_151(){
+		if (jj_3R_21())
+			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[]{0x41,0x0,0x0,0x0,0x0,0x80000,0x100000,0x20,0x0,0x0,0x400000,0x400,0x304,0x20,0x20,0x20,0x0,0x10,0x10,0x10,0x0,0x0,0x0,0x0,0x400000,0x400000,0x400000,0x0,0x4,0x3d800000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x20,0xc0000000,0x3d800000,0x0,0x0,0x0,0x300,0x300,0x4,0x4,0x0,0x304,0x300,0x300,0xc00,0xc00,0x300,0x300,0x4,0x80,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x3f000,0x0,0x0,0x304,0x3f000,0x0,0x0,0x20,0x4,0x80000,0x704,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x304,0x20,0x20,0x0,0x0,0x20,0x304,};
+	}
+
+	private static void jj_la1_init_1(){
+		jj_la1_1 = new int[]{0x0,0x1,0x400,0x800,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x3f00000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x80000000,0x0,0x3f00000,0x8,0x6,0x6,0x8,0x0,0x8,0x8,0x0,0x108,0x200,0xffff8000,0x0,0x8,0x8,0x0,0x0,0x0,0xffff8000,0x78000,0x0,0xf8000,0xc000000,0x800000,0x800000,0x800000,0x800000,0x7c000000,0x0,0x3f00000,0x7c000000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0xffff8000,};
+	}
+
+	private static void jj_la1_init_2(){
+		jj_la1_2 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,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,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0xffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xffffff,0xffffff,0x0,0x0,0xfffe,0xff0000,0x0,0x20ffffff,};
+	}
+
+	private static void jj_la1_init_3(){
+		jj_la1_3 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x0,0x0,0x3b,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x23,0x23,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x30,0x0,0x0,0x3b,0x3,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x3,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x3,0x3,0x3,0x3,0x0,0x0,0x0,0x2,0x3b,0x0,0x0,0x0,0x0,0x0,0x3b,};
+	}
+
+	final private JJCalls[] jj_2_rtns = new JJCalls[16];
+	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();
+	}
+
+	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(){
+		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[103];
+		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 < 103; 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 < 16; 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;
+						}
+					}
+					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;
+	}
 
 }
diff --git a/src/adql/parser/ADQLQueryFactory.java b/src/adql/parser/ADQLQueryFactory.java
index 4543372ddc2903a5e4d5ccf4bbb7fc7ce4a83a5f..4bcfdf2fbfc8828d34bc123e7001e111eb994c93 100644
--- a/src/adql/parser/ADQLQueryFactory.java
+++ b/src/adql/parser/ADQLQueryFactory.java
@@ -16,7 +16,7 @@ package adql.parser;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -83,7 +83,7 @@ import adql.query.operand.function.geometry.RegionFunction;
  * <p>To customize the object representation you merely have to extends the appropriate functions of this class.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  * 
  * @see ADQLParser
  */
@@ -123,9 +123,6 @@ public class ADQLQueryFactory {
 			caseSensitivity = IdentifierField.ALIAS.setCaseSensitive(caseSensitivity, alias.caseSensitivity);
 		t.setCaseSensitive(caseSensitivity);
 
-		// Set the position in the query:
-		t.setPosition(idItems.getPosition());
-
 		return t;
 	}
 
@@ -387,6 +384,18 @@ public class ADQLQueryFactory {
 		return new IntersectsFunction(left, right);
 	}
 
+	/**
+	 * Replace {@link #createOrder(int, boolean, TextPosition)}.
+	 * @since 1.4
+	 */
+	public ADQLOrder createOrder(final int ind, final boolean desc) throws Exception{
+		return new ADQLOrder(ind, desc);
+	}
+
+	/**
+	 * @deprecated since 1.4 ; Replaced by {@link #createOrder(int, boolean)}
+	 */
+	@Deprecated
 	public ADQLOrder createOrder(final int ind, final boolean desc, final TextPosition position) throws Exception{
 		ADQLOrder order = new ADQLOrder(ind, desc);
 		if (order != null)
@@ -396,10 +405,8 @@ public class ADQLQueryFactory {
 
 	public ADQLOrder createOrder(final IdentifierItems idItems, final boolean desc) throws Exception{
 		ADQLOrder order = new ADQLOrder(idItems.join("."), desc);
-		if (order != null){
-			order.setPosition(idItems.getPosition());
+		if (order != null)
 			order.setCaseSensitive(idItems.getColumnCaseSensitivity());
-		}
 		return order;
 	}
 
diff --git a/src/adql/parser/adqlGrammar.jj b/src/adql/parser/adqlGrammar.jj
index 83ff39080bbb3ea2dbb28f499520aef3a96aaaa2..2b771a931d7b31bf2aca158771222fc4be9c99fa 100644
--- a/src/adql/parser/adqlGrammar.jj
+++ b/src/adql/parser/adqlGrammar.jj
@@ -14,7 +14,7 @@
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institute (ARI)
  */
 
@@ -158,6 +158,7 @@ public class ADQLParser {
 	*/
 	public ADQLParser(java.io.InputStream stream, QueryChecker checker, ADQLQueryFactory factory) {
 		this(stream);
+		setDebug(false);
 		
 		setDebug(false);
 		
@@ -197,6 +198,7 @@ public class ADQLParser {
 	*/
 	public ADQLParser(java.io.InputStream stream, String encoding, QueryChecker checker, ADQLQueryFactory factory) {
 		this(stream, encoding);
+		setDebug(false);
 		
 		queryChecker = checker;
 		
@@ -235,6 +237,7 @@ public class ADQLParser {
 	*/
 	public ADQLParser(java.io.Reader reader, QueryChecker checker, ADQLQueryFactory factory) {
 		this(reader);
+		setDebug(false);
 		
 		setDebug(false);
 		
@@ -273,6 +276,7 @@ public class ADQLParser {
 	*/
 	public ADQLParser(ADQLParserTokenManager tm, QueryChecker checker, ADQLQueryFactory factory) {
 		this(tm);
+		setDebug(false);
 		
 		setDebug(false);
 		
@@ -707,7 +711,7 @@ ADQLQuery Query(): {ADQLQuery q = null;}{
 	}
 }
 
-ADQLQuery QueryExpression(): {} {
+ADQLQuery QueryExpression(): {TextPosition endPos = null;} {
 	{
 		try{
 			// create the query:
@@ -718,12 +722,15 @@ ADQLQuery QueryExpression(): {} {
 		}
 	}
 	Select()
-	From()
-	[Where()]
-	[GroupBy()]
-	[Having()]
-	[OrderBy()]
+	From()     {endPos = query.getFrom().getPosition();}
+	[Where()   {endPos = query.getWhere().getPosition();}]
+	[GroupBy() {endPos = query.getGroupBy().getPosition();}]
+	[Having()  {endPos = query.getHaving().getPosition();}]
+	[OrderBy() {endPos = query.getOrderBy().getPosition();}]
 	{
+		// 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())
@@ -735,13 +742,16 @@ ADQLQuery QueryExpression(): {} {
 	}
 }
 
-ADQLQuery SubQueryExpression(): {ADQLQuery q = null;} {
-	<LEFT_PAR> q=QueryExpression() <RIGHT_PAR>
-	{return q;}
+ADQLQuery SubQueryExpression(): {ADQLQuery q = null; Token start, end;} {
+	start=<LEFT_PAR> q=QueryExpression() end=<RIGHT_PAR>
+	{
+		q.setPosition(new TextPosition(start, end));
+		return q;
+	}
 }
 
-void Select(): {ClauseSelect select = query.getSelect(); SelectItem item=null; Token t = null;} {
-	<SELECT>
+void Select(): {ClauseSelect select = query.getSelect(); SelectItem item=null; Token start,t = null;} {
+	start=<SELECT>
 	[t=<QUANTIFIER> {select.setDistinctColumns(t.image.equalsIgnoreCase("DISTINCT"));}]
 	[<TOP> t=<UNSIGNED_INTEGER>
 	 {
@@ -755,11 +765,20 @@ void Select(): {ClauseSelect select = query.getSelect(); SelectItem item=null; T
 	
 	item=SelectItem() {select.add(item);}
 	(<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));
	}
 }
 
-SelectItem SelectItem(): {IdentifierItems identifiers = new IdentifierItems(true); IdentifierItem id = null, label = null; ADQLOperand op = null;} {
+SelectItem SelectItem(): {IdentifierItems identifiers = new IdentifierItems(true); IdentifierItem id = null, label = null; ADQLOperand op = null; SelectItem item; Token starToken;} {
 	(
-		( <ASTERISK> {return new SelectAllColumns(query);} )
+		( starToken=<ASTERISK>
+		  {
+		    item = new SelectAllColumns(query);
+		    item.setPosition(new TextPosition(starToken));
+		    return item;
+		  }
+		)
 	|LOOKAHEAD(7)
 		(
 			id=Identifier() <DOT> { identifiers.append(id); }
@@ -769,10 +788,13 @@ SelectItem SelectItem(): {IdentifierItems identifiers = new IdentifierItems(true
 					id=Identifier() <DOT> { identifiers.append(id); }
 				)?
 			)?
-			<ASTERISK>
+			starToken=<ASTERISK>
 			{
-				try{;
-					return new SelectAllColumns( queryFactory.createTable(identifiers, null) );
+				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)));
+					return item;
 				}catch(Exception ex) {
 					throw generateParseException(ex);
 				}
@@ -785,9 +807,11 @@ SelectItem SelectItem(): {IdentifierItems identifiers = new IdentifierItems(true
 	
 	{
 		try{
-			SelectItem item = queryFactory.createSelectItem(op, (label==null)?null:label.identifier);
-			if (label != null)
+			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()));
 			return item;
 		}catch(Exception ex){
 			throw generateParseException(ex);
@@ -798,29 +822,45 @@ SelectItem SelectItem(): {IdentifierItems identifiers = new IdentifierItems(true
 void From():{FromContent content = null, content2 = null;}{
 	try{
 		<FROM> content=TableRef()
-		(<COMMA> content2=TableRef() { content = queryFactory.createJoin(JoinType.CROSS, content, content2); } )*
+		(<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){
 		throw generateParseException(ex);
 	}
 }
 
-void Where(): {ClauseConstraints where = query.getWhere(); ADQLConstraint condition;} {
-	<WHERE> ConditionsList(where)
+void Where(): {ClauseConstraints where = query.getWhere(); ADQLConstraint condition; Token start;} {
+	start=<WHERE> ConditionsList(where)
+	{
+	  TextPosition endPosition = where.getPosition();
+	  where.setPosition(new TextPosition(start.beginLine, start.beginColumn, endPosition.endLine, endPosition.endColumn));
+	}
 }
 
-void GroupBy(): {ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); ColumnReference colRef = null;} {
-	<GROUP_BY> colRef=ColumnRef() { groupBy.add(colRef); }
+void GroupBy(): {ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); ColumnReference colRef = null; Token start;} {
+	start=<GROUP_BY> colRef=ColumnRef() { groupBy.add(colRef); }
 	( <COMMA> colRef=ColumnRef() { groupBy.add(colRef); } )*
+	{ groupBy.setPosition(new TextPosition(start.beginLine, start.beginColumn, colRef.getPosition().endLine, colRef.getPosition().endColumn)); }
 }
 
-void Having(): {ClauseConstraints having = query.getHaving();} {
-	<HAVING> ConditionsList(having)
+void Having(): {ClauseConstraints having = query.getHaving(); Token start;} {
+	start=<HAVING> ConditionsList(having)
+	{
+	  TextPosition endPosition = having.getPosition();
+	  having.setPosition(new TextPosition(start.beginLine, start.beginColumn, endPosition.endLine, endPosition.endColumn));
+	}
 }
 
-void OrderBy(): {ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); ADQLOrder order = null;} {
-	<ORDER_BY> order=OrderItem() {orderBy.add(order);}
+void OrderBy(): {ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); ADQLOrder order = null; Token start;} {
+	start=<ORDER_BY> order=OrderItem() {orderBy.add(order);}
 	( <COMMA> order=OrderItem() {orderBy.add(order);} )*
+	{ orderBy.setPosition(new TextPosition(start, token)); }
 }
 
 /* *************************** */
@@ -899,10 +939,13 @@ ADQLOrder OrderItem(): {IdentifierItems identifiers = null; Token ind = null, de
 	{
 		try{
 			ADQLOrder order = null;
-			if (identifiers != null)
+			if (identifiers != null){
 				order = queryFactory.createOrder(identifiers, desc!=null);
-			else
-				order = queryFactory.createOrder(Integer.parseInt(ind.image), desc!=null, new TextPosition(ind));
+				order.setPosition(identifiers.getPosition());
+			}else{
+				order = queryFactory.createOrder(Integer.parseInt(ind.image), desc!=null);
+				order.setPosition(new TextPosition(ind));
+			}
 			return order;
 		}catch(Exception ex){
 			throw generateParseException(ex);
@@ -910,17 +953,34 @@ ADQLOrder OrderItem(): {IdentifierItems identifiers = null; Token ind = null, de
 	}
 }
 
-FromContent SimpleTableRef(): {IdentifierItem alias = null; IdentifierItems identifiers = null; ADQLQuery subQuery = null; FromContent content = null;} {
+FromContent SimpleTableRef(): {IdentifierItem alias = null; IdentifierItems identifiers = null; ADQLQuery subQuery = null; FromContent content = null; Token start,end;} {
 	try{
 		(
 			identifiers=TableName() [[<AS>] alias=Identifier()]
-			{ return queryFactory.createTable(identifiers, alias); }
+			{
+			  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));
+			  return content;
+			}
 		|LOOKAHEAD(2)
 			subQuery=SubQueryExpression() [<AS>] alias=Identifier()
-			{ return queryFactory.createTable(subQuery, alias); }
+			{
+			  content = queryFactory.createTable(subQuery, alias);
+			  if (alias == null)
+			  	content.setPosition(new TextPosition(subQuery.getPosition()));
+			  else
+			  	content.setPosition(new TextPosition(subQuery.getPosition(), alias.position));
+			  return content;
+			}
 		|
-			<LEFT_PAR> content=JoinedTable() <RIGHT_PAR>
-			{ return content; }
+			start=<LEFT_PAR> content=JoinedTable() end=<RIGHT_PAR>
+			{
+			  content.setPosition(new TextPosition(start, end));
+			  return content;
+			}
 		)
 	}catch(Exception ex){
 		throw generateParseException(ex);
@@ -940,24 +1000,36 @@ FromContent JoinedTable(): { FromContent content; } {
 }
 
 
-ADQLJoin JoinSpecification(FromContent leftTable): { boolean natural = false; JoinType type = JoinType.INNER;  ClauseConstraints condition = new ClauseConstraints("ON"); ArrayList<ADQLColumn> lstColumns=new ArrayList<ADQLColumn>(); IdentifierItem id; FromContent rightTable;} {
+ADQLJoin JoinSpecification(FromContent leftTable): { 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{
 		(
 			<NATURAL> {natural=true;} [<INNER> | ((<LEFT> {type = JoinType.OUTER_LEFT;}|<RIGHT> {type = JoinType.OUTER_RIGHT;}|<FULL> {type = JoinType.OUTER_FULL;}) [<OUTER>])] <JOIN> rightTable=TableRef()
-			{ return queryFactory.createJoin(type, leftTable, rightTable); }
+			{
+			  join = queryFactory.createJoin(type, leftTable, rightTable);
+			  join.setPosition(new TextPosition(leftTable.getPosition(), rightTable.getPosition()));
+			  return join;
+			}
 		|
 			[<INNER> | ((<LEFT> {type = JoinType.OUTER_LEFT;}|<RIGHT> {type = JoinType.OUTER_RIGHT;}|<FULL> {type = JoinType.OUTER_FULL;}) [<OUTER>])] <JOIN> rightTable=TableRef()
 			(
 				<ON> ConditionsList(condition)
-				{ return queryFactory.createJoin(type, leftTable, rightTable, condition); }
+				{
+				  join = queryFactory.createJoin(type, leftTable, rightTable, condition);
+				  join.setPosition(new TextPosition(leftTable.getPosition(), condition.getPosition()));
+				  return join;
+				}
 			|
 				<USING> <LEFT_PAR> id=Identifier()
 						{ lstColumns.add( queryFactory.createColumn(id) ); }
 						(
 							<COMMA> id=Identifier()
 							{ lstColumns.add( queryFactory.createColumn(id) ); }
-						)* <RIGHT_PAR>
-				{ return queryFactory.createJoin(type, leftTable, rightTable, lstColumns); }
+						)* lastPar=<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)));
+				  return join;
+				}
 			)
 		)
 	}catch(Exception ex){
@@ -968,68 +1040,108 @@ ADQLJoin JoinSpecification(FromContent leftTable): { boolean natural = false; Jo
 /* ****** */
 /* STRING */
 /* ****** */
-String String(): {Token t; String str="";} {
-	(t=<STRING_LITERAL> {str += t.image.substring(1,t.image.length()-1).replaceAll("''", "'");})+
-	{return str;}
+StringConstant String(): {Token t, start=null; String str=""; StringConstant cst;} {
+	(t=<STRING_LITERAL>
+	 {
+	   	str += t.image.substring(1, t.image.length()-1).replaceAll("''", "'");
+	   	if (start == null)
+	   		start = t;
+	 }
+	)+
+	{
+		try{
+		  cst = queryFactory.createStringConstant(str);
+		  cst.setPosition(new TextPosition(start, t));
+		  return cst;
+		}catch(Exception ex){
+			throw generateParseException(ex);
+		}
+	}
 }
 
 /* ************* */
 /* NUMERIC TYPES */
 /* ************* */
-String UnsignedNumeric(): {Token t;} {
+NumericConstant UnsignedNumeric(): {Token t; NumericConstant cst;} {
 	(t=<SCIENTIFIC_NUMBER>
 	| t=<UNSIGNED_FLOAT>
 	| t=<UNSIGNED_INTEGER>)
-	{return t.image;}
+	{		try{
+		  cst = queryFactory.createNumericConstant(t.image);
+		  cst.setPosition(new TextPosition(t));
+		  return cst;
+		}catch(Exception ex){
+			throw generateParseException(ex);
+		}
+	}
 }
 
-String UnsignedFloat(): {Token t;} {
+NumericConstant UnsignedFloat(): {Token t; NumericConstant cst;} {
 	(t=<UNSIGNED_INTEGER>
 	| t=<UNSIGNED_FLOAT>)
-	{return t.image;}
+	{
+		try{
+			cst = queryFactory.createNumericConstant(t.image);
+		  	cst.setPosition(new TextPosition(t));
+			return cst;
+		}catch(Exception ex){
+			throw generateParseException(ex);
+		}
+	}
 }
 
-String SignedInteger(): {Token sign=null, number;} {
+NumericConstant SignedInteger(): {Token sign=null, number; NumericConstant cst;} {
 	((sign=<PLUS>|sign=<MINUS>)? number=<UNSIGNED_INTEGER>)
-	{return ((sign==null)?"":sign.image)+number.image;}
+	{
+		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));
+		 	}
+		 	return cst;
+		}catch(Exception ex){
+			throw generateParseException(ex);
+		}
+	}
 }
 
 /* *********** */
 /* EXPRESSIONS */
 /* *********** */
-ADQLOperand NumericValueExpressionPrimary(): {String expr; ADQLColumn column; ADQLOperand op;} {
+ADQLOperand NumericValueExpressionPrimary(): {ADQLColumn column; ADQLOperand op; Token left, right;} {
 	try{
 		(// unsigned_value_specification
-		  expr=UnsignedNumeric() {return queryFactory.createNumericConstant(expr);}
+		  op=UnsignedNumeric() {return op;}
 		// column_reference
 		| column=Column() {column.setExpectedType('N'); return column;}
 		// set_function_specification
 		| op=SqlFunction() {return op;}
 		// LEFT_PAR value_expression RIGHT_PAR
-		| (<LEFT_PAR> op=NumericExpression() <RIGHT_PAR>) {return queryFactory.createWrappedOperand(op);})
+		| (left=<LEFT_PAR> op=NumericExpression() right=<RIGHT_PAR>) { WrappedOperand wop = queryFactory.createWrappedOperand(op); wop.setPosition(new TextPosition(left, right)); return wop; })
 	}catch(Exception ex){
 		throw generateParseException(ex);
 	}
 }
 
-ADQLOperand StringValueExpressionPrimary(): {String expr; ADQLColumn column; ADQLOperand op;} {
+ADQLOperand StringValueExpressionPrimary(): {StringConstant expr; ADQLColumn column; ADQLOperand op; Token left, right;} {
 	try{
 		(// string
-		  expr=String() {return queryFactory.createStringConstant(expr);}
+		  expr=String() {return expr;}
 		// column_reference
 		| column=Column() {column.setExpectedType('S'); return column;}
 		// LEFT_PAR value_expression RIGHT_PAR
-		| (<LEFT_PAR> (op=StringExpression()) <RIGHT_PAR>) {return queryFactory.createWrappedOperand(op);})
+		| (left=<LEFT_PAR> (op=StringExpression()) right=<RIGHT_PAR>) { WrappedOperand wop = queryFactory.createWrappedOperand(op); wop.setPosition(new TextPosition(left, right)); return wop; })
 	}catch(Exception ex){
 		throw generateParseException(ex);
 	}
 }
 
-ADQLOperand ValueExpression(): {ADQLOperand valueExpr = null; } {
+ADQLOperand ValueExpression(): {ADQLOperand valueExpr = null; Token left, right; } {
 	try{
 		(LOOKAHEAD((<PLUS>|<MINUS>) | (Factor() (<PLUS>|<MINUS>|<ASTERISK>|<DIVIDE>))) valueExpr=NumericExpression()
 		| LOOKAHEAD(<COORDSYS> | (StringFactor() <CONCAT>)) valueExpr=StringExpression()
-		| LOOKAHEAD(<LEFT_PAR>) <LEFT_PAR> valueExpr=ValueExpression() <RIGHT_PAR> { valueExpr = queryFactory.createWrappedOperand(valueExpr); }
+		| LOOKAHEAD(<LEFT_PAR>) left=<LEFT_PAR> valueExpr=ValueExpression() right=<RIGHT_PAR> { valueExpr = queryFactory.createWrappedOperand(valueExpr); ((WrappedOperand)valueExpr).setPosition(new TextPosition(left, right)); }
 		| LOOKAHEAD(<REGULAR_IDENTIFIER> <LEFT_PAR>) valueExpr=UserDefinedFunction()
 		| valueExpr=GeometryValueFunction()
 		| LOOKAHEAD(Column()) valueExpr=Column()
@@ -1048,7 +1160,9 @@ ADQLOperand NumericExpression(): {Token sign=null; ADQLOperand leftOp, rightOp=n
 		return leftOp;
 	else{
 		try{
-			return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+			Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+			operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
+			return operation;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
@@ -1063,7 +1177,9 @@ ADQLOperand NumericTerm(): {Token sign=null; ADQLOperand leftOp, rightOp=null;}
 		return leftOp;
 	else{
 		try{
-			return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+			Operation operation = queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp);
+			operation.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
+			return operation;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
@@ -1071,16 +1187,22 @@ ADQLOperand NumericTerm(): {Token sign=null; ADQLOperand leftOp, rightOp=null;}
 	}
 }
 
-ADQLOperand Factor(): {boolean negative = false;; ADQLOperand op;} {
+ADQLOperand Factor(): {boolean negative = false; Token minusSign = null; ADQLOperand op;} {
 	(
-		(<PLUS> | (<MINUS> {negative = true;}))?
+		(<PLUS> | (minusSign=<MINUS> {negative = true;}))?
 		(LOOKAHEAD(2) op=NumericFunction() | op=NumericValueExpressionPrimary())
 	)
 	
 	{
 		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){
 				throw generateParseException(ex);
 			}
@@ -1108,7 +1230,12 @@ ADQLOperand StringExpression(): {ADQLOperand leftOp; ADQLOperand rightOp = null;
 			((Concatenation)leftOp).add(rightOp);
 		}
 	)*
-	{ return leftOp; }
+	{
+		if (leftOp instanceof Concatenation){
+			Concatenation concat = (Concatenation)leftOp;
			concat.setPosition(new TextPosition(concat.get(0).getPosition(), concat.get(concat.size()-1).getPosition()));
+		}
+	  return leftOp;
+	}
 }
 
 ADQLOperand StringFactor(): {ADQLOperand op;} {
@@ -1133,11 +1260,15 @@ GeometryValue<GeometryFunction> GeometryExpression(): {ADQLColumn col = null; Ge
 /* ********************************** */
 ClauseConstraints ConditionsList(ClauseConstraints clause): {ADQLConstraint constraint = null; Token op = null; boolean notOp = false;} {
 	try{
-		[<NOT> {notOp = true;}]
+		[op=<NOT> {notOp = true;}]
 		constraint=Constraint()
 		{
-			if (notOp) constraint = queryFactory.createNot(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
@@ -1148,8 +1279,13 @@ ClauseConstraints ConditionsList(ClauseConstraints clause): {ADQLConstraint cons
 			[<NOT> {notOp = true;}]
 			constraint=Constraint()
 			{
-				if (notOp) constraint = queryFactory.createNot(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
@@ -1159,13 +1295,19 @@ ClauseConstraints ConditionsList(ClauseConstraints clause): {ADQLConstraint cons
 	}catch(Exception ex){
 		throw generateParseException(ex);
 	}
-	{return clause;}
+	{
+	  	if (!clause.isEmpty()){
	  		TextPosition start = clause.get(0).getPosition();
+	  		TextPosition end = clause.get(clause.size()-1).getPosition();
+			clause.setPosition(new TextPosition(start, end));
+		}
+		return clause;
+	}
 }
 
-ADQLConstraint Constraint(): {ADQLConstraint constraint =  null;} {
-	(LOOKAHEAD(Predicate()) constraint=Predicate()
+ADQLConstraint Constraint(): {ADQLConstraint constraint =  null; Token start, end;} {
+	(LOOKAHEAD(<EXISTS> | ValueExpression()) constraint=Predicate()
 	| (
-		<LEFT_PAR>
+		start=<LEFT_PAR>
 		{
 			try{
 				constraint = queryFactory.createGroupOfConstraints();
@@ -1174,19 +1316,39 @@ ADQLConstraint Constraint(): {ADQLConstraint constraint =  null;} {
 			}
 		}
 		ConditionsList((ConstraintsGroup)constraint)
-		<RIGHT_PAR>
+		end=<RIGHT_PAR>
+		{ ((ConstraintsGroup)constraint).setPosition(new TextPosition(start, end)); }
 	))
 	{return constraint;}
 }
 
-ADQLConstraint Predicate(): {ADQLQuery q=null; ADQLColumn column=null; ADQLOperand strExpr1=null, strExpr2=null; ADQLOperand op; Token notToken = null; ADQLConstraint constraint = null;} {
+ADQLConstraint Predicate(): {ADQLQuery q=null; ADQLColumn column=null; ADQLOperand strExpr1=null, strExpr2=null; ADQLOperand op; Token start, notToken = null, end; ADQLConstraint constraint = null;} {
 	try{
 		// exists_predicate
-		((<EXISTS> q=SubQueryExpression()) {return queryFactory.createExists(q);}
+		(
+		  (start=<EXISTS> q=SubQueryExpression()
+			{
+			  Exists e = queryFactory.createExists(q);
+			  e.setPosition(new TextPosition(start.beginLine, start.beginColumn, q.getPosition().endLine, q.getPosition().endColumn));
+			  return e;
+			}
+		  )
 		// null_predicate
-		| LOOKAHEAD(Column() <IS>)(column=Column() <IS> [notToken=<NOT>] <NULL> {return queryFactory.createIsNull((notToken!=null), column);})
+		| LOOKAHEAD(Column() <IS>)(column=Column() <IS> [notToken=<NOT>] end=<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)));
+		      return in;
+		    }
+		   )
 		// like_predicate
-		| LOOKAHEAD(StringExpression() [<NOT>] <LIKE>) (strExpr1=StringExpression() [notToken=<NOT>] <LIKE> strExpr2=StringExpression() {return queryFactory.createComparison(strExpr1, (notToken==null)?ComparisonOperator.LIKE:ComparisonOperator.NOTLIKE, strExpr2);})
+		| LOOKAHEAD(StringExpression() [<NOT>] <LIKE>) (strExpr1=StringExpression() [notToken=<NOT>] <LIKE> strExpr2=StringExpression()
+		    {
+		      Comparison comp = queryFactory.createComparison(strExpr1, (notToken==null)?ComparisonOperator.LIKE:ComparisonOperator.NOTLIKE, strExpr2);
+		      comp.setPosition(new TextPosition(strExpr1.getPosition(), strExpr2.getPosition()));
+		      return comp;
+		    }
+		  )
 		| (op=ValueExpression()
 			(// comparison_predicate
 			(constraint=ComparisonEnd(op))
@@ -1195,7 +1357,8 @@ ADQLConstraint Predicate(): {ADQLQuery q=null; ADQLColumn column=null; ADQLOpera
 			// in_predicate
 			| constraint=InEnd(op)
 			)
-		))
+		  )
+		)
 	}catch(Exception ex){
 		throw generateParseException(ex);
 	}
@@ -1206,39 +1369,49 @@ Comparison ComparisonEnd(ADQLOperand leftOp): {Token comp; ADQLOperand rightOp;}
 	((comp=<EQUAL> | comp=<NOT_EQUAL> | comp=<LESS_THAN> | comp=<LESS_EQUAL_THAN> | comp=<GREATER_THAN> | comp=<GREATER_EQUAL_THAN>) rightOp=ValueExpression())
 	{
 		try{
-			return queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp);
+		  	Comparison comparison = queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp);
+		  	comparison.setPosition(new TextPosition(leftOp.getPosition(), rightOp.getPosition()));
+			return comparison;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
 	}
 }
 
-Between BetweenEnd(ADQLOperand leftOp): {Token notToken=null; ADQLOperand min, max;} {
-	[notToken=<NOT>] <BETWEEN> min=ValueExpression() <AND> max=ValueExpression()
+Between BetweenEnd(ADQLOperand leftOp): {Token start,notToken=null; ADQLOperand min, max;} {
+	[notToken=<NOT>] start=<BETWEEN> min=ValueExpression() <AND> max=ValueExpression()
 	{
 		try{
-			return queryFactory.createBetween((notToken!=null), leftOp, min, max);
+		  	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));
+			return bet;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
 	}
 }
 
-In InEnd(ADQLOperand leftOp): {Token not=null; ADQLQuery q = null; ADQLOperand item; Vector<ADQLOperand> items = new Vector<ADQLOperand>();} {
-	[not=<NOT>] <IN>
+In InEnd(ADQLOperand leftOp): {Token not=null, start; ADQLQuery q = null; ADQLOperand item; Vector<ADQLOperand> items = new Vector<ADQLOperand>();} {
+	[not=<NOT>] start=<IN>
 	(LOOKAHEAD(2) q=SubQueryExpression()
 	| (<LEFT_PAR> item=ValueExpression() {items.add(item);} (<COMMA> item=ValueExpression() {items.add(item);})* <RIGHT_PAR>))
 	{
 		try{
-			if (q != null)
-				return queryFactory.createIn(leftOp, q, not!=null);
-			else{
+		  	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;
-				return queryFactory.createIn(leftOp, list, not!=null);
+				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));
 			}
+			return in;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
@@ -1249,14 +1422,20 @@ In InEnd(ADQLOperand leftOp): {Token not=null; ADQLQuery q = null; ADQLOperand i
 /* ************* */
 /* SQL FUNCTIONS */
 /* ************* */
-SQLFunction SqlFunction(): {Token fct, all=null, distinct=null; ADQLOperand op=null; SQLFunction funct = null;}{
+SQLFunction SqlFunction(): {Token fct, all=null, distinct=null, end; ADQLOperand op=null; SQLFunction funct = null;}{
 	try{
 		(
-			(<COUNT> <LEFT_PAR> [distinct=<QUANTIFIER>] (all=<ASTERISK> | op=ValueExpression()) <RIGHT_PAR>
-			{ funct = queryFactory.createSQLFunction((all!=null)?SQLFunctionType.COUNT_ALL:SQLFunctionType.COUNT, op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); })
+			(fct=<COUNT> <LEFT_PAR> [distinct=<QUANTIFIER>] (all=<ASTERISK> | op=ValueExpression()) end=<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));
+			})
 		|
-			((fct=<AVG> | fct=<MAX> | fct=<MIN> | fct=<SUM>) <LEFT_PAR> [distinct=<QUANTIFIER>] op=ValueExpression() <RIGHT_PAR> 
-			{ funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); })
+			((fct=<AVG> | fct=<MAX> | fct=<MIN> | fct=<SUM>) <LEFT_PAR> [distinct=<QUANTIFIER>] op=ValueExpression() end=<RIGHT_PAR> 
+			{
+			  funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct"));
+			  funct.setPosition(new TextPosition(fct, end));
+			})
 		)
 	}catch(Exception ex){
 		throw generateParseException(ex);
@@ -1273,22 +1452,22 @@ ADQLOperand[] Coordinates(): {ADQLOperand[] ops = new ADQLOperand[2];} {
 	{return ops;}
 }
 
-GeometryFunction GeometryFunction(): {Token t=null; GeometryValue<GeometryFunction> gvf1, gvf2; GeometryValue<PointFunction> gvp1, gvp2; GeometryFunction gf = null; PointFunction p1=null, p2=null; ADQLColumn col1 = null, col2 = null;} {
+GeometryFunction GeometryFunction(): {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{
 		// predicate_geometry_function
 		(
-			((t=<CONTAINS> | t=<INTERSECTS>) <LEFT_PAR> gvf1=GeometryExpression() <COMMA> gvf2=GeometryExpression() <RIGHT_PAR>
+			((fct=<CONTAINS> | fct=<INTERSECTS>) <LEFT_PAR> gvf1=GeometryExpression() <COMMA> gvf2=GeometryExpression() end=<RIGHT_PAR>
 			{
-				if (t.image.equalsIgnoreCase("contains"))
+				if (fct.image.equalsIgnoreCase("contains"))
 					gf = queryFactory.createContains(gvf1, gvf2);
 				else
 					gf = queryFactory.createIntersects(gvf1, gvf2);
 			})
 		// non_predicate_geometry_function
-		|	(<AREA> <LEFT_PAR> gvf1=GeometryExpression() <RIGHT_PAR>) {gf = queryFactory.createArea(gvf1);}
-		|	(<COORD1> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord1(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord1(col1);}) <RIGHT_PAR>)
-		|	(<COORD2> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord2(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord2(col1);}) <RIGHT_PAR>)
-		|	(<DISTANCE>
+		|	(fct=<AREA> <LEFT_PAR> gvf1=GeometryExpression() end=<RIGHT_PAR>) {gf = queryFactory.createArea(gvf1);}
+		|	(fct=<COORD1> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord1(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord1(col1);}) end=<RIGHT_PAR>)
+		|	(fct=<COORD2> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord2(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord2(col1);}) end=<RIGHT_PAR>)
+		|	(fct=<DISTANCE>
 				<LEFT_PAR>
 				(p1=Point()|col1=Column()) 
 				{
@@ -1307,7 +1486,7 @@ GeometryFunction GeometryFunction(): {Token t=null; GeometryValue<GeometryFuncti
 						gvp2 = new GeometryValue<PointFunction>(col2);
 					}
 				} 
-				<RIGHT_PAR>
+				end=<RIGHT_PAR>
 				{gf = queryFactory.createDistance(gvp1, gvp2);}
 			)
 		)
@@ -1315,7 +1494,10 @@ GeometryFunction GeometryFunction(): {Token t=null; GeometryValue<GeometryFuncti
 		throw generateParseException(ex);
 	}
 	
-	{ return gf; }
+	{
+	  gf.setPosition(new TextPosition(fct, end));
+	  return gf;
+	}
 }
 
 ADQLOperand CoordinateSystem(): { ADQLOperand coordSys=null;}{
@@ -1323,62 +1505,70 @@ ADQLOperand CoordinateSystem(): { ADQLOperand coordSys=null;}{
 	{ return coordSys; }
 }
 
-GeometryFunction GeometryValueFunction(): {ADQLOperand coordSys; ADQLOperand width, height; ADQLOperand[] coords, tmp; Vector<ADQLOperand> vCoords; ADQLOperand op=null; GeometryValue<GeometryFunction> gvf = null; GeometryFunction gf = null;} {
+GeometryFunction GeometryValueFunction(): {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{
 		// BOX:
-		((<BOX> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
+		((fct=<BOX> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
 				<COMMA> coords=Coordinates() // coordinates
-				<COMMA> width=NumericExpression() <COMMA> height=NumericExpression() <RIGHT_PAR>)
+				<COMMA> width=NumericExpression() <COMMA> height=NumericExpression() end=<RIGHT_PAR>)
 		 {gf = queryFactory.createBox(coordSys, coords[0], coords[1], width, height);}
 		 
 		// CENTROID:
-		| (<CENTROID> <LEFT_PAR> gvf=GeometryExpression() <RIGHT_PAR>) {gf = queryFactory.createCentroid(gvf);}
+		| (fct=<CENTROID> <LEFT_PAR> gvf=GeometryExpression() end=<RIGHT_PAR>) {gf = queryFactory.createCentroid(gvf);}
 		
 		// CIRCLE:
-		| (<CIRCLE> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
+		| (fct=<CIRCLE> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
 				<COMMA> coords=Coordinates() // coordinates
-				<COMMA> width=NumericExpression() <RIGHT_PAR>) // radius
+				<COMMA> width=NumericExpression() end=<RIGHT_PAR>) // radius
 		 {gf = queryFactory.createCircle(coordSys, coords[0], coords[1], width);}
 		
 		// POINT: 
 		| gf=Point()
 		
 		// POLYGON:
-		| (<POLYGON> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
+		| (fct=<POLYGON> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
 				{ vCoords = new Vector<ADQLOperand>(); } // coordinates
 				<COMMA> tmp=Coordinates() {vCoords.add(tmp[0]); vCoords.add(tmp[1]);}
 				<COMMA> tmp=Coordinates() {vCoords.add(tmp[0]); vCoords.add(tmp[1]);}
 				<COMMA> tmp=Coordinates() {vCoords.add(tmp[0]); vCoords.add(tmp[1]);}
 				(<COMMA> tmp=Coordinates() {vCoords.add(tmp[0]); vCoords.add(tmp[1]);})*
-				<RIGHT_PAR>)
+				end=<RIGHT_PAR>)
 		  { gf = queryFactory.createPolygon(coordSys, vCoords); }
 		  
 		// REGION:
-		| (<REGION> <LEFT_PAR> op=StringExpression() <RIGHT_PAR>) {gf = queryFactory.createRegion(op);})
+		| (fct=<REGION> <LEFT_PAR> op=StringExpression() end=<RIGHT_PAR>) {gf = queryFactory.createRegion(op);})
 	}catch(Exception ex){
 		throw generateParseException(ex);
 	}
 	
-	{return gf;}
+	{
+	  if (fct != null && end != null) // = !(gf instanceof Point)
+	  	gf.setPosition(new TextPosition(fct, end));
+	  return gf;
+	}
 }
 
-PointFunction Point(): {ADQLOperand coordSys; ADQLOperand[] coords;} {
-	<POINT> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
-			<COMMA> coords=Coordinates() <RIGHT_PAR> // coordinates
+PointFunction Point(): {Token start, end; ADQLOperand coordSys; ADQLOperand[] coords;} {
+	start=<POINT> <LEFT_PAR> coordSys=CoordinateSystem() // coord_sys
+			<COMMA> coords=Coordinates() end=<RIGHT_PAR> // coordinates
 	{
 		try{
-			return queryFactory.createPoint(coordSys, coords[0], coords[1]);
+			PointFunction pf = queryFactory.createPoint(coordSys, coords[0], coords[1]);
+			pf.setPosition(new TextPosition(start, end));
+			return pf;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
 	}
 }
 
-GeometryFunction ExtractCoordSys(): {GeometryValue<GeometryFunction> gvf;} {
-	<COORDSYS> <LEFT_PAR> gvf=GeometryExpression() <RIGHT_PAR>
+GeometryFunction ExtractCoordSys(): {Token start, end; GeometryValue<GeometryFunction> gvf;} {
+	start=<COORDSYS> <LEFT_PAR> gvf=GeometryExpression() end=<RIGHT_PAR>
 	{
 		try{
-			return queryFactory.createExtractCoordSys(gvf);
+			GeometryFunction gf = queryFactory.createExtractCoordSys(gvf);
+			gf.setPosition(new TextPosition(start, end));
+			return gf;
 		}catch(Exception ex){
 			throw generateParseException(ex);
 		}
@@ -1396,27 +1586,28 @@ ADQLFunction NumericFunction(): {ADQLFunction fct;} {
 	{return fct;}
 }
 
-MathFunction MathFunction(): {Token fct=null; ADQLOperand param1=null, param2=null; String integerValue = null;} {
+MathFunction MathFunction(): {Token fct=null, end; ADQLOperand param1=null, param2=null; NumericConstant integerValue = null;} {
 	try{
-		((fct=<ABS> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<CEILING> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<DEGREES> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<EXP> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<FLOOR> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<LOG> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<LOG10> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<MOD> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() <RIGHT_PAR>)
-		| (fct=<PI> <LEFT_PAR><RIGHT_PAR>)
-		| (fct=<POWER> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() <RIGHT_PAR>)
-		| (fct=<RADIANS> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<RAND> <LEFT_PAR> (param1=NumericExpression())? <RIGHT_PAR>)
-		| (fct=<ROUND> <LEFT_PAR> param1=NumericExpression() (<COMMA> integerValue=SignedInteger() {param2 = queryFactory.createNumericConstant(integerValue);})? <RIGHT_PAR>)
-		| (fct=<SQRT> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-		| (fct=<TRUNCATE> <LEFT_PAR> param1=NumericExpression() (<COMMA> integerValue=SignedInteger() {param2 = queryFactory.createNumericConstant(integerValue);})? <RIGHT_PAR>))
+		((fct=<ABS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<CEILING> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<DEGREES> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<EXP> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<FLOOR> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<LOG> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<LOG10> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<MOD> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<PI> <LEFT_PAR> end=<RIGHT_PAR>)
+		| (fct=<POWER> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<RADIANS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<RAND> <LEFT_PAR> (param1=NumericExpression())? end=<RIGHT_PAR>)
+		| (fct=<ROUND> <LEFT_PAR> param1=NumericExpression() (<COMMA> param2=SignedInteger())? end=<RIGHT_PAR>)
+		| (fct=<SQRT> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+		| (fct=<TRUNCATE> <LEFT_PAR> param1=NumericExpression() (<COMMA> param2=SignedInteger())? end=<RIGHT_PAR>))
 		{
-			if (param1 != null)
-				return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
-			else
+			if (param1 != null){
			  	MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
+			  	mf.setPosition(new TextPosition(fct, end));
+				return mf;
+			}else
 				return null;
 		}
 	}catch(Exception ex){
@@ -1424,20 +1615,21 @@ MathFunction MathFunction(): {Token fct=null; ADQLOperand param1=null, param2=nu
 	}
 }
 
-MathFunction TrigFunction(): {Token fct=null; ADQLOperand param1=null, param2=null;} {
-	((fct=<ACOS> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<ASIN> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<ATAN> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<ATAN2> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() <RIGHT_PAR>)
-	| (fct=<COS> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<COT> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<SIN> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>)
-	| (fct=<TAN> <LEFT_PAR> param1=NumericExpression() <RIGHT_PAR>))
+MathFunction TrigFunction(): {Token fct=null, end; ADQLOperand param1=null, param2=null;} {
+	((fct=<ACOS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<ASIN> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<ATAN> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<ATAN2> <LEFT_PAR> param1=NumericExpression() <COMMA> param2=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<COS> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<COT> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<SIN> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>)
+	| (fct=<TAN> <LEFT_PAR> param1=NumericExpression() end=<RIGHT_PAR>))
 	{
 		try{
-			if (param1 != null)
-				return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
-			else
+			if (param1 != null){
			  	MathFunction mf = queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2);
+			  	mf.setPosition(new TextPosition(fct, end));
+			  	return mf;
+			}else
 				return null;
 		}catch(Exception ex){
 			throw generateParseException(ex);
@@ -1445,8 +1637,8 @@ MathFunction TrigFunction(): {Token fct=null; ADQLOperand param1=null, param2=nu
 	}
 }
 
-UserDefinedFunction UserDefinedFunction(): {Token fct; Vector<ADQLOperand> params = new Vector<ADQLOperand>(); ADQLOperand op;} {
-	fct=<REGULAR_IDENTIFIER> <LEFT_PAR> (op=ValueExpression() {params.add(op);} (<COMMA> op=ValueExpression() {params.add(op);})*)? <RIGHT_PAR>
+UserDefinedFunction UserDefinedFunction(): {Token fct, end; Vector<ADQLOperand> params = new Vector<ADQLOperand>(); ADQLOperand op;} {
+	fct=<REGULAR_IDENTIFIER> <LEFT_PAR> (op=ValueExpression() {params.add(op);} (<COMMA> op=ValueExpression() {params.add(op);})*)? end=<RIGHT_PAR>
 	{
 		//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{
@@ -1454,9 +1646,10 @@ UserDefinedFunction UserDefinedFunction(): {Token fct; Vector<ADQLOperand> param
 			ADQLOperand[] parameters = new ADQLOperand[params.size()];
 			for(int i=0; i<params.size(); i++)
 				parameters[i] = params.get(i);
-
 			// Create the UDF function:
-			return queryFactory.createUserDefinedFunction(fct.image, parameters);
+			UserDefinedFunction udf = queryFactory.createUserDefinedFunction(fct.image, parameters);
+			udf.setPosition(new TextPosition(fct, end));
+			return udf;
 		}catch(UnsupportedOperationException uoe){
 		  	/* This catch clause is just for backward compatibility:
 		  	 * if the createUserDefinedFunction(...) is overridden and
diff --git a/src/adql/query/ADQLList.java b/src/adql/query/ADQLList.java
index 68c93a19bedc6e973a513dc89aa0a00103bbb5d0..2ffdaee06d4c6305c100cbdf76006c28d9c4d5cd 100644
--- a/src/adql/query/ADQLList.java
+++ b/src/adql/query/ADQLList.java
@@ -16,7 +16,7 @@ package adql.query;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -29,7 +29,7 @@ import java.util.Vector;
  * <p>Since it is a list, it is possible to add, remove, modify and iterate on a such object.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 2.2 (10/2014)
+ * @version 1.4 (06/2015)
  * 
  * @see ClauseADQL
  * @see ClauseConstraints
@@ -44,6 +44,10 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	/** List of ADQL items. */
 	private final Vector<T> list = new Vector<T>();
 
+	/** Position inside an ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds an ADQLList with only its name. This name will always prefix the list.
 	 * 
@@ -71,6 +75,7 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 		this(toCopy.getName());
 		for(T obj : toCopy)
 			add((T)obj.getCopy());
+		position = (toCopy.position != null) ? new TextPosition(toCopy.position) : null;
 	}
 
 	/**
@@ -83,8 +88,13 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	public boolean add(T item) throws NullPointerException{
 		if (item == null)
 			throw new NullPointerException("It is impossible to add NULL items to an ADQL clause !");
-		else
-			return list.add(item);
+		else{
+			if (list.add(item)){
+				position = null;
+				return true;
+			}else
+				return false;
+		}
 	}
 
 	/**
@@ -96,9 +106,10 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	 * @throws ArrayIndexOutOfBoundsException	If the index is out of range (index < 0 || index > size()).
 	 */
 	public void add(int index, T item) throws NullPointerException, ArrayIndexOutOfBoundsException{
-		if (item != null)
+		if (item != null){
 			list.add(index, item);
-		else
+			position = null;
+		}else
 			throw new NullPointerException("It is impossible to add NULL items to an ADQL clause !");
 	}
 
@@ -112,9 +123,11 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	 * @throws ArrayIndexOutOfBoundsException	If the index is out of range (index < 0 || index > size()).
 	 */
 	public T set(int index, T item) throws NullPointerException, ArrayIndexOutOfBoundsException{
-		if (item != null)
-			return list.set(index, item);
-		else
+		if (item != null){
+			T removed = list.set(index, item);
+			position = null;
+			return removed;
+		}else
 			throw new NullPointerException("It is impossible to replace an ADQL item by a NULL item into an ADQL clause !");
 	}
 
@@ -137,7 +150,10 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	 * @throws ArrayIndexOutOfBoundsException	If the index is out of range (index < 0 || index > size()).
 	 */
 	public T remove(int index) throws ArrayIndexOutOfBoundsException{
-		return list.remove(index);
+		T removed = list.remove(index);
+		if (removed != null)
+			position = null;
+		return removed;
 	}
 
 	/**
@@ -145,6 +161,7 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 	 */
 	public void clear(){
 		list.clear();
+		position = null;
 	}
 
 	/**
@@ -170,6 +187,21 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It
 		return name;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Sets the position at which this {@link ADQLList} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link ADQLList}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	@Override
 	public String toADQL(){
 		StringBuffer adql = new StringBuffer((getName() == null) ? "" : (getName() + " "));
diff --git a/src/adql/query/ADQLObject.java b/src/adql/query/ADQLObject.java
index 40776cf1f72171205e5835b031dab3a3a1f0d166..fee5aef5963ff5f522f752312858dd4f9f593a37 100644
--- a/src/adql/query/ADQLObject.java
+++ b/src/adql/query/ADQLObject.java
@@ -18,7 +18,8 @@ import adql.search.ISearchHandler;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 /**
@@ -26,12 +27,13 @@ import adql.search.ISearchHandler;
  * <ul>
  * 	<li>to have a name in ADQL</i>
  * 	<li>to be written in ADQL</li>
- * 	<li>to offer a way to search any ADQL item <i>(included itself)</i>.</li>
+ * 	<li>to offer a way to search any ADQL item <i>(included itself)</i></li>
+ * 	<li>to get its position in the original ADQL query.</li>
  * </ul>
  * </p>
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 01/2012
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public interface ADQLObject {
 
@@ -42,6 +44,17 @@ public interface ADQLObject {
 	 */
 	public String getName();
 
+	/**
+	 * <p>Gets the position of this object/token in the ADQL query.</p>
+	 * <p><i>By default, no position should be set.</i></p>
+	 * 
+	 * @return	Position of this ADQL item in the ADQL query,
+	 *          or NULL if not written originally in the query (for example, if added afterwards.
+	 * 
+	 * @since 1.4
+	 */
+	public TextPosition getPosition();
+
 	/**
 	 * Gets the ADQL expression of this object.
 	 * 
diff --git a/src/adql/query/ADQLQuery.java b/src/adql/query/ADQLQuery.java
index 95725e4859a72b761739af9a21aa114fb7e8a354..1372e716fed3a0cdd5f46028dd7606b9ce84c6e1 100644
--- a/src/adql/query/ADQLQuery.java
+++ b/src/adql/query/ADQLQuery.java
@@ -16,7 +16,7 @@ package adql.query;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -38,7 +38,7 @@ import adql.search.ISearchHandler;
  * <p>The resulting object of the {@link ADQLParser} is an object of this class.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.2 (09/2014)
+ * @version 1.4 (06/2015)
  */
 public class ADQLQuery implements ADQLObject {
 
@@ -60,6 +60,10 @@ public class ADQLQuery implements ADQLObject {
 	/** The ADQL clause ORDER BY. */
 	private ClauseADQL<ADQLOrder> orderBy;
 
+	/** Position of this Query (or sub-query) inside the whole given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds an empty ADQL query.
 	 */
@@ -86,6 +90,7 @@ public class ADQLQuery implements ADQLObject {
 		groupBy = (ClauseADQL<ColumnReference>)toCopy.groupBy.getCopy();
 		having = (ClauseConstraints)toCopy.having.getCopy();
 		orderBy = (ClauseADQL<ADQLOrder>)toCopy.orderBy.getCopy();
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -101,6 +106,7 @@ public class ADQLQuery implements ADQLObject {
 		groupBy.clear();
 		having.clear();
 		orderBy.clear();
+		position = null;
 	}
 
 	/**
@@ -113,7 +119,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its SELECT clause by the given one.
+	 * <p>Replaces its SELECT clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newSelect					The new SELECT clause.
 	 * 
@@ -124,6 +132,7 @@ public class ADQLQuery implements ADQLObject {
 			throw new NullPointerException("Impossible to replace the SELECT clause of a query by NULL !");
 		else
 			select = newSelect;
+		position = null;
 	}
 
 	/**
@@ -136,7 +145,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its FROM clause by the given one.
+	 * <p>Replaces its FROM clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newFrom					The new FROM clause.
 	 * 
@@ -147,6 +158,7 @@ public class ADQLQuery implements ADQLObject {
 			throw new NullPointerException("Impossible to replace the FROM clause of a query by NULL !");
 		else
 			from = newFrom;
+		position = null;
 	}
 
 	/**
@@ -159,7 +171,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its WHERE clause by the given one.
+	 * <p>Replaces its WHERE clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newWhere					The new WHERE clause.
 	 * 
@@ -170,6 +184,7 @@ public class ADQLQuery implements ADQLObject {
 			where.clear();
 		else
 			where = newWhere;
+		position = null;
 	}
 
 	/**
@@ -182,7 +197,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its GROUP BY clause by the given one.
+	 * <p>Replaces its GROUP BY clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newGroupBy				The new GROUP BY clause.
 	 * @throws NullPointerException		If the given GROUP BY clause is <i>null</i>.
@@ -192,6 +209,7 @@ public class ADQLQuery implements ADQLObject {
 			groupBy.clear();
 		else
 			groupBy = newGroupBy;
+		position = null;
 	}
 
 	/**
@@ -204,7 +222,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its HAVING clause by the given one.
+	 * <p>Replaces its HAVING clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newHaving					The new HAVING clause.
 	 * @throws NullPointerException		If the given HAVING clause is <i>null</i>.
@@ -214,6 +234,7 @@ public class ADQLQuery implements ADQLObject {
 			having.clear();
 		else
 			having = newHaving;
+		position = null;
 	}
 
 	/**
@@ -226,7 +247,9 @@ public class ADQLQuery implements ADQLObject {
 	}
 
 	/**
-	 * Replaces its ORDER BY clause by the given one.
+	 * <p>Replaces its ORDER BY clause by the given one.</p>
+	 * 
+	 * <p><i>note: the position of the query is erased.</i></p>
 	 * 
 	 * @param newOrderBy				The new ORDER BY clause.
 	 * @throws NullPointerException		If the given ORDER BY clause is <i>null</i>.
@@ -236,6 +259,22 @@ public class ADQLQuery implements ADQLObject {
 			orderBy.clear();
 		else
 			orderBy = newOrderBy;
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link ADQLQuery} (or sub-query) inside the whole given ADQL query string.
+	 * 
+	 * @param position New position of this {@link ADQLQuery}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
 	}
 
 	@Override
@@ -392,6 +431,7 @@ public class ADQLQuery implements ADQLObject {
 								throw new UnsupportedOperationException("Impossible to replace a ClauseADQL (" + orderBy.toADQL() + ") by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 							break;
 					}
+					position = null;
 				}
 			}
 
@@ -402,8 +442,10 @@ public class ADQLQuery implements ADQLObject {
 
 				if (index == 0 || index == 1)
 					throw new UnsupportedOperationException("Impossible to remove a " + ((index == 0) ? "SELECT" : "FROM") + " clause from a query !");
-				else
+				else{
 					currentClause.clear();
+					position = null;
+				}
 			}
 		};
 	}
@@ -428,4 +470,4 @@ public class ADQLQuery implements ADQLObject {
 		return adql.toString();
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/SelectAllColumns.java b/src/adql/query/SelectAllColumns.java
index fec54b9d1aad3d7abd413102abc3044a3b80dfb5..33dc27ed0ea5979c11d61e1214b6262edae19ab8 100644
--- a/src/adql/query/SelectAllColumns.java
+++ b/src/adql/query/SelectAllColumns.java
@@ -20,7 +20,7 @@ import adql.query.from.ADQLTable;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -29,7 +29,7 @@ import adql.query.from.ADQLTable;
  * It means: 'select all columns'.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.2 (09/2014)
+ * @version 1.4 (06/2015)
  */
 public final class SelectAllColumns extends SelectItem {
 
@@ -88,6 +88,7 @@ public final class SelectAllColumns extends SelectItem {
 		if (query != null){
 			this.query = query;
 			adqlTable = null;
+			setPosition(null);
 		}
 	}
 
@@ -110,6 +111,7 @@ public final class SelectAllColumns extends SelectItem {
 		if (table != null){
 			adqlTable = table;
 			query = null;
+			setPosition(null);
 		}
 	}
 
@@ -150,8 +152,10 @@ public final class SelectAllColumns extends SelectItem {
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
 				else if (!(replacer instanceof ADQLTable))
 					throw new IllegalStateException("Impossible to replace an ADQLTable by a " + replacer.getClass().getName() + " !");
-				else
+				else{
 					adqlTable = (ADQLTable)replacer;
+					setPosition(null);
+				}
 			}
 
 			@Override
diff --git a/src/adql/query/SelectItem.java b/src/adql/query/SelectItem.java
index 595e762482a24502ce2db1bd7eb89d86e120b6eb..803101abca0ce66a7b11dde618c107a1d127ab03 100644
--- a/src/adql/query/SelectItem.java
+++ b/src/adql/query/SelectItem.java
@@ -16,7 +16,8 @@ package adql.query;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
@@ -28,8 +29,8 @@ import adql.query.operand.ADQLOperand;
  * 
  * <p>It merely encapsulates an operand and allows to associate to it an alias (according to the following syntax: "SELECT operand AS alias").</p>
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 01/2012
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  * 
  * @see ClauseSelect
  */
@@ -44,6 +45,10 @@ public class SelectItem implements ADQLObject {
 	/** Indicates whether the alias is case sensitive (if yes, the alias is written between double-quotes). */
 	private boolean caseSensitive = false;
 
+	/** Position of this Select item in the ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds a SELECT item just with an operand.
 	 * 
@@ -77,6 +82,7 @@ public class SelectItem implements ADQLObject {
 			operand = null;
 		alias = toCopy.getAlias();
 		caseSensitive = toCopy.caseSensitive;
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -112,6 +118,8 @@ public class SelectItem implements ADQLObject {
 	 * @param newAlias	The new alias of the operand.
 	 */
 	public final void setAlias(String newAlias){
+		if (alias == null && newAlias != null || alias != null && newAlias == null || alias != null && !alias.equals(newAlias))
+			position = null;
 		alias = newAlias;
 		caseSensitive = false;
 
@@ -120,6 +128,7 @@ public class SelectItem implements ADQLObject {
 			a.trimToSize();
 			if (a.length() == 0){
 				alias = null;
+				position = null;
 				return;
 			}else if (a.length() > 1 && a.charAt(0) == '\"' && a.charAt(a.length() - 1) == '\"'){
 				a.deleteCharAt(0);
@@ -127,6 +136,7 @@ public class SelectItem implements ADQLObject {
 				a.trimToSize();
 				if (a.length() == 0){
 					alias = null;
+					position = null;
 					return;
 				}
 				caseSensitive = true;
@@ -153,19 +163,38 @@ public class SelectItem implements ADQLObject {
 		caseSensitive = sensitive;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link SelectItem} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link SelectItem}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new SelectItem(this);
 	}
 
+	@Override
 	public String getName(){
 		return hasAlias() ? alias : operand.getName();
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private boolean operandGot = (operand == null);
 
+			@Override
 			public ADQLObject next() throws NoSuchElementException{
 				if (operandGot)
 					throw new NoSuchElementException();
@@ -173,10 +202,12 @@ public class SelectItem implements ADQLObject {
 				return operand;
 			}
 
+			@Override
 			public boolean hasNext(){
 				return !operandGot;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (replacer == null)
 					remove();
@@ -184,10 +215,13 @@ public class SelectItem implements ADQLObject {
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
 				else if (!(replacer instanceof ADQLOperand))
 					throw new IllegalStateException("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " !");
-				else
+				else{
 					operand = (ADQLOperand)replacer;
+					position = null;
+				}
 			}
 
+			@Override
 			public void remove(){
 				if (!operandGot)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -197,6 +231,7 @@ public class SelectItem implements ADQLObject {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		StringBuffer adql = new StringBuffer(operand.toADQL());
 		if (hasAlias()){
diff --git a/src/adql/query/TextPosition.java b/src/adql/query/TextPosition.java
index e7d086aa64e47dc19cf36207904307e7f0debcaa..5324ebab077160eed2e873d290f21779ad2161f8 100644
--- a/src/adql/query/TextPosition.java
+++ b/src/adql/query/TextPosition.java
@@ -16,7 +16,8 @@ package adql.query;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import adql.parser.Token;
@@ -25,8 +26,8 @@ import adql.parser.Token;
  * Indicates a simple position or a token/string position in a text.
  * It is particularly used to localize columns and tables in the original ADQL query.
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 01/2012
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class TextPosition {
 
@@ -71,7 +72,7 @@ public class TextPosition {
 	}
 
 	/**
-	 * Builds a position whose the end line and column are unknown => a simple position.
+	 * Builds a position defining the region delimited by the given token.
 	 * 
 	 * @param token	The position will be the one of this token.
 	 */
@@ -89,6 +90,27 @@ public class TextPosition {
 		this(beginToken.beginLine, beginToken.beginColumn, endToken.endLine, (endToken.endColumn < 0) ? -1 : (endToken.endColumn + 1));
 	}
 
+	/**
+	 * Builds a copy of the given position.
+	 * 
+	 * @param positionToCopy	Position to copy.
+	 * @since 1.4
+	 */
+	public TextPosition(final TextPosition positionToCopy){
+		this(positionToCopy.beginLine, positionToCopy.beginColumn, positionToCopy.endLine, positionToCopy.endColumn);
+	}
+
+	/**
+	 * Builds a position whose the start is the start position of the first parameter and the end is the end position of the second parameter.
+	 * 
+	 * @param startPos	Start position (only beginLine and beginColumn will be used).
+	 * @param endPos	End position (only endLine and endColumn will be used).
+	 * @since 1.4
+	 */
+	public TextPosition(final TextPosition startPos, final TextPosition endPos){
+		this(startPos.beginLine, startPos.beginColumn, endPos.endLine, endPos.endColumn);
+	}
+
 	@Override
 	public String toString(){
 		if (beginLine == -1 && beginColumn == -1)
diff --git a/src/adql/query/constraint/Between.java b/src/adql/query/constraint/Between.java
index 28cecbd4ba60221013da2eefd92c275cd4cd3da1..d321f1829430c05e831609469bedc78674ace2c7 100644
--- a/src/adql/query/constraint/Between.java
+++ b/src/adql/query/constraint/Between.java
@@ -16,14 +16,15 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
-
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
@@ -32,8 +33,8 @@ import adql.query.operand.ADQLOperand;
  * <p>This predicate returns <i>true</i> if the value of the left operand is
  * between the value of the two other operands, else it returns <i>false</i>.</p>
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class Between implements ADQLConstraint {
 
@@ -49,6 +50,10 @@ public class Between implements ADQLConstraint {
 	/** Indicates which predicate must be used: BETWEEN (<i>false</i>) or NOT BETWEEN (<i>true</i>). */
 	private boolean notBetween = false;
 
+	/** Position of this {@link Between} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds a BETWEEN constraints.
 	 * 
@@ -87,6 +92,7 @@ public class Between implements ADQLConstraint {
 		setLeftOperand((ADQLOperand)toCopy.leftOperand.getCopy());
 		setMinOperand((ADQLOperand)toCopy.minOperand.getCopy());
 		setMaxOperand((ADQLOperand)toCopy.maxOperand.getCopy());
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -106,6 +112,7 @@ public class Between implements ADQLConstraint {
 	 */
 	public void setLeftOperand(ADQLOperand leftOperand) throws NullPointerException{
 		this.leftOperand = leftOperand;
+		position = null;
 	}
 
 	/**
@@ -125,6 +132,7 @@ public class Between implements ADQLConstraint {
 	 */
 	public void setMinOperand(ADQLOperand minOperand) throws NullPointerException{
 		this.minOperand = minOperand;
+		position = null;
 	}
 
 	/**
@@ -144,6 +152,7 @@ public class Between implements ADQLConstraint {
 	 */
 	public void setMaxOperand(ADQLOperand maxOperand) throws NullPointerException{
 		this.maxOperand = maxOperand;
+		position = null;
 	}
 
 	/**
@@ -162,21 +171,41 @@ public class Between implements ADQLConstraint {
 	 */
 	public void setNotBetween(boolean notBetween){
 		this.notBetween = notBetween;
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link Between} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link Between}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
 	}
 
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new Between(this);
 	}
 
+	@Override
 	public String getName(){
 		return (isNotBetween() ? "NOT " : "") + "BETWEEN";
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private int index = -1;
 
+			@Override
 			public ADQLObject next(){
 				switch(++index){
 					case 0:
@@ -190,10 +219,12 @@ public class Between implements ADQLConstraint {
 				}
 			}
 
+			@Override
 			public boolean hasNext(){
 				return index + 1 < 3;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (index <= -1)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
@@ -212,10 +243,12 @@ public class Between implements ADQLConstraint {
 							maxOperand = (ADQLOperand)replacer;
 							break;
 					}
+					position = null;
 				}else
 					throw new UnsupportedOperationException("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 			}
 
+			@Override
 			public void remove(){
 				if (index <= -1)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -225,6 +258,7 @@ public class Between implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return leftOperand.toADQL() + " " + getName() + " " + minOperand.toADQL() + " AND " + maxOperand.toADQL();
 	}
diff --git a/src/adql/query/constraint/Comparison.java b/src/adql/query/constraint/Comparison.java
index 8aeab2e2e1e1444d31003bcb9e2339307cf22907..1c0d23612d974b0f68b23c412734c4f3dae94af8 100644
--- a/src/adql/query/constraint/Comparison.java
+++ b/src/adql/query/constraint/Comparison.java
@@ -16,20 +16,22 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
  * Represents a comparison (numeric or not) between two operands.
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  * 
  * @see ComparisonOperator
  */
@@ -44,6 +46,10 @@ public class Comparison implements ADQLConstraint {
 	/** The right part of the comparison. */
 	private ADQLOperand rightOperand;
 
+	/** Position of this {@link Comparison} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Creates a comparison between two operands.
 	 * 
@@ -73,6 +79,7 @@ public class Comparison implements ADQLConstraint {
 		leftOperand = (ADQLOperand)toCopy.leftOperand.getCopy();
 		compOperator = toCopy.compOperator;
 		rightOperand = (ADQLOperand)toCopy.rightOperand.getCopy();
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -100,6 +107,7 @@ public class Comparison implements ADQLConstraint {
 			throw new UnsupportedOperationException("Impossible to update the left operand of the comparison (" + toADQL() + ") with \"" + newLeftOperand.toADQL() + "\" because the comparison operator " + compOperator.toADQL() + " is not applicable on numeric operands !");
 
 		leftOperand = newLeftOperand;
+		position = null;
 	}
 
 	/**
@@ -125,6 +133,7 @@ public class Comparison implements ADQLConstraint {
 			throw new UnsupportedOperationException("Impossible to update the comparison operator" + ((compOperator != null) ? (" (" + compOperator.toADQL() + ")") : "") + " by " + newOperation.toADQL() + " because the two operands (\"" + leftOperand.toADQL() + "\" & \"" + rightOperand.toADQL() + "\") are not all Strings !");
 
 		compOperator = newOperation;
+		position = null;
 	}
 
 	/**
@@ -152,21 +161,41 @@ public class Comparison implements ADQLConstraint {
 			throw new UnsupportedOperationException("Impossible to update the right operand of the comparison (" + toADQL() + ") with \"" + newRightOperand.toADQL() + "\" because the comparison operator " + compOperator.toADQL() + " is not applicable on numeric operands !");
 
 		rightOperand = newRightOperand;
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link Comparison} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link Comparison}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
 	}
 
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new Comparison(this);
 	}
 
+	@Override
 	public String getName(){
 		return compOperator.toADQL();
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private int index = -1;
 
+			@Override
 			public ADQLObject next(){
 				index++;
 				if (index == 0)
@@ -177,10 +206,12 @@ public class Comparison implements ADQLConstraint {
 					throw new NoSuchElementException();
 			}
 
+			@Override
 			public boolean hasNext(){
 				return index + 1 < 2;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (index <= -1)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
@@ -188,14 +219,18 @@ public class Comparison implements ADQLConstraint {
 				if (replacer == null)
 					remove();
 				else if (replacer instanceof ADQLOperand){
-					if (index == 0)
+					if (index == 0){
 						leftOperand = (ADQLOperand)replacer;
-					else if (index == 1)
+						position = null;
+					}else if (index == 1){
 						rightOperand = (ADQLOperand)replacer;
+						position = null;
+					}
 				}else
 					throw new UnsupportedOperationException("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " in a comparison !");
 			}
 
+			@Override
 			public void remove(){
 				if (index <= -1)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -205,6 +240,7 @@ public class Comparison implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return ((leftOperand == null) ? "NULL" : leftOperand.toADQL()) + " " + ((compOperator == null) ? "NULL" : compOperator.toADQL()) + " " + ((rightOperand == null) ? "NULL" : rightOperand.toADQL());
 	}
diff --git a/src/adql/query/constraint/Exists.java b/src/adql/query/constraint/Exists.java
index 363588ff01bd554ab862411ce7abb0c4e0129a20..52af88f7d327cab45a7cce7c8b2048d17c020815 100644
--- a/src/adql/query/constraint/Exists.java
+++ b/src/adql/query/constraint/Exists.java
@@ -16,7 +16,8 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
@@ -24,20 +25,25 @@ import java.util.NoSuchElementException;
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
 import adql.query.ADQLQuery;
+import adql.query.TextPosition;
 
 /**
  * <p>Represents the predicate EXISTS of SQL and ADQL.</p>
  * 
  * <p>This function returns <i>true</i> if the sub-query given in parameter returns at least one result, else it returns <i>false</i>.</p>
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class Exists implements ADQLConstraint {
 
 	/** The sub-query. */
 	private ADQLQuery subQuery;
 
+	/** Position of this {@link Exists} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds an Exists constraint instance.
 	 * 
@@ -55,6 +61,7 @@ public class Exists implements ADQLConstraint {
 	 */
 	public Exists(Exists toCopy) throws Exception{
 		subQuery = (ADQLQuery)toCopy.subQuery.getCopy();
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -75,23 +82,44 @@ public class Exists implements ADQLConstraint {
 	public void setSubQuery(ADQLQuery query) throws NullPointerException{
 		if (query == null)
 			throw new NullPointerException("Impossible to build an EXISTS constraint with a sub-query NULL !");
-		else
+		else{
 			subQuery = query;
+			position = null;
+		}
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
 	}
 
+	/**
+	 * Set the position of this {@link Exists} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link Exists}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new Exists(this);
 	}
 
+	@Override
 	public String getName(){
 		return "EXISTS";
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private boolean subQueryGot = (subQuery == null);
 
+			@Override
 			public ADQLObject next(){
 				if (subQueryGot)
 					throw new NoSuchElementException();
@@ -99,22 +127,26 @@ public class Exists implements ADQLConstraint {
 				return subQuery;
 			}
 
+			@Override
 			public boolean hasNext(){
 				return !subQueryGot;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (!subQueryGot)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
 
 				if (replacer == null)
 					remove();
-				else if (replacer instanceof ADQLQuery)
+				else if (replacer instanceof ADQLQuery){
 					subQuery = (ADQLQuery)replacer;
-				else
+					position = null;
+				}else
 					throw new UnsupportedOperationException("Impossible to replace an ADQLQuery by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 			}
 
+			@Override
 			public void remove(){
 				if (!subQueryGot)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -124,6 +156,7 @@ public class Exists implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return getName() + "(" + subQuery.toADQL() + ")";
 	}
diff --git a/src/adql/query/constraint/In.java b/src/adql/query/constraint/In.java
index 2ea7ffa10727f19d2530130f0cda0a0a442415b2..67f37e4d6228f3a5ce28ee8c00d0ed65f5a60715 100644
--- a/src/adql/query/constraint/In.java
+++ b/src/adql/query/constraint/In.java
@@ -16,7 +16,8 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
@@ -26,7 +27,7 @@ import adql.query.ADQLList;
 import adql.query.ADQLObject;
 import adql.query.ADQLQuery;
 import adql.query.ClauseADQL;
-
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
@@ -35,8 +36,8 @@ import adql.query.operand.ADQLOperand;
  * <p>This predicate returns <i>true</i> if the value of the given operand is
  * either in the given values list or in the results of the given sub-query, else it returns <i>false</i>.</p>
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class In implements ADQLConstraint {
 
@@ -52,6 +53,10 @@ public class In implements ADQLConstraint {
 	/** IN or NOT IN ? */
 	private boolean notIn = false;
 
+	/** Position of this {@link In} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds an IN constraint with a sub-query.
 	 * 
@@ -141,6 +146,7 @@ public class In implements ADQLConstraint {
 		else
 			setValuesList((ADQLList<ADQLOperand>)toCopy.list.getCopy());
 		notIn = toCopy.notIn;
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -161,8 +167,10 @@ public class In implements ADQLConstraint {
 	public void setOperand(ADQLOperand newLeftOp) throws NullPointerException{
 		if (newLeftOp == null)
 			throw new NullPointerException("Impossible to set a left operand NULL in an IN constraint !");
-		else
+		else{
 			leftOp = newLeftOp;
+			position = null;
+		}
 	}
 
 	/**
@@ -195,6 +203,7 @@ public class In implements ADQLConstraint {
 		else{
 			list = null;
 			subQuery = newSubQuery;
+			position = null;
 		}
 	}
 
@@ -221,6 +230,7 @@ public class In implements ADQLConstraint {
 			list = new ClauseADQL<ADQLOperand>();
 			for(int i = 0; i < valuesList.length; i++)
 				list.add(valuesList[i]);
+			position = null;
 		}
 	}
 
@@ -236,6 +246,7 @@ public class In implements ADQLConstraint {
 		else{
 			subQuery = null;
 			list = valuesList;
+			position = null;
 		}
 	}
 
@@ -255,21 +266,41 @@ public class In implements ADQLConstraint {
 	 */
 	public void setNotIn(boolean notIn){
 		this.notIn = notIn;
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link In} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link In}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
 	}
 
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new In(this);
 	}
 
+	@Override
 	public String getName(){
 		return notIn ? "NOT IN" : "IN";
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private int index = -1;
 
+			@Override
 			public ADQLObject next(){
 				index++;
 				if (index == 0)
@@ -280,10 +311,12 @@ public class In implements ADQLConstraint {
 					throw new NoSuchElementException();
 			}
 
+			@Override
 			public boolean hasNext(){
 				return index + 1 < 2;
 			}
 
+			@Override
 			@SuppressWarnings("unchecked")
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (index <= -1)
@@ -293,20 +326,24 @@ public class In implements ADQLConstraint {
 					remove();
 
 				if (index == 0){
-					if (replacer instanceof ADQLOperand)
+					if (replacer instanceof ADQLOperand){
 						leftOp = (ADQLOperand)replacer;
-					else
+						position = null;
+					}else
 						throw new UnsupportedOperationException("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 				}else if (index == 1){
-					if (hasSubQuery() && replacer instanceof ADQLQuery)
+					if (hasSubQuery() && replacer instanceof ADQLQuery){
 						subQuery = (ADQLQuery)replacer;
-					else if (!hasSubQuery() && replacer instanceof ADQLList)
+						position = null;
+					}else if (!hasSubQuery() && replacer instanceof ADQLList){
 						list = (ADQLList<ADQLOperand>)replacer;
-					else
+						position = null;
+					}else
 						throw new UnsupportedOperationException("Impossible to replace an " + (hasSubQuery() ? "ADQLQuery" : "ADQLList<ADQLOperand>") + " by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 				}
 			}
 
+			@Override
 			public void remove(){
 				if (index <= -1)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -319,6 +356,7 @@ public class In implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return leftOp.toADQL() + " " + getName() + " (" + (hasSubQuery() ? subQuery.toADQL() : list.toADQL()) + ")";
 	}
diff --git a/src/adql/query/constraint/IsNull.java b/src/adql/query/constraint/IsNull.java
index 666654df3b61b0afa29ec7e1417fe246866aa525..56c6cdfe3a6039e0c88f3a350a805fec565ff718 100644
--- a/src/adql/query/constraint/IsNull.java
+++ b/src/adql/query/constraint/IsNull.java
@@ -16,20 +16,22 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLColumn;
 
 /**
  * Represents a comparison between a column to the NULL value.
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class IsNull implements ADQLConstraint {
 
@@ -39,6 +41,10 @@ public class IsNull implements ADQLConstraint {
 	/** Indicates whether the predicate IS NOT NULL must be used rather than IS NULL. */
 	private boolean isNotNull = false;
 
+	/** Position of this {@link IsNull} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds a comparison between the given column and NULL.
 	 * 
@@ -70,6 +76,7 @@ public class IsNull implements ADQLConstraint {
 	public IsNull(IsNull toCopy) throws Exception{
 		column = (ADQLColumn)toCopy.column.getCopy();
 		isNotNull = toCopy.isNotNull;
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -90,8 +97,10 @@ public class IsNull implements ADQLConstraint {
 	public final void setColumn(ADQLColumn column) throws NullPointerException{
 		if (column == null)
 			throw new NullPointerException("Impossible to compare nothing to NULL: no column has been given to build a IsNull constraint !");
-		else
+		else{
 			this.column = column;
+			position = null;
+		}
 	}
 
 	/**
@@ -110,21 +119,41 @@ public class IsNull implements ADQLConstraint {
 	 */
 	public final void setNotNull(boolean notNull){
 		isNotNull = notNull;
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
 	}
 
+	/**
+	 * Set the position of this {@link IsNull} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link IsNull}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new IsNull(this);
 	}
 
+	@Override
 	public String getName(){
 		return "IS" + (isNotNull ? " NOT " : " ") + "NULL";
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private boolean columnGot = (column == null);
 
+			@Override
 			public ADQLObject next(){
 				if (columnGot)
 					throw new NoSuchElementException();
@@ -132,22 +161,26 @@ public class IsNull implements ADQLConstraint {
 				return column;
 			}
 
+			@Override
 			public boolean hasNext(){
 				return !columnGot;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (!columnGot)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
 
 				if (replacer == null)
 					remove();
-				else if (replacer instanceof ADQLColumn)
+				else if (replacer instanceof ADQLColumn){
 					column = (ADQLColumn)replacer;
-				else
+					position = null;
+				}else
 					throw new UnsupportedOperationException("Impossible to replace a column (" + column.toADQL() + ") by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") in a IsNull constraint (" + toADQL() + ") !");
 			}
 
+			@Override
 			public void remove(){
 				if (!columnGot)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -157,6 +190,7 @@ public class IsNull implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return column.toADQL() + " " + getName();
 	}
diff --git a/src/adql/query/constraint/NotConstraint.java b/src/adql/query/constraint/NotConstraint.java
index 77caae147ec5d6b278eede5f4f7d34b9d7f1ed31..9f5a7571cf35a62951ffac5f6ba676ca0d904cd3 100644
--- a/src/adql/query/constraint/NotConstraint.java
+++ b/src/adql/query/constraint/NotConstraint.java
@@ -16,24 +16,30 @@ package adql.query.constraint;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 
 /**
  * Lets apply the logical operator NOT on any constraint.
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public class NotConstraint implements ADQLConstraint {
 
 	private ADQLConstraint constraint;
 
+	/** Position of this {@link NotConstraint} in the ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds a NotConstraint just with the constraint on which the logical operator NOT must be applied.
 	 * 
@@ -56,19 +62,38 @@ public class NotConstraint implements ADQLConstraint {
 		return constraint;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link NotConstraint} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link NotConstraint}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
+	@Override
 	public ADQLObject getCopy() throws Exception{
 		return new NotConstraint((ADQLConstraint)constraint.getCopy());
 	}
 
+	@Override
 	public String getName(){
 		return "NOT " + constraint.getName();
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private boolean constraintGot = (constraint == null);
 
+			@Override
 			public ADQLObject next(){
 				if (constraintGot)
 					throw new NoSuchElementException();
@@ -76,22 +101,26 @@ public class NotConstraint implements ADQLConstraint {
 				return constraint;
 			}
 
+			@Override
 			public boolean hasNext(){
 				return !constraintGot;
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (!constraintGot)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
 
 				if (replacer == null)
 					remove();
-				else if (replacer instanceof ADQLConstraint)
+				else if (replacer instanceof ADQLConstraint){
 					constraint = (ADQLConstraint)replacer;
-				else
+					position = null;
+				}else
 					throw new UnsupportedOperationException("Impossible to replace an ADQLConstraint by a " + replacer.getClass().getName() + " !");
 			}
 
+			@Override
 			public void remove(){
 				if (!constraintGot)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -101,6 +130,7 @@ public class NotConstraint implements ADQLConstraint {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		return "NOT " + constraint.toADQL();
 	}
diff --git a/src/adql/query/from/ADQLJoin.java b/src/adql/query/from/ADQLJoin.java
index 650422cb83565fdc33b76ff458fbb3e2404e954c..7973b2b9adf0aeed375c3059aab4a4600f69824b 100644
--- a/src/adql/query/from/ADQLJoin.java
+++ b/src/adql/query/from/ADQLJoin.java
@@ -35,13 +35,14 @@ import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
 import adql.query.ClauseConstraints;
 import adql.query.IdentifierField;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLColumn;
 
 /**
  * Defines a join between two "tables".
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (05/2015)
+ * @version 1.4 (06/2015)
  */
 public abstract class ADQLJoin implements ADQLObject, FromContent {
 
@@ -60,6 +61,10 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 	/** List of columns on which the join must be done. */
 	protected ArrayList<ADQLColumn> lstColumns = null;
 
+	/** Position of this {@link ADQLJoin} in the given ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/* ************ */
 	/* CONSTRUCTORS */
 	/* ************ */
@@ -92,6 +97,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 			for(ADQLColumn col : toCopy.lstColumns)
 				lstColumns.add((ADQLColumn)col.getCopy());
 		}
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/* ***************** */
@@ -117,6 +123,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 			condition = null;
 			lstColumns = null;
 		}
+		position = null;
 	}
 
 	/**
@@ -135,6 +142,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 	 */
 	public void setLeftTable(FromContent table){
 		leftTable = table;
+		position = null;
 	}
 
 	/**
@@ -153,6 +161,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 	 */
 	public void setRightTable(FromContent table){
 		rightTable = table;
+		position = null;
 	}
 
 	/**
@@ -175,6 +184,17 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 			natural = false;
 			lstColumns = null;
 		}
+		position = null;
+	}
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	@Override
+	public final void setPosition(final TextPosition position){
+		this.position = position;
 	}
 
 	/**
@@ -228,6 +248,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 
 			natural = false;
 			condition = null;
+			position = null;
 		}
 	}
 
@@ -299,6 +320,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 					else
 						throw new UnsupportedOperationException("Impossible to replace an ADQLColumn by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
 				}
+				position = null;
 
 			}
 
@@ -315,6 +337,7 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 				else if (itCol != null){
 					itCol.remove();
 					index--;
+					position = null;
 				}
 			}
 		};
@@ -341,64 +364,69 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 
 	@Override
 	public SearchColumnList getDBColumns() throws UnresolvedJoinException{
-		SearchColumnList list = new SearchColumnList();
-		SearchColumnList leftList = leftTable.getDBColumns();
-		SearchColumnList rightList = rightTable.getDBColumns();
-
-		/* 1. Figure out duplicated columns */
-		HashMap<String,DBCommonColumn> mapDuplicated = new HashMap<String,DBCommonColumn>();
-		// CASE: NATURAL
-		if (natural){
-			// Find duplicated items between the two lists and add one common column in mapDuplicated for each
-			DBColumn rightCol;
-			for(DBColumn leftCol : leftList){
-				// search for at most one column with the same name in the RIGHT list
-				// and throw an exception is there are several matches:
-				rightCol = findAtMostOneColumn(leftCol.getADQLName(), (byte)0, rightList, false);
-				// if there is one...
-				if (rightCol != null){
-					// ...check there is only one column with this name in the LEFT list,
-					// and throw an exception if it is not the case:
-					findExactlyOneColumn(leftCol.getADQLName(), (byte)0, leftList, true);
-					// ...create a common column:
-					mapDuplicated.put(leftCol.getADQLName().toLowerCase(), new DBCommonColumn(leftCol, rightCol));
+		try{
+			SearchColumnList list = new SearchColumnList();
+			SearchColumnList leftList = leftTable.getDBColumns();
+			SearchColumnList rightList = rightTable.getDBColumns();
+
+			/* 1. Figure out duplicated columns */
+			HashMap<String,DBCommonColumn> mapDuplicated = new HashMap<String,DBCommonColumn>();
+			// CASE: NATURAL
+			if (natural){
+				// Find duplicated items between the two lists and add one common column in mapDuplicated for each
+				DBColumn rightCol;
+				for(DBColumn leftCol : leftList){
+					// search for at most one column with the same name in the RIGHT list
+					// and throw an exception is there are several matches:
+					rightCol = findAtMostOneColumn(leftCol.getADQLName(), (byte)0, rightList, false);
+					// if there is one...
+					if (rightCol != null){
+						// ...check there is only one column with this name in the LEFT list,
+						// and throw an exception if it is not the case:
+						findExactlyOneColumn(leftCol.getADQLName(), (byte)0, leftList, true);
+						// ...create a common column:
+						mapDuplicated.put(leftCol.getADQLName().toLowerCase(), new DBCommonColumn(leftCol, rightCol));
+					}
 				}
-			}
 
-		}
-		// CASE: USING
-		else if (lstColumns != null && !lstColumns.isEmpty()){
-			// For each columns of usingList, check there is in each list exactly one matching column, and then, add it in mapDuplicated
-			DBColumn leftCol, rightCol;
-			for(ADQLColumn usingCol : lstColumns){
-				// search for exactly one column with the same name in the LEFT list
-				// and throw an exception if there is none, or if there are several matches:
-				leftCol = findExactlyOneColumn(usingCol.getColumnName(), usingCol.getCaseSensitive(), leftList, true);
-				// idem in the RIGHT list:
-				rightCol = findExactlyOneColumn(usingCol.getColumnName(), usingCol.getCaseSensitive(), rightList, false);
-				// create a common column:
-				mapDuplicated.put((usingCol.isCaseSensitive(IdentifierField.COLUMN) ? ("\"" + usingCol.getColumnName() + "\"") : usingCol.getColumnName().toLowerCase()), new DBCommonColumn(leftCol, rightCol));
 			}
+			// CASE: USING
+			else if (lstColumns != null && !lstColumns.isEmpty()){
+				// For each columns of usingList, check there is in each list exactly one matching column, and then, add it in mapDuplicated
+				DBColumn leftCol, rightCol;
+				for(ADQLColumn usingCol : lstColumns){
+					// search for exactly one column with the same name in the LEFT list
+					// and throw an exception if there is none, or if there are several matches:
+					leftCol = findExactlyOneColumn(usingCol.getColumnName(), usingCol.getCaseSensitive(), leftList, true);
+					// idem in the RIGHT list:
+					rightCol = findExactlyOneColumn(usingCol.getColumnName(), usingCol.getCaseSensitive(), rightList, false);
+					// create a common column:
+					mapDuplicated.put((usingCol.isCaseSensitive(IdentifierField.COLUMN) ? ("\"" + usingCol.getColumnName() + "\"") : usingCol.getColumnName().toLowerCase()), new DBCommonColumn(leftCol, rightCol));
+				}
 
-		}
-		// CASE: NO DUPLICATION TO FIGURE OUT
-		else{
-			// Return the union of both lists:
-			list.addAll(leftList);
-			list.addAll(rightList);
-			return list;
-		}
+			}
+			// CASE: NO DUPLICATION TO FIGURE OUT
+			else{
+				// Return the union of both lists:
+				list.addAll(leftList);
+				list.addAll(rightList);
+				return list;
+			}
 
-		/* 2. Add all columns of the left list except the ones identified as duplications */
-		addAllExcept(leftList, list, mapDuplicated);
+			/* 2. Add all columns of the left list except the ones identified as duplications */
+			addAllExcept(leftList, list, mapDuplicated);
 
-		/* 3. Add all columns of the right list except the ones identified as duplications */
-		addAllExcept(rightList, list, mapDuplicated);
+			/* 3. Add all columns of the right list except the ones identified as duplications */
+			addAllExcept(rightList, list, mapDuplicated);
 
-		/* 4. Add all common columns of mapDuplicated */
-		list.addAll(mapDuplicated.values());
+			/* 4. Add all common columns of mapDuplicated */
+			list.addAll(mapDuplicated.values());
 
-		return list;
+			return list;
+		}catch(UnresolvedJoinException uje){
+			uje.setPosition(position);
+			throw uje;
+		}
 	}
 
 	public final static void addAllExcept(final SearchColumnList itemsToAdd, final SearchColumnList target, final Map<String,DBCommonColumn> exception){
@@ -463,4 +491,4 @@ public abstract class ADQLJoin implements ADQLObject, FromContent {
 	@Override
 	public abstract ADQLObject getCopy() throws Exception;
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/from/FromContent.java b/src/adql/query/from/FromContent.java
index 413929c09cc6d4ce1c8c3aa6cb962f10e6522235..a3df9cce2a1d0f1590239d1af87a7f15264a45f8 100644
--- a/src/adql/query/from/FromContent.java
+++ b/src/adql/query/from/FromContent.java
@@ -26,13 +26,14 @@ import adql.db.DBColumn;
 import adql.db.SearchColumnList;
 import adql.db.exception.UnresolvedJoinException;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 
 /**
  * Represents the content of the whole or a part of the clause FROM.
  * It could be either a table ({@link ADQLTable}) or a join ({@link ADQLJoin}).
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (05/2015)
+ * @version 1.4 (06/2015)
  */
 public interface FromContent extends ADQLObject {
 
@@ -67,4 +68,12 @@ public interface FromContent extends ADQLObject {
 	 */
 	public ArrayList<ADQLTable> getTablesByAlias(final String alias, final boolean caseSensitive);
 
+	/**
+	 * Set the position of this {@link FromContent} in the given ADQL query string.
+	 * 
+	 * @param position	New position of this {@link FromContent}.
+	 * @since 1.4
+	 */
+	public void setPosition(final TextPosition position);
+
 }
diff --git a/src/adql/query/operand/ADQLColumn.java b/src/adql/query/operand/ADQLColumn.java
index 57b30b5353b9871f16ebd7083912eddbf0a9112a..eebce23b893d6c0f15336343678928ca3e5671a9 100644
--- a/src/adql/query/operand/ADQLColumn.java
+++ b/src/adql/query/operand/ADQLColumn.java
@@ -16,7 +16,7 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -32,7 +32,7 @@ import adql.query.from.ADQLTable;
  * Represents the complete (literal) reference to a column ({schema(s)}.{table}.{column}).
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class ADQLColumn implements ADQLOperand, UnknownType {
 
@@ -167,11 +167,7 @@ public class ADQLColumn implements ADQLOperand, UnknownType {
 	/* ***************** */
 	/* GETTERS & SETTERS */
 	/* ***************** */
-	/**
-	 * Gets the position in the original ADQL query string.
-	 * 
-	 * @return	The position of this {@link ADQLTable}.
-	 */
+	@Override
 	public final TextPosition getPosition(){
 		return position;
 	}
diff --git a/src/adql/query/operand/NegativeOperand.java b/src/adql/query/operand/NegativeOperand.java
index b6e4dd7c022473e531b296c21c39ad7cd1eb3998..7b4bc5901867a65e6e4a0a92f355f15617dffeda 100644
--- a/src/adql/query/operand/NegativeOperand.java
+++ b/src/adql/query/operand/NegativeOperand.java
@@ -16,7 +16,7 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -24,16 +24,21 @@ import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 
 /**
  * Lets putting a minus sign in front of any numeric operand.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public final class NegativeOperand implements ADQLOperand {
 
+	/** The negativated operand. */
 	private ADQLOperand operand;
+	/** Position of this operand.
+	 * @since 1.4 */
+	private TextPosition position = null;
 
 	/**
 	 * <p>Builds an operand which will negativate the given operand.</p>
@@ -80,6 +85,21 @@ public final class NegativeOperand implements ADQLOperand {
 		return false;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return this.position;
+	}
+
+	/**
+	 * Sets the position at which this {@link NegativeOperand} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link NegativeOperand}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	/** Always returns <i>false</i>.
 	 * @see adql.query.operand.ADQLOperand#isGeometry()
 	 */
diff --git a/src/adql/query/operand/NumericConstant.java b/src/adql/query/operand/NumericConstant.java
index 8baa697effca3d8f284383d834eb5095d103c2af..53e4937cf1f7bbff1a48c3939d6c4a7e3ad1c0a8 100644
--- a/src/adql/query/operand/NumericConstant.java
+++ b/src/adql/query/operand/NumericConstant.java
@@ -16,24 +16,29 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
 import adql.query.NullADQLIterator;
+import adql.query.TextPosition;
 
 /**
  * A numeric (integer, double, ...) constant.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public final class NumericConstant implements ADQLOperand {
 
 	private String value;
 
+	/** Position of this operand.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * The numeric value is saved as a string so that the exact user format can be saved.
 	 * The given string must be convertible in a Double value.
@@ -163,6 +168,21 @@ public final class NumericConstant implements ADQLOperand {
 		return false;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return this.position;
+	}
+
+	/**
+	 * Sets the position at which this {@link NumericConstant} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link NumericConstant}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	/** Always returns <i>false</i>.
 	 * @see adql.query.operand.ADQLOperand#isGeometry()
 	 */
diff --git a/src/adql/query/operand/Operation.java b/src/adql/query/operand/Operation.java
index d890770377557406eff06a686b0f11031322f1e9..1418ae1cce1ea4784c4ba47c3d2e2255018d06fa 100644
--- a/src/adql/query/operand/Operation.java
+++ b/src/adql/query/operand/Operation.java
@@ -16,7 +16,7 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -24,12 +24,13 @@ import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 
 /**
  * It represents a simple numeric operation (sum, difference, multiplication and division).
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  * 
  * @see OperationType
  */
@@ -47,6 +48,10 @@ public class Operation implements ADQLOperand {
 	/** Part of the operation at the right of the operator. */
 	private ADQLOperand rightOperand;
 
+	/** Position of the operation in the ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	/**
 	 * Builds an operation.
 	 * 
@@ -69,6 +74,8 @@ public class Operation implements ADQLOperand {
 			operation = op;
 
 		setRightOperand(rightOp);
+
+		position = null;
 	}
 
 	/**
@@ -82,6 +89,7 @@ public class Operation implements ADQLOperand {
 		leftOperand = (ADQLOperand)toCopy.leftOperand.getCopy();
 		operation = toCopy.operation;
 		rightOperand = (ADQLOperand)toCopy.rightOperand.getCopy();
+		position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 	}
 
 	/**
@@ -108,6 +116,8 @@ public class Operation implements ADQLOperand {
 			throw new UnsupportedOperationException("Impossible to update an Operation because the left operand is not numeric (" + newLeftOperand.toADQL() + ") !");
 
 		leftOperand = newLeftOperand;
+
+		position = null;
 	}
 
 	/**
@@ -156,6 +166,8 @@ public class Operation implements ADQLOperand {
 			throw new UnsupportedOperationException("Impossible to update an Operation because the right operand is not numeric (" + newRightOperand.toADQL() + ") !");
 
 		rightOperand = newRightOperand;
+
+		position = null;
 	}
 
 	/** Always returns <i>true</i>.
@@ -174,6 +186,21 @@ public class Operation implements ADQLOperand {
 		return false;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return this.position;
+	}
+
+	/**
+	 * Sets the position at which this {@link WrappedOperand} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link WrappedOperand}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	/** Always returns <i>false</i>.
 	 * @see adql.query.operand.ADQLOperand#isGeometry()
 	 */
@@ -230,6 +257,7 @@ public class Operation implements ADQLOperand {
 							leftOperand = (ADQLOperand)replacer;
 						else if (index == 1)
 							rightOperand = (ADQLOperand)replacer;
+						position = null;
 					}else
 						throw new UnsupportedOperationException("Impossible to replace the operand \"" + operand.toADQL() + "\" by \"" + replacer.toADQL() + "\" in the operation \"" + toADQL() + "\" because the replacer is not an ADQLOperand or is not numeric !");
 				}
@@ -250,4 +278,4 @@ public class Operation implements ADQLOperand {
 		return leftOperand.toADQL() + operation.toADQL() + rightOperand.toADQL();
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/StringConstant.java b/src/adql/query/operand/StringConstant.java
index 6c115e74b2287f87e4c2d021b69d9cbd3f8f2408..998bda9057ee2e1d85d6202dfd9f8e14ff2fe458 100644
--- a/src/adql/query/operand/StringConstant.java
+++ b/src/adql/query/operand/StringConstant.java
@@ -16,24 +16,29 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
 import adql.query.NullADQLIterator;
+import adql.query.TextPosition;
 
 /**
  * A string constant.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public final class StringConstant implements ADQLOperand {
 
 	private String value;
 
+	/** Position of this operand.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
 	public StringConstant(String value){
 		this.value = value;
 	}
@@ -60,6 +65,21 @@ public final class StringConstant implements ADQLOperand {
 		return true;
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return this.position;
+	}
+
+	/**
+	 * Sets the position at which this {@link StringConstant} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link StringConstant}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	@Override
 	public final boolean isGeometry(){
 		return false;
diff --git a/src/adql/query/operand/WrappedOperand.java b/src/adql/query/operand/WrappedOperand.java
index 98fde1d171ef34f4a8d63998003a93755e6086f7..ca36d7a03793796702ddd36c38aaa9e843751c47 100644
--- a/src/adql/query/operand/WrappedOperand.java
+++ b/src/adql/query/operand/WrappedOperand.java
@@ -16,7 +16,7 @@ package adql.query.operand;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -24,17 +24,21 @@ import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 
 /**
  * Lets wrapping an operand by parenthesis.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class WrappedOperand implements ADQLOperand {
 
 	/** The wrapped operand. */
 	private ADQLOperand operand;
+	/** Position of this operand.
+	 * @since 1.4 */
+	private TextPosition position = null;
 
 	/**
 	 * Wraps the given operand.
@@ -68,6 +72,21 @@ public class WrappedOperand implements ADQLOperand {
 		return operand.isString();
 	}
 
+	@Override
+	public final TextPosition getPosition(){
+		return this.position;
+	}
+
+	/**
+	 * Sets the position at which this {@link WrappedOperand} has been found in the original ADQL query string.
+	 * 
+	 * @param pos	Position of this {@link WrappedOperand}.
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	@Override
 	public final boolean isGeometry(){
 		return operand.isGeometry();
@@ -109,9 +128,10 @@ public class WrappedOperand implements ADQLOperand {
 
 				if (replacer == null)
 					remove();
-				else if (replacer instanceof ADQLOperand)
+				else if (replacer instanceof ADQLOperand){
 					operand = (ADQLOperand)replacer;
-				else
+					position = null;
+				}else
 					throw new UnsupportedOperationException("Impossible to replace an ADQLOperand (\"" + operand + "\") by a " + replacer.getClass().getName() + " (\"" + replacer.toADQL() + "\") !");
 			}
 
diff --git a/src/adql/query/operand/function/ADQLFunction.java b/src/adql/query/operand/function/ADQLFunction.java
index 97a22b7f30340c0fcd5d74be2febc83ff9e0675b..b22ec5611baee8e66c3a175aa7269cf9296758ca 100644
--- a/src/adql/query/operand/function/ADQLFunction.java
+++ b/src/adql/query/operand/function/ADQLFunction.java
@@ -16,7 +16,8 @@ package adql.query.operand.function;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import java.util.Iterator;
@@ -24,17 +25,36 @@ import java.util.NoSuchElementException;
 
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
-
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
  * Represents any kind of function.
  * 
- * @author Gr&eacute;gory Mantelet (CDS)
- * @version 06/2011
+ * @author Gr&eacute;gory Mantelet (CDS;ARI)
+ * @version 1.4 (06/2015)
  */
 public abstract class ADQLFunction implements ADQLOperand {
 
+	/** Position of this {@link ADQLFunction} in the ADQL query string.
+	 * @since 1.4 */
+	private TextPosition position = null;
+
+	@Override
+	public final TextPosition getPosition(){
+		return position;
+	}
+
+	/**
+	 * Set the position of this {@link ADQLFunction} in the ADQL query string.
+	 * 
+	 * @param position	New position of this {@link ADQLFunction}
+	 * @since 1.4
+	 */
+	public final void setPosition(final TextPosition position){
+		this.position = position;
+	}
+
 	/**
 	 * Gets the number of parameters this function has.
 	 * 
@@ -82,11 +102,13 @@ public abstract class ADQLFunction implements ADQLOperand {
 		return new ParameterIterator(this);
 	}
 
+	@Override
 	public ADQLIterator adqlIterator(){
 		return new ADQLIterator(){
 
 			private int index = -1;
 
+			@Override
 			public ADQLObject next(){
 				try{
 					return getParameter(++index);
@@ -95,10 +117,12 @@ public abstract class ADQLFunction implements ADQLOperand {
 				}
 			}
 
+			@Override
 			public boolean hasNext(){
 				return index + 1 < getNbParameters();
 			}
 
+			@Override
 			public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{
 				if (index <= -1)
 					throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !");
@@ -116,6 +140,7 @@ public abstract class ADQLFunction implements ADQLOperand {
 					throw new UnsupportedOperationException("Impossible to replace the " + index + "-th parameter of \"" + toADQL() + "\" by an object whose the class (" + replacer.getClass().getName() + ") is not ADQLOperand !");
 			}
 
+			@Override
 			public void remove(){
 				if (index <= -1)
 					throw new IllegalStateException("remove() impossible: next() has not yet been called !");
@@ -125,6 +150,7 @@ public abstract class ADQLFunction implements ADQLOperand {
 		};
 	}
 
+	@Override
 	public String toADQL(){
 		String adql = getName() + "(";
 
@@ -152,15 +178,18 @@ public abstract class ADQLFunction implements ADQLOperand {
 				function = fct;
 		}
 
+		@Override
 		public boolean hasNext(){
 			return (index + 1) < function.getNbParameters();
 		}
 
+		@Override
 		public ADQLOperand next(){
 			index++;
 			return function.getParameter(index);
 		}
 
+		@Override
 		public void remove() throws UnsupportedOperationException{
 			try{
 				function.setParameter(index, null);
diff --git a/src/adql/query/operand/function/DefaultUDF.java b/src/adql/query/operand/function/DefaultUDF.java
index 285eb4ef987cfa0e146ca1ad299af03460176cf8..268de91d048012fd25f27f2b7e1d0e722404a155 100644
--- a/src/adql/query/operand/function/DefaultUDF.java
+++ b/src/adql/query/operand/function/DefaultUDF.java
@@ -24,6 +24,7 @@ import adql.db.FunctionDef;
 import adql.query.ADQLList;
 import adql.query.ADQLObject;
 import adql.query.ClauseADQL;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 import adql.translator.ADQLTranslator;
 import adql.translator.TranslationException;
@@ -32,7 +33,7 @@ import adql.translator.TranslationException;
  * It represents any function which is not managed by ADQL.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (02/2015)
+ * @version 1.4 (06/2015)
  */
 public final class DefaultUDF extends UserDefinedFunction {
 
@@ -69,6 +70,7 @@ public final class DefaultUDF extends UserDefinedFunction {
 	public DefaultUDF(final DefaultUDF toCopy) throws Exception{
 		functionName = toCopy.functionName;
 		parameters = (ADQLList<ADQLOperand>)(toCopy.parameters.getCopy());
+		setPosition((toCopy.getPosition() == null) ? null : new TextPosition(toCopy.getPosition()));;
 	}
 
 	/**
@@ -156,7 +158,9 @@ public final class DefaultUDF extends UserDefinedFunction {
 	 */
 	@Override
 	public ADQLOperand setParameter(int index, ADQLOperand replacer) throws ArrayIndexOutOfBoundsException, NullPointerException, Exception{
-		return parameters.set(index, replacer);
+		ADQLOperand oldParam = parameters.set(index, replacer);
+		setPosition(null);
+		return oldParam;
 	}
 
 	@Override
diff --git a/src/adql/query/operand/function/MathFunction.java b/src/adql/query/operand/function/MathFunction.java
index c29d64a8c6f333fc241c5e10e24dc46cbccff4fd..49e1a4a675e436658378ac736e4cf919057784f1 100644
--- a/src/adql/query/operand/function/MathFunction.java
+++ b/src/adql/query/operand/function/MathFunction.java
@@ -16,18 +16,19 @@ package adql.query.operand.function;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
  * It represents any basic mathematical function.
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  * 
  * @see MathFunctionType
  */
@@ -116,6 +117,7 @@ public class MathFunction extends ADQLFunction {
 		type = toCopy.type;
 		param1 = (ADQLOperand)toCopy.param1.getCopy();
 		param2 = (ADQLOperand)toCopy.param2.getCopy();
+		setPosition((toCopy.getPosition() == null) ? null : new TextPosition(toCopy.getPosition()));
 	}
 
 	/**
@@ -198,10 +200,12 @@ public class MathFunction extends ADQLFunction {
 				case 0:
 					replaced = param1;
 					param1 = replacer;
+					setPosition(null);
 					break;
 				case 1:
 					replaced = param2;
 					param2 = replacer;
+					setPosition(null);
 					break;
 			}
 			return replaced;
diff --git a/src/adql/query/operand/function/SQLFunction.java b/src/adql/query/operand/function/SQLFunction.java
index 6603fd90b6c0083feb4468cde5b7e0a1bff5270f..5d0748e62f47182eb86a965e29c673c60dc43181 100644
--- a/src/adql/query/operand/function/SQLFunction.java
+++ b/src/adql/query/operand/function/SQLFunction.java
@@ -16,18 +16,19 @@ package adql.query.operand.function;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
- *                       Astronomisches Rechen Institut (ARI)
+ * Copyright 2011-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ *                       Astronomisches Rechen Institute (ARI)
  */
 
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLOperand;
 
 /**
  * It represents any SQL function (COUNT, MAX, MIN, AVG, SUM, etc...).
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  * 
  * @see SQLFunctionType
  */
@@ -87,6 +88,7 @@ public class SQLFunction extends ADQLFunction {
 		type = toCopy.type;
 		param = (ADQLOperand)toCopy.param.getCopy();
 		distinct = toCopy.distinct;
+		setPosition((toCopy.getPosition() == null) ? null : new TextPosition(toCopy.getPosition()));;
 	}
 
 	/**
@@ -105,6 +107,7 @@ public class SQLFunction extends ADQLFunction {
 	 */
 	public void setDistinct(boolean distinctValues){
 		distinct = distinctValues;
+		setPosition(null);
 	}
 
 	/**
@@ -172,6 +175,7 @@ public class SQLFunction extends ADQLFunction {
 
 		ADQLOperand replaced = param;
 		param = replacer;
+		setPosition(null);
 
 		return replaced;
 	}
@@ -184,4 +188,4 @@ public class SQLFunction extends ADQLFunction {
 			return getName() + "(" + (distinct ? "DISTINCT " : "") + param.toADQL() + ")";
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/AreaFunction.java b/src/adql/query/operand/function/geometry/AreaFunction.java
index 6b163aca0a6775956801405384fb447e8b66de91..bb9003d5484091d54efde436410ce6c866f7c9b6 100644
--- a/src/adql/query/operand/function/geometry/AreaFunction.java
+++ b/src/adql/query/operand/function/geometry/AreaFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -34,7 +34,7 @@ import adql.query.operand.ADQLOperand;
  * <p>Inappropriate geometries for this construct (e.g. POINT) SHOULD either return zero or throw an error message. <b>This choice must be done in an extended class of {@link AreaFunction}</b>.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class AreaFunction extends GeometryFunction {
 
@@ -85,6 +85,7 @@ public class AreaFunction extends GeometryFunction {
 	 */
 	public final void setParameter(GeometryValue<GeometryFunction> parameter){
 		this.parameter = parameter;
+		setPosition(null);
 	}
 
 	@Override
@@ -145,9 +146,10 @@ public class AreaFunction extends GeometryFunction {
 				parameter.setGeometry((GeometryFunction)replacer);
 			else
 				throw new Exception("Impossible to replace a GeometryValue/Column/GeometryFunction by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
+			setPosition(null);
 			return replaced;
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/BoxFunction.java b/src/adql/query/operand/function/geometry/BoxFunction.java
index 7e064a4f32d88b372036b606ea07443bcb02529f..7585fd67b13412b1548c24e41e9e288e8d2054f5 100644
--- a/src/adql/query/operand/function/geometry/BoxFunction.java
+++ b/src/adql/query/operand/function/geometry/BoxFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -39,7 +39,7 @@ import adql.query.operand.ADQLOperand;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class BoxFunction extends GeometryFunction {
 
@@ -133,6 +133,7 @@ public class BoxFunction extends GeometryFunction {
 	 */
 	public final void setCoord1(ADQLOperand coord1){
 		this.coord1 = coord1;
+		setPosition(null);
 	}
 
 	/**
@@ -151,6 +152,7 @@ public class BoxFunction extends GeometryFunction {
 	 */
 	public final void setCoord2(ADQLOperand coord2){
 		this.coord2 = coord2;
+		setPosition(null);
 	}
 
 	/**
@@ -169,6 +171,7 @@ public class BoxFunction extends GeometryFunction {
 	 */
 	public final void setWidth(ADQLOperand width){
 		this.width = width;
+		setPosition(null);
 	}
 
 	/**
@@ -187,6 +190,7 @@ public class BoxFunction extends GeometryFunction {
 	 */
 	public final void setHeight(ADQLOperand height){
 		this.height = height;
+		setPosition(null);
 	}
 
 	@Override
@@ -249,6 +253,7 @@ public class BoxFunction extends GeometryFunction {
 			default:
 				throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 		}
+		setPosition(null);
 		return replaced;
 	}
 
diff --git a/src/adql/query/operand/function/geometry/CentroidFunction.java b/src/adql/query/operand/function/geometry/CentroidFunction.java
index 3b3b0147982cbd9a1f50a2d8a6282e4e238484cb..23a2b7852972ed5df64646e54739db87b29842b0 100644
--- a/src/adql/query/operand/function/geometry/CentroidFunction.java
+++ b/src/adql/query/operand/function/geometry/CentroidFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -36,7 +36,7 @@ import adql.query.operand.ADQLOperand;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class CentroidFunction extends GeometryFunction {
 
@@ -126,9 +126,10 @@ public class CentroidFunction extends GeometryFunction {
 				parameter.setGeometry((GeometryFunction)replacer);
 			else
 				throw new Exception("Impossible to replace a GeometryValue/Column/GeometryFunction by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
+			setPosition(null);
 			return replaced;
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/CircleFunction.java b/src/adql/query/operand/function/geometry/CircleFunction.java
index f979d3850bf3afe53526fe67e68cf47a85a6e3fa..3d3dc6bf8e6a51ba24615538d770290661a1b7bf 100644
--- a/src/adql/query/operand/function/geometry/CircleFunction.java
+++ b/src/adql/query/operand/function/geometry/CircleFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -36,7 +36,7 @@ import adql.query.operand.ADQLOperand;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class CircleFunction extends GeometryFunction {
 
@@ -124,6 +124,7 @@ public class CircleFunction extends GeometryFunction {
 	 */
 	public final void setCoord1(ADQLOperand coord1){
 		this.coord1 = coord1;
+		setPosition(null);
 	}
 
 	/**
@@ -142,6 +143,7 @@ public class CircleFunction extends GeometryFunction {
 	 */
 	public final void setCoord2(ADQLOperand coord2){
 		this.coord2 = coord2;
+		setPosition(null);
 	}
 
 	/**
@@ -160,6 +162,7 @@ public class CircleFunction extends GeometryFunction {
 	 */
 	public final void setRadius(ADQLOperand radius){
 		this.radius = radius;
+		setPosition(null);
 	}
 
 	@Override
@@ -214,6 +217,7 @@ public class CircleFunction extends GeometryFunction {
 			default:
 				throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 		}
+		setPosition(null);
 		return replaced;
 	}
 
diff --git a/src/adql/query/operand/function/geometry/ContainsFunction.java b/src/adql/query/operand/function/geometry/ContainsFunction.java
index 4cb4aad040c85f5a8bc225b1c3b5fc03ac60b4d0..e26fa97593863abc8242f5cea3f805e5e6d56db0 100644
--- a/src/adql/query/operand/function/geometry/ContainsFunction.java
+++ b/src/adql/query/operand/function/geometry/ContainsFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -42,7 +42,7 @@ import adql.query.operand.ADQLOperand;
  * </b></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class ContainsFunction extends GeometryFunction {
 
@@ -117,8 +117,10 @@ public class ContainsFunction extends GeometryFunction {
 	 * @param leftParam The leftParam to set.
 	 */
 	public final void setLeftParam(GeometryValue<GeometryFunction> leftParam){
-		if (leftParam != null)
+		if (leftParam != null){
 			this.leftParam = leftParam;
+			setPosition(null);
+		}
 	}
 
 	/**
@@ -132,8 +134,10 @@ public class ContainsFunction extends GeometryFunction {
 	 * @param rightParam The rightParam to set.
 	 */
 	public final void setRightParam(GeometryValue<GeometryFunction> rightParam){
-		if (rightParam != null)
+		if (rightParam != null){
 			this.rightParam = rightParam;
+			setPosition(null);
+		}
 	}
 
 	@Override
@@ -183,7 +187,8 @@ public class ContainsFunction extends GeometryFunction {
 				rightParam.setGeometry((GeometryFunction)replacer);
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
+		setPosition(null);
 		return replaced;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/DistanceFunction.java b/src/adql/query/operand/function/geometry/DistanceFunction.java
index ead9b4b465c21e70cad5d6a1623b57c7efac19bc..fb49a9353f98ffe6730e97bd451ef978458758d5 100644
--- a/src/adql/query/operand/function/geometry/DistanceFunction.java
+++ b/src/adql/query/operand/function/geometry/DistanceFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -35,7 +35,7 @@ import adql.query.operand.ADQLOperand;
  * coordinate system with GEOCENTER reference position.</i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class DistanceFunction extends GeometryFunction {
 
@@ -120,6 +120,7 @@ public class DistanceFunction extends GeometryFunction {
 	 */
 	public final void setP1(GeometryValue<PointFunction> p1){
 		this.p1 = p1;
+		setPosition(null);
 	}
 
 	/**
@@ -138,6 +139,7 @@ public class DistanceFunction extends GeometryFunction {
 	 */
 	public final void setP2(GeometryValue<PointFunction> p2){
 		this.p2 = p2;
+		setPosition(null);
 	}
 
 	@Override
@@ -198,7 +200,9 @@ public class DistanceFunction extends GeometryFunction {
 				toUpdate.setGeometry((PointFunction)replacer);
 		}
 
+		setPosition(null);
+
 		return replaced;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/ExtractCoord.java b/src/adql/query/operand/function/geometry/ExtractCoord.java
index 2fa17cd953ceb46f0da616199f7c9e1283156489..edff24aeb91c4bdce913d1d190856a8b7188355d 100644
--- a/src/adql/query/operand/function/geometry/ExtractCoord.java
+++ b/src/adql/query/operand/function/geometry/ExtractCoord.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -36,7 +36,7 @@ import adql.query.operand.ADQLOperand;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class ExtractCoord extends GeometryFunction {
 
@@ -136,9 +136,10 @@ public class ExtractCoord extends GeometryFunction {
 				point.setGeometry((PointFunction)replacer);
 			else
 				throw new Exception("Impossible to replace GeometryValue/Column/PointFunction by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
+			setPosition(null);
 			return replaced;
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/ExtractCoordSys.java b/src/adql/query/operand/function/geometry/ExtractCoordSys.java
index dcd8e542a75d8a11d7961788fd3ed64a7996e05b..3865c2df8799ed3d15fd6de37e26206416ef09dd 100644
--- a/src/adql/query/operand/function/geometry/ExtractCoordSys.java
+++ b/src/adql/query/operand/function/geometry/ExtractCoordSys.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -36,7 +36,7 @@ import adql.query.operand.ADQLOperand;
  * </i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class ExtractCoordSys extends GeometryFunction {
 
@@ -123,9 +123,10 @@ public class ExtractCoordSys extends GeometryFunction {
 				geomExpr.setGeometry((GeometryFunction)replacer);
 			else
 				throw new Exception("Impossible to replace GeometryValue/Column/GeometryFunction by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
+			setPosition(null);
 			return replaced;
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function " + getName() + " !");
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/GeometryFunction.java b/src/adql/query/operand/function/geometry/GeometryFunction.java
index e6e10ecf2513847a9ca922fd53e78e621f8ff670..18920016ddc3ed18cfac41030f30ee0387fbbe22 100644
--- a/src/adql/query/operand/function/geometry/GeometryFunction.java
+++ b/src/adql/query/operand/function/geometry/GeometryFunction.java
@@ -16,13 +16,14 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
 import adql.parser.ParseException;
 import adql.query.ADQLIterator;
 import adql.query.ADQLObject;
+import adql.query.TextPosition;
 import adql.query.operand.ADQLColumn;
 import adql.query.operand.ADQLOperand;
 import adql.query.operand.StringConstant;
@@ -32,7 +33,7 @@ import adql.query.operand.function.ADQLFunction;
  * <p>It represents any geometric function of ADQL.</p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public abstract class GeometryFunction extends ADQLFunction {
 
@@ -66,6 +67,7 @@ public abstract class GeometryFunction extends ADQLFunction {
 	 */
 	protected GeometryFunction(GeometryFunction toCopy) throws Exception{
 		coordSys = (ADQLOperand)(toCopy.coordSys.getCopy());
+		setPosition((toCopy.getPosition() == null) ? null : new TextPosition(toCopy.getPosition()));
 	}
 
 	/**
@@ -90,8 +92,10 @@ public abstract class GeometryFunction extends ADQLFunction {
 			this.coordSys = new StringConstant("");
 		else if (!coordSys.isString())
 			throw new ParseException("A coordinate system must be a string literal: \"" + coordSys.toADQL() + "\" is not a string operand!");
-		else
+		else{
 			this.coordSys = coordSys;
+			setPosition(null);
+		}
 	}
 
 	/**
@@ -99,34 +103,43 @@ public abstract class GeometryFunction extends ADQLFunction {
 	 * which, in general, is either a GeometryFunction or a Column.
 	 * 
 	 * @author Gr&eacute;gory Mantelet (CDS;ARI)
-	 * @version 1.3 (10/2014)
+	 * @version 1.4 (06/2015)
 	 */
 	public static final class GeometryValue< F extends GeometryFunction > implements ADQLOperand {
 		private ADQLColumn column;
 		private F geomFunct;
+		/** Position of this {@link GeometryValue} in the ADQL query string.
+		 * @since 1.4 */
+		private TextPosition position = null;
 
 		public GeometryValue(ADQLColumn col) throws NullPointerException{
 			if (col == null)
 				throw new NullPointerException("Impossible to build a GeometryValue without a column or a geometry function !");
 			setColumn(col);
+			if (col.getPosition() != null)
+				position = col.getPosition();
 		}
 
 		public GeometryValue(F geometry) throws NullPointerException{
 			if (geometry == null)
 				throw new NullPointerException("Impossible to build a GeometryValue without a column or a geometry function !");
 			setGeometry(geometry);
+			if (geometry.getPosition() != null)
+				position = geometry.getPosition();
 		}
 
 		@SuppressWarnings("unchecked")
 		public GeometryValue(GeometryValue<F> toCopy) throws Exception{
 			column = (toCopy.column == null) ? null : ((ADQLColumn)(toCopy.column.getCopy()));
 			geomFunct = (toCopy.geomFunct == null) ? null : ((F)(toCopy.geomFunct.getCopy()));
+			position = (toCopy.position == null) ? null : new TextPosition(toCopy.position);
 		}
 
 		public void setColumn(ADQLColumn col){
 			if (col != null){
 				geomFunct = null;
 				column = col;
+				position = (column.getPosition() != null) ? column.getPosition() : null;
 			}
 		}
 
@@ -134,6 +147,7 @@ public abstract class GeometryFunction extends ADQLFunction {
 			if (geometry != null){
 				column = null;
 				geomFunct = geometry;
+				position = (geomFunct.getPosition() != null) ? geomFunct.getPosition() : null;
 			}
 		}
 
@@ -155,6 +169,11 @@ public abstract class GeometryFunction extends ADQLFunction {
 			return getValue().isString();
 		}
 
+		@Override
+		public TextPosition getPosition(){
+			return position;
+		}
+
 		@Override
 		public boolean isGeometry(){
 			return getValue().isGeometry();
@@ -180,4 +199,4 @@ public abstract class GeometryFunction extends ADQLFunction {
 			return getValue().toADQL();
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/IntersectsFunction.java b/src/adql/query/operand/function/geometry/IntersectsFunction.java
index 29bc881fdf61bd455068e3afe694dca137a7a2c4..8b5d8b92763ebad7723e7b855b2a72bab7a03fac 100644
--- a/src/adql/query/operand/function/geometry/IntersectsFunction.java
+++ b/src/adql/query/operand/function/geometry/IntersectsFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -43,7 +43,7 @@ import adql.query.operand.ADQLOperand;
  * </b></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class IntersectsFunction extends GeometryFunction {
 
@@ -118,8 +118,10 @@ public class IntersectsFunction extends GeometryFunction {
 	 * @param leftParam The leftParam to set.
 	 */
 	public final void setLeftParam(GeometryValue<GeometryFunction> leftParam){
-		if (leftParam != null)
+		if (leftParam != null){
 			this.leftParam = leftParam;
+			setPosition(null);
+		}
 	}
 
 	/**
@@ -133,8 +135,10 @@ public class IntersectsFunction extends GeometryFunction {
 	 * @param rightParam The rightParam to set.
 	 */
 	public final void setRightParam(GeometryValue<GeometryFunction> rightParam){
-		if (rightParam != null)
+		if (rightParam != null){
 			this.rightParam = rightParam;
+			setPosition(null);
+		}
 	}
 
 	@Override
@@ -184,7 +188,8 @@ public class IntersectsFunction extends GeometryFunction {
 				rightParam.setGeometry((GeometryFunction)replacer);
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
+		setPosition(null);
 		return replaced;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/src/adql/query/operand/function/geometry/PointFunction.java b/src/adql/query/operand/function/geometry/PointFunction.java
index 1b736ffabe897b65ee20200f0a9db0602d0f4f00..1d5fd26a8a1af88014a475c8ed6db4fa9dee2cea 100644
--- a/src/adql/query/operand/function/geometry/PointFunction.java
+++ b/src/adql/query/operand/function/geometry/PointFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -35,7 +35,7 @@ import adql.query.operand.ADQLOperand;
  * to the ICRS coordinate system with GEOCENTER reference position.</i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class PointFunction extends GeometryFunction {
 
@@ -98,8 +98,10 @@ public class PointFunction extends GeometryFunction {
 			throw new NullPointerException("The first coordinate of a POINT function must be different from NULL !");
 		else if (!coord1.isNumeric())
 			throw new Exception("Coordinates of a POINT function must be numeric !");
-		else
+		else{
 			this.coord1 = coord1;
+			setPosition(null);
+		}
 	}
 
 	/**
@@ -123,8 +125,10 @@ public class PointFunction extends GeometryFunction {
 			throw new NullPointerException("The second coordinate of a POINT function must be different from NULL !");
 		else if (!coord2.isNumeric())
 			throw new Exception("Coordinates of a POINT function must be numeric !");
-		else
+		else{
 			this.coord2 = coord2;
+			setPosition(null);
+		}
 	}
 
 	@Override
@@ -199,6 +203,8 @@ public class PointFunction extends GeometryFunction {
 				throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" !");
 		}
 
+		setPosition(null);
+
 		return replaced;
 	}
 
diff --git a/src/adql/query/operand/function/geometry/PolygonFunction.java b/src/adql/query/operand/function/geometry/PolygonFunction.java
index 33dd2a629c49bc989025a4fba21fe7d8ab343a9c..a4d07a2549aca257cbec2d3578fa4fe247e62dcb 100644
--- a/src/adql/query/operand/function/geometry/PolygonFunction.java
+++ b/src/adql/query/operand/function/geometry/PolygonFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -42,7 +42,7 @@ import adql.query.operand.ADQLOperand;
  * according to the STC coordinate system with GEOCENTER reference position.</i></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class PolygonFunction extends GeometryFunction {
 
@@ -168,6 +168,9 @@ public class PolygonFunction extends GeometryFunction {
 			coordinates.set(index - 1, replacer);
 		}else
 			throw new ArrayIndexOutOfBoundsException("No " + index + "-th parameter for the function \"" + getName() + "\" (" + toADQL() + ") !");
+
+		setPosition(null);
+
 		return replaced;
 	}
 
diff --git a/src/adql/query/operand/function/geometry/RegionFunction.java b/src/adql/query/operand/function/geometry/RegionFunction.java
index 998d4a56a7abb22bc75cf9810334e6db7daa4a5b..30e9e00cc0c01034b06b4a3513576aeb8ab68367 100644
--- a/src/adql/query/operand/function/geometry/RegionFunction.java
+++ b/src/adql/query/operand/function/geometry/RegionFunction.java
@@ -16,7 +16,7 @@ package adql.query.operand.function.geometry;
  * You should have received a copy of the GNU Lesser General Public License
  * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
  * 
- * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
+ * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
  *                       Astronomisches Rechen Institut (ARI)
  */
 
@@ -38,7 +38,7 @@ import adql.query.operand.ADQLOperand;
  * Inappropriate geometries for this construct SHOULD throw an error message, to be defined by the service making use of ADQL.</b></p>
  * 
  * @author Gr&eacute;gory Mantelet (CDS;ARI)
- * @version 1.3 (10/2014)
+ * @version 1.4 (06/2015)
  */
 public class RegionFunction extends GeometryFunction {
 
@@ -122,6 +122,7 @@ public class RegionFunction extends GeometryFunction {
 			else if (replacer instanceof ADQLOperand){
 				ADQLOperand replaced = parameter;
 				parameter = replacer;
+				setPosition(null);
 				return replaced;
 			}else
 				throw new Exception("Impossible to replace an ADQLOperand by a " + replacer.getClass().getName() + " (" + replacer.toADQL() + ") !");
diff --git a/src/tap/metadata/TAPColumn.java b/src/tap/metadata/TAPColumn.java
index 289dbe938969247a00f4a3f4aac05107b811eff3..3365cc60f0053a00baa76e3685ea7759f51d950c 100644
--- a/src/tap/metadata/TAPColumn.java
+++ b/src/tap/metadata/TAPColumn.java
@@ -494,7 +494,7 @@ public class TAPColumn implements DBColumn {
 	 * <p>Set the type of the column's values.</p>
 	 * 
 	 * <p><i>Note:
-	 * 	If the given type is NULL, a {@link DBDatatype#UNKNOWN UNKNOWN} type will be set instead.
+	 * 	If the given type is NULL, an {@link DBDatatype#UNKNOWN UNKNOWN} type will be set instead.
 	 * </i></p>
 	 * 
 	 * @param type	Its new datatype.
diff --git a/test/adql/TestADQLObjectPosition.java b/test/adql/TestADQLObjectPosition.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c1b8d41b741e2a9fa28b031f2a176b6757a715e
--- /dev/null
+++ b/test/adql/TestADQLObjectPosition.java
@@ -0,0 +1,143 @@
+package adql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import adql.parser.ADQLParser;
+import adql.parser.ParseException;
+import adql.query.ADQLObject;
+import adql.query.ADQLQuery;
+import adql.query.TextPosition;
+import adql.query.constraint.Comparison;
+import adql.query.from.ADQLJoin;
+import adql.query.from.ADQLTable;
+import adql.query.operand.ADQLColumn;
+import adql.query.operand.ADQLOperand;
+import adql.query.operand.function.ADQLFunction;
+import adql.search.SimpleSearchHandler;
+
+public class TestADQLObjectPosition {
+
+	private ADQLParser parser = new ADQLParser();
+
+	@Before
+	public void setUp(){
+
+	}
+
+	@Test
+	public void testPositionInAllClauses(){
+		try{
+			ADQLQuery query = parser.parseQuery("SELECT truc, bidule.machin, toto(truc, chose) AS \"super\" FROM foo JOIN bidule USING(id) WHERE truc > 12.5 AND bidule.machin < 5 GROUP BY chose HAVING try > 0 ORDER BY chouetteAlors");
+
+			Iterator<ADQLObject> results = query.search(new SimpleSearchHandler(true){
+				@Override
+				protected boolean match(ADQLObject obj){
+					return obj.getPosition() == null;
+				}
+			});
+			if (results.hasNext()){
+				System.err.println("OBJECT WITH NO DEFINED POSITION:");
+				while(results.hasNext())
+					System.err.println("    * " + results.next().toADQL());
+				fail("At least one item of the generated ADQL tree does not have a position information! (see System.err for more details)");
+			}
+		}catch(ParseException pe){
+			pe.printStackTrace();
+			fail("No error should have occured here: the ADQL query is syntactically correct!");
+		}
+	}
+
+	private void assertEquality(final TextPosition expected, final TextPosition realPos){
+		assertEquals(expected.beginLine, realPos.beginLine);
+		assertEquals(expected.beginColumn, realPos.beginColumn);
+		assertEquals(expected.endLine, realPos.endLine);
+		assertEquals(expected.endColumn, realPos.endColumn);
+	}
+
+	@Test
+	public void testPositionAccuracy(){
+		try{
+			ADQLQuery query = parser.parseQuery("SELECT TOP 1000 oid FROM foo JOIN bar USING(oid)\nWHERE foo || toto = 'truc'\n      AND 2 > 1+0 GROUP BY oid HAVING COUNT(oid) > 10\n\tORDER BY 1 DESC");
+			// Test SELECT
+			assertEquality(new TextPosition(1, 1, 1, 20), query.getSelect().getPosition());
+			// Test ADQLColumn (here: "oid")
+			assertEquality(new TextPosition(1, 17, 1, 20), query.getSelect().get(0).getPosition());
+			// Test FROM & ADQLJoin
+			/* NB: The clause FROM is the only one which is not a list but a single item of type FromContent (JOIN or table).
+			 *     That's why, it is not possible to get its exact starting position ('FROM') ; the starting position is
+			 *     the one of the first table of the clause FROM. */
+			assertEquality(new TextPosition(1, 26, 1, 49), query.getFrom().getPosition());
+			// Test ADQLTable
+			ArrayList<ADQLTable> tables = query.getFrom().getTables();
+			assertEquality(new TextPosition(1, 26, 1, 29), tables.get(0).getPosition());
+			assertEquality(new TextPosition(1, 35, 1, 38), tables.get(1).getPosition());
+			// Test the join condition:
+			Iterator<ADQLColumn> itCol = ((ADQLJoin)query.getFrom()).getJoinedColumns();
+			assertEquality(new TextPosition(1, 45, 1, 48), itCol.next().getPosition());
+			// Test WHERE
+			assertEquality(new TextPosition(2, 1, 3, 18), query.getWhere().getPosition());
+			// Test COMPARISON = CONSTRAINT
+			Comparison comp = (Comparison)(query.getWhere().get(0));
+			assertEquality(new TextPosition(2, 7, 2, 27), comp.getPosition());
+			// Test left operand = concatenation:
+			ADQLOperand operand = comp.getLeftOperand();
+			assertEquality(new TextPosition(2, 7, 2, 18), operand.getPosition());
+			Iterator<ADQLObject> itObj = operand.adqlIterator();
+			// foo
+			assertEquality(new TextPosition(2, 7, 2, 10), itObj.next().getPosition());
+			// toto
+			assertEquality(new TextPosition(2, 14, 2, 18), itObj.next().getPosition());
+			// Test right operand = string:
+			operand = comp.getRightOperand();
+			assertEquality(new TextPosition(2, 21, 2, 27), operand.getPosition());
+			// Test COMPARISON > CONSTRAINT:
+			comp = (Comparison)(query.getWhere().get(1));
+			assertEquality(new TextPosition(3, 11, 3, 18), comp.getPosition());
+			// Test left operand = numeric:
+			operand = comp.getLeftOperand();
+			assertEquality(new TextPosition(3, 11, 3, 12), operand.getPosition());
+			// Test right operand = operation:
+			operand = comp.getRightOperand();
+			assertEquality(new TextPosition(3, 15, 3, 18), operand.getPosition());
+			itObj = operand.adqlIterator();
+			// 1
+			assertEquality(new TextPosition(3, 15, 3, 16), itObj.next().getPosition());
+			// 0
+			assertEquality(new TextPosition(3, 17, 3, 18), itObj.next().getPosition());
+			// Test GROUP BY
+			assertEquality(new TextPosition(3, 19, 3, 31), query.getGroupBy().getPosition());
+			// oid
+			assertEquality(new TextPosition(3, 28, 3, 31), query.getGroupBy().get(0).getPosition());
+			// Test HAVING
+			assertEquality(new TextPosition(3, 32, 3, 54), query.getHaving().getPosition());
+			// Test COMPARISON > CONSTRAINT:
+			comp = (Comparison)(query.getHaving().get(0));
+			assertEquality(new TextPosition(3, 39, 3, 54), comp.getPosition());
+			// Test left operand = COUNT function:
+			operand = comp.getLeftOperand();
+			assertEquality(new TextPosition(3, 39, 3, 49), operand.getPosition());
+			// Test parameter = ADQLColumn oid:
+			assertEquality(new TextPosition(3, 45, 3, 48), ((ADQLFunction)operand).getParameter(0).getPosition());
+			// Test right operand = operation:
+			operand = comp.getRightOperand();
+			assertEquality(new TextPosition(3, 52, 3, 54), operand.getPosition());
+			// Test ORDER BY
+			assertEquality(new TextPosition(4, 9, 4, 24), query.getOrderBy().getPosition());
+			// Test column index:
+			assertEquality(new TextPosition(4, 18, 4, 19), query.getOrderBy().get(0).getPosition());
+
+		}catch(ParseException pe){
+			System.err.println("ERROR IN THE ADQL QUERY AT " + pe.getPosition());
+			pe.printStackTrace();
+			fail("No error should have occured here: the ADQL query is syntactically correct!");
+		}
+	}
+
+}
diff --git a/test/adql/db/TestDBChecker.java b/test/adql/db/TestDBChecker.java
index 3f9924a8616ad959deebbbbab8f7df1dac96b3f8..36b85b792e4de94f734fafe4b5edf4973fecb2ae 100644
--- a/test/adql/db/TestDBChecker.java
+++ b/test/adql/db/TestDBChecker.java
@@ -315,7 +315,7 @@ public class TestDBChecker {
 			assertTrue(pe instanceof UnresolvedIdentifiersException);
 			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe;
 			assertEquals(1, ex.getNbErrors());
-			assertEquals("Coordinate system \"fk5 geocenter\" (= \"FK5 GEOCENTER SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage());
+			assertEquals("Coordinate system \"fk5 geocenter\" (= \"FK5 GEOCENTER SPHERICAL2\") not allowed in this implementation. Allowed coordinate systems are: fk4 geocenter *, galactic * spherical2, icrs * *", ex.getErrors().next().getMessage());
 		}
 		try{
 			parser.parseQuery("SELECT Region('not(position fk5 heliocenter 1 2)') FROM foo;");
@@ -324,7 +324,7 @@ public class TestDBChecker {
 			assertTrue(pe instanceof UnresolvedIdentifiersException);
 			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe;
 			assertEquals(1, ex.getNbErrors());
-			assertEquals("Coordinate system \"FK5 HELIOCENTER\" (= \"FK5 HELIOCENTER SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage());
+			assertEquals("Coordinate system \"FK5 HELIOCENTER\" (= \"FK5 HELIOCENTER SPHERICAL2\") not allowed in this implementation. Allowed coordinate systems are: fk4 geocenter *, galactic * spherical2, icrs * *", ex.getErrors().next().getMessage());
 		}
 
 		// Test with a coordinate system while none is allowed:
@@ -345,8 +345,8 @@ public class TestDBChecker {
 			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe;
 			assertEquals(2, ex.getNbErrors());
 			Iterator<ParseException> itErrors = ex.getErrors();
-			assertEquals("Coordinate system \"ICRS SPHERICAL2\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", itErrors.next().getMessage());
-			assertEquals("Coordinate system \"icrs\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", itErrors.next().getMessage());
+			assertEquals("Coordinate system \"ICRS SPHERICAL2\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation. No coordinate system is allowed!", itErrors.next().getMessage());
+			assertEquals("Coordinate system \"icrs\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation. No coordinate system is allowed!", itErrors.next().getMessage());
 		}
 		try{
 			parser.parseQuery("SELECT Region('not(position fk4 1 2)') FROM foo;");
@@ -355,7 +355,7 @@ public class TestDBChecker {
 			assertTrue(pe instanceof UnresolvedIdentifiersException);
 			UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe;
 			assertEquals(1, ex.getNbErrors());
-			assertEquals("Coordinate system \"FK4\" (= \"FK4 UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage());
+			assertEquals("Coordinate system \"FK4\" (= \"FK4 UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation. No coordinate system is allowed!", ex.getErrors().next().getMessage());
 		}
 	}