diff --git a/exec/java-exec/pom.xml b/exec/java-exec/pom.xml
index 9d86187..1408935 100644
--- a/exec/java-exec/pom.xml
+++ b/exec/java-exec/pom.xml
@@ -818,6 +818,51 @@
         </dependency>
       </dependencies>
     </profile>
+    <profile>
+      <!-- If Drill has not provided its own parser grammar at the location
+      below then we default to Calcite's. You'd have hoped that a simple
+      overWrite=false setting in the relevant maven-dependency-plugin unpack
+      goal in this pom would have been sufficient but alas this whole new
+      profile is required. -->
+      <id>calcite-parser-grammar</id>
+      <activation>
+        <file>
+          <missing>${basedir}/src/main/codegen/templates/Parser.jj</missing>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <executions>
+             <!-- Extract parser grammar template from calcite-core.jar and put
+          it under ${project.build.directory}/codegen/templates where all freemarker templates are. -->
+              <execution>
+                <id>unpack-parser-template</id>
+                <phase>initialize</phase>
+                <goals>
+                  <goal>unpack</goal>
+                </goals>
+                <configuration>
+                  <overWrite>false</overWrite>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${calcite.groupId}</groupId>
+                      <artifactId>calcite-core</artifactId>
+                      <type>jar</type>
+                      <overWrite>false</overWrite>
+                      <outputDirectory>${project.build.directory}/</outputDirectory>
+                      <includes>codegen/templates/Parser.jj</includes>
+                    </artifactItem>
+                  </artifactItems>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
   <build>
     <plugins>
@@ -849,28 +894,6 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
         <executions>
-        <!-- Extract parser grammar template from calcite-core.jar and put
-          it under ${project.build.directory}/codegen/templates where all freemarker templates are. -->
-          <execution>
-            <id>unpack-parser-template</id>
-            <phase>initialize</phase>
-            <goals>
-              <goal>unpack</goal>
-            </goals>
-            <configuration>
-              <artifactItems>
-                <artifactItem>
-                  <groupId>${calcite.groupId}</groupId>
-                  <artifactId>calcite-core</artifactId>
-                  <type>jar</type>
-                  <overWrite>true</overWrite>
-                  <outputDirectory>${project.build.directory}/</outputDirectory>
-                  <includes>codegen/templates/Parser.jj</includes>
-                </artifactItem>
-              </artifactItems>
-            </configuration>
-          </execution>
-
         <!-- Extract ValueVectorTypes.tdd from drill-vector.jar and put
           it under ${project.build.directory}/codegen/data where all freemarker data files are. -->
           <execution>
diff --git a/exec/java-exec/src/main/codegen/templates/Parser.jj b/exec/java-exec/src/main/codegen/templates/Parser.jj
new file mode 100644
index 0000000..b5d9f96
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/templates/Parser.jj
@@ -0,0 +1,8758 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO: Delete this file to reinstate its extraction from calcite-core.jar
+// once CALCITE-5579 is resolved and the incompatible grammar changes introduced
+// by CALCITE-5469 have been backed out. Also see: exec/java-exec/pom.xml.
+
+<@pp.dropOutputFile />
+
+<@pp.changeOutputFile name="javacc/Parser.jj" />
+
+options {
+    STATIC = false;
+    IGNORE_CASE = true;
+    UNICODE_INPUT = true;
+}
+
+
+PARSER_BEGIN(${parser.class})
+
+package ${parser.package};
+
+<#list (parser.imports!default.parser.imports) as importStr>
+import ${importStr};
+</#list>
+
+import org.apache.calcite.avatica.util.Casing;
+import org.apache.calcite.avatica.util.TimeUnit;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.runtime.CalciteContextException;
+import org.apache.calcite.sql.JoinConditionType;
+import org.apache.calcite.sql.JoinType;
+import org.apache.calcite.sql.SqlAlter;
+import org.apache.calcite.sql.SqlBasicTypeNameSpec;
+import org.apache.calcite.sql.SqlBinaryOperator;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlCharStringLiteral;
+import org.apache.calcite.sql.SqlCollation;
+import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
+import org.apache.calcite.sql.SqlDataTypeSpec;
+import org.apache.calcite.sql.SqlDelete;
+import org.apache.calcite.sql.SqlDescribeSchema;
+import org.apache.calcite.sql.SqlDescribeTable;
+import org.apache.calcite.sql.SqlDynamicParam;
+import org.apache.calcite.sql.SqlExplain;
+import org.apache.calcite.sql.SqlExplainFormat;
+import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlHint;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlInsert;
+import org.apache.calcite.sql.SqlInsertKeyword;
+import org.apache.calcite.sql.SqlIntervalQualifier;
+import org.apache.calcite.sql.SqlJdbcDataTypeName;
+import org.apache.calcite.sql.SqlJdbcFunctionCall;
+import org.apache.calcite.sql.SqlJoin;
+import org.apache.calcite.sql.SqlJsonConstructorNullClause;
+import org.apache.calcite.sql.SqlJsonEncoding;
+import org.apache.calcite.sql.SqlJsonExistsErrorBehavior;
+import org.apache.calcite.sql.SqlJsonEmptyOrError;
+import org.apache.calcite.sql.SqlJsonQueryEmptyOrErrorBehavior;
+import org.apache.calcite.sql.SqlJsonQueryWrapperBehavior;
+import org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior;
+import org.apache.calcite.sql.SqlJsonValueReturning;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlMatchRecognize;
+import org.apache.calcite.sql.SqlMerge;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlNumericLiteral;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlOrderBy;
+import org.apache.calcite.sql.SqlPivot;
+import org.apache.calcite.sql.SqlPostfixOperator;
+import org.apache.calcite.sql.SqlPrefixOperator;
+import org.apache.calcite.sql.SqlRowTypeNameSpec;
+import org.apache.calcite.sql.SqlSampleSpec;
+import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.SqlSelectKeyword;
+import org.apache.calcite.sql.SqlSetOption;
+import org.apache.calcite.sql.SqlSnapshot;
+import org.apache.calcite.sql.SqlTableRef;
+import org.apache.calcite.sql.SqlTypeNameSpec;
+import org.apache.calcite.sql.SqlUnnestOperator;
+import org.apache.calcite.sql.SqlUnpivot;
+import org.apache.calcite.sql.SqlUpdate;
+import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec;
+import org.apache.calcite.sql.SqlUtil;
+import org.apache.calcite.sql.SqlWindow;
+import org.apache.calcite.sql.SqlWith;
+import org.apache.calcite.sql.SqlWithItem;
+import org.apache.calcite.sql.fun.SqlCase;
+import org.apache.calcite.sql.fun.SqlInternalOperators;
+import org.apache.calcite.sql.fun.SqlLibraryOperators;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.fun.SqlTrimFunction;
+import org.apache.calcite.sql.parser.Span;
+import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.parser.SqlParserImplFactory;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.parser.SqlParserUtil;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.validate.SqlConformance;
+import org.apache.calcite.util.Glossary;
+import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.SourceStringReader;
+import org.apache.calcite.util.Util;
+import org.apache.calcite.util.trace.CalciteTrace;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.slf4j.Logger;
+
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.apache.calcite.util.Static.RESOURCE;
+
+/**
+ * SQL parser, generated from Parser.jj by JavaCC.
+ *
+ * <p>The public wrapper for this parser is {@link SqlParser}.
+ */
+public class ${parser.class} extends SqlAbstractParserImpl
+{
+    private static final Logger LOGGER = CalciteTrace.getParserTracer();
+
+    // Can't use quoted literal because of a bug in how JavaCC translates
+    // backslash-backslash.
+    private static final char BACKSLASH = 0x5c;
+    private static final char DOUBLE_QUOTE = 0x22;
+    private static final String DQ = DOUBLE_QUOTE + "";
+    private static final String DQDQ = DQ + DQ;
+    private static final SqlLiteral LITERAL_ZERO =
+        SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO);
+    private static final SqlLiteral LITERAL_ONE =
+        SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO);
+    private static final SqlLiteral LITERAL_MINUS_ONE =
+        SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
+
+    private static Metadata metadata;
+
+    private Casing unquotedCasing;
+    private Casing quotedCasing;
+    private int identifierMaxLength;
+    private SqlConformance conformance;
+
+    /**
+     * {@link SqlParserImplFactory} implementation for creating parser.
+     */
+    public static final SqlParserImplFactory FACTORY = new SqlParserImplFactory() {
+        public SqlAbstractParserImpl getParser(Reader reader) {
+            final ${parser.class} parser = new ${parser.class}(reader);
+            if (reader instanceof SourceStringReader) {
+                final String sql =
+                    ((SourceStringReader) reader).getSourceString();
+                parser.setOriginalSql(sql);
+            }
+          return parser;
+        }
+    };
+
+    public SqlParseException normalizeException(Throwable ex) {
+        try {
+            if (ex instanceof ParseException) {
+                ex = cleanupParseException((ParseException) ex);
+            }
+            return convertException(ex);
+        } catch (ParseException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    public Metadata getMetadata() {
+        synchronized (${parser.class}.class) {
+            if (metadata == null) {
+                metadata = new MetadataImpl(
+                    new ${parser.class}(new java.io.StringReader("")));
+            }
+            return metadata;
+        }
+    }
+
+    public void setTabSize(int tabSize) {
+        jj_input_stream.setTabSize(tabSize);
+    }
+
+    public void switchTo(SqlAbstractParserImpl.LexicalState state) {
+        final int stateOrdinal =
+            Arrays.asList(${parser.class}TokenManager.lexStateNames)
+                .indexOf(state.name());
+        token_source.SwitchTo(stateOrdinal);
+    }
+
+    public void setQuotedCasing(Casing quotedCasing) {
+        this.quotedCasing = quotedCasing;
+    }
+
+    public void setUnquotedCasing(Casing unquotedCasing) {
+        this.unquotedCasing = unquotedCasing;
+    }
+
+    public void setIdentifierMaxLength(int identifierMaxLength) {
+        this.identifierMaxLength = identifierMaxLength;
+    }
+
+    public void setConformance(SqlConformance conformance) {
+        this.conformance = conformance;
+    }
+
+    public SqlNode parseSqlExpressionEof() throws Exception {
+        return SqlExpressionEof();
+    }
+
+    public SqlNode parseSqlStmtEof() throws Exception {
+        return SqlStmtEof();
+    }
+
+    public SqlNodeList parseSqlStmtList() throws Exception {
+        return SqlStmtList();
+    }
+
+    public SqlNode parseArray() throws SqlParseException {
+        switchTo(LexicalState.BQID);
+        try {
+          return ArrayLiteral();
+        } catch (ParseException ex) {
+          throw normalizeException(ex);
+        } catch (TokenMgrError ex) {
+          throw normalizeException(ex);
+        }
+    }
+
+    private SqlNode extend(SqlNode table, SqlNodeList extendList) {
+        return SqlStdOperatorTable.EXTEND.createCall(
+            Span.of(table, extendList).pos(), table, extendList);
+    }
+
+    /** Adds a warning that a token such as "HOURS" was used,
+    * whereas the SQL standard only allows "HOUR".
+    *
+    * <p>Currently, we silently add an exception to a list of warnings. In
+    * future, we may have better compliance checking, for example a strict
+    * compliance mode that throws if any non-standard features are used. */
+    private TimeUnit warn(TimeUnit timeUnit) throws ParseException {
+        final String token = getToken(0).image.toUpperCase(Locale.ROOT);
+        warnings.add(
+            SqlUtil.newContextException(getPos(),
+                RESOURCE.nonStandardFeatureUsed(token)));
+        return timeUnit;
+    }
+}
+
+PARSER_END(${parser.class})
+
+
+/***************************************
+ * Utility Codes for Semantic Analysis *
+ ***************************************/
+
+/* For Debug */
+JAVACODE
+void debug_message1() {
+    LOGGER.info("{} , {}", getToken(0).image, getToken(1).image);
+}
+
+JAVACODE String unquotedIdentifier() {
+    return SqlParserUtil.toCase(getToken(0).image, unquotedCasing);
+}
+
+/**
+ * Allows parser to be extended with new types of table references.  The
+ * default implementation of this production is empty.
+ */
+SqlNode ExtendedTableRef() :
+{
+}
+{
+    UnusedExtension()
+    {
+        return null;
+    }
+}
+
+/**
+ * Allows an OVER clause following a table expression as an extension to
+ * standard SQL syntax. The default implementation of this production is empty.
+ */
+SqlNode TableOverOpt() :
+{
+}
+{
+    {
+        return null;
+    }
+}
+
+/*
+ * Parses dialect-specific keywords immediately following the SELECT keyword.
+ */
+void SqlSelectKeywords(List<SqlLiteral> keywords) :
+{}
+{
+    E()
+}
+
+/*
+ * Parses dialect-specific keywords immediately following the INSERT keyword.
+ */
+void SqlInsertKeywords(List<SqlLiteral> keywords) :
+{}
+{
+    E()
+}
+
+/*
+* Parse Floor/Ceil function parameters
+*/
+SqlNode FloorCeilOptions(Span s, boolean floorFlag) :
+{
+    SqlNode node;
+}
+{
+    node = StandardFloorCeilOptions(s, floorFlag) {
+        return node;
+    }
+}
+
+/*
+// This file contains the heart of a parser for SQL SELECT statements.
+// code can be shared between various parsers (for example, a DDL parser and a
+// DML parser) but is not a standalone JavaCC file. You need to prepend a
+// parser declaration (such as that in Parser.jj).
+*/
+
+/* Epsilon */
+JAVACODE
+void E() {}
+
+/** @Deprecated */
+JAVACODE List startList(Object o)
+{
+    List list = new ArrayList();
+    list.add(o);
+    return list;
+}
+
+/*
+ * NOTE jvs 6-Feb-2004: The straightforward way to implement the SQL grammar is
+ * to keep query expressions (SELECT, UNION, etc) separate from row expressions
+ * (+, LIKE, etc).  However, this is not possible with an LL(k) parser, because
+ * both kinds of expressions allow parenthesization, so no fixed amount of left
+ * context is ever good enough.  A sub-query can be a leaf in a row expression,
+ * and can include operators like UNION, so it's not even possible to use a
+ * syntactic lookahead rule like "look past an indefinite number of parentheses
+ * until you see SELECT, VALUES, or TABLE" (since at that point we still
+ * don't know whether we're parsing a sub-query like ((select ...) + x)
+ * vs. (select ... union select ...).
+ *
+ * The somewhat messy solution is to unify the two kinds of expression,
+ * and to enforce syntax rules using parameterized context.  This
+ * is the purpose of the ExprContext parameter.  It is passed to
+ * most expression productions, which check the expressions encountered
+ * against the context for correctness.  When a query
+ * element like SELECT is encountered, the production calls
+ * checkQueryExpression, which will throw an exception if
+ * a row expression was expected instead.  When a row expression like
+ * IN is encountered, the production calls checkNonQueryExpression
+ * instead.  It is very important to understand how this works
+ * when modifying the grammar.
+ *
+ * The commingling of expressions results in some bogus ambiguities which are
+ * resolved with LOOKAHEAD hints.  The worst example is comma.  SQL allows both
+ * (WHERE x IN (1,2)) and (WHERE x IN (select ...)).  This means when we parse
+ * the right-hand-side of an IN, we have to allow any kind of expression inside
+ * the parentheses.  Now consider the expression "WHERE x IN(SELECT a FROM b
+ * GROUP BY c,d)".  When the parser gets to "c,d" it doesn't know whether the
+ * comma indicates the end of the GROUP BY or the end of one item in an IN
+ * list.  Luckily, we know that select and comma-list are mutually exclusive
+ * within IN, so we use maximal munch for the GROUP BY comma.  However, this
+ * usage of hints could easily mask unintended ambiguities resulting from
+ * future changes to the grammar, making it very brittle.
+ */
+
+JAVACODE protected SqlParserPos getPos()
+{
+    return new SqlParserPos(
+        token.beginLine,
+        token.beginColumn,
+        token.endLine,
+        token.endColumn);
+}
+
+/** Starts a span at the current position. */
+JAVACODE Span span()
+{
+    return Span.of(getPos());
+}
+
+JAVACODE void checkQueryExpression(ExprContext exprContext)
+{
+    switch (exprContext) {
+    case ACCEPT_NON_QUERY:
+    case ACCEPT_SUB_QUERY:
+    case ACCEPT_CURSOR:
+        throw SqlUtil.newContextException(getPos(),
+            RESOURCE.illegalQueryExpression());
+    }
+}
+
+JAVACODE void checkNonQueryExpression(ExprContext exprContext)
+{
+    switch (exprContext) {
+    case ACCEPT_QUERY:
+        throw SqlUtil.newContextException(getPos(),
+            RESOURCE.illegalNonQueryExpression());
+    }
+}
+
+JAVACODE SqlNode checkNotJoin(SqlNode e)
+{
+    if (e instanceof SqlJoin) {
+        throw SqlUtil.newContextException(e.getParserPosition(),
+            RESOURCE.illegalJoinExpression());
+    }
+    return e;
+}
+
+/**
+ * Converts a ParseException (local to this particular instantiation
+ * of the parser) into a SqlParseException (common to all parsers).
+ */
+JAVACODE SqlParseException convertException(Throwable ex)
+{
+    if (ex instanceof SqlParseException) {
+        return (SqlParseException) ex;
+    }
+    SqlParserPos pos = null;
+    int[][] expectedTokenSequences = null;
+    String[] tokenImage = null;
+    if (ex instanceof ParseException) {
+        ParseException pex = (ParseException) ex;
+        expectedTokenSequences = pex.expectedTokenSequences;
+        tokenImage = pex.tokenImage;
+        if (pex.currentToken != null) {
+            final Token token = pex.currentToken.next;
+            // Checks token.image.equals("1") to avoid recursive call.
+            // The SqlAbstractParserImpl#MetadataImpl constructor uses constant "1" to
+            // throw intentionally to collect the expected tokens.
+            if (!token.image.equals("1")
+                && getMetadata().isKeyword(token.image)
+                && SqlParserUtil.allowsIdentifier(tokenImage, expectedTokenSequences)) {
+                // If the next token is a keyword, reformat the error message as:
+
+                // Incorrect syntax near the keyword '{keyword}' at line {line_number},
+                // column {column_number}.
+                final String expecting = ex.getMessage()
+                    .substring(ex.getMessage().indexOf("Was expecting"));
+                final String errorMsg = String.format("Incorrect syntax near the keyword '%s' "
+                        + "at line %d, column %d.\n%s",
+                    token.image,
+                    token.beginLine,
+                    token.beginColumn,
+                    expecting);
+                // Replace the ParseException with explicit error message.
+                ex = new ParseException(errorMsg);
+            }
+            pos = new SqlParserPos(
+                token.beginLine,
+                token.beginColumn,
+                token.endLine,
+                token.endColumn);
+        }
+    } else if (ex instanceof TokenMgrError) {
+        expectedTokenSequences = null;
+        tokenImage = null;
+        // Example:
+        //    Lexical error at line 3, column 24.  Encountered "#" after "a".
+        final java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(
+            "(?s)Lexical error at line ([0-9]+), column ([0-9]+).*");
+        java.util.regex.Matcher matcher = pattern.matcher(ex.getMessage());
+        if (matcher.matches()) {
+            int line = Integer.parseInt(matcher.group(1));
+            int column = Integer.parseInt(matcher.group(2));
+            pos = new SqlParserPos(line, column, line, column);
+        }
+    } else if (ex instanceof CalciteContextException) {
+        // CalciteContextException is the standard wrapper for exceptions
+        // produced by the validator, but in the parser, the standard is
+        // SqlParseException; so, strip it away. In case you were wondering,
+        // the CalciteContextException appears because the parser
+        // occasionally calls into validator-style code such as
+        // SqlSpecialOperator.reduceExpr.
+        CalciteContextException ece =
+            (CalciteContextException) ex;
+        pos = new SqlParserPos(
+            ece.getPosLine(),
+            ece.getPosColumn(),
+            ece.getEndPosLine(),
+            ece.getEndPosColumn());
+        ex = ece.getCause();
+    }
+
+    return new SqlParseException(
+        ex.getMessage(), pos, expectedTokenSequences, tokenImage, ex);
+}
+
+/**
+ * Removes or transforms misleading information from a parse exception.
+ *
+ * @param e dirty excn
+ *
+ * @return clean excn
+ */
+JAVACODE ParseException cleanupParseException(ParseException ex)
+{
+    if (ex.expectedTokenSequences == null) {
+        return ex;
+    }
+    int iIdentifier = Arrays.asList(ex.tokenImage).indexOf("<IDENTIFIER>");
+
+    // Find all sequences in the error which contain identifier. For
+    // example,
+    //       {<IDENTIFIER>}
+    //       {A}
+    //       {B, C}
+    //       {D, <IDENTIFIER>}
+    //       {D, A}
+    //       {D, B}
+    //
+    // would yield
+    //       {}
+    //       {D}
+    final List<int[]> prefixList = new ArrayList<int[]>();
+    for (int i = 0; i < ex.expectedTokenSequences.length; ++i) {
+        int[] seq = ex.expectedTokenSequences[i];
+        int j = seq.length - 1;
+        int i1 = seq[j];
+        if (i1 == iIdentifier) {
+            int[] prefix = new int[j];
+            System.arraycopy(seq, 0, prefix, 0, j);
+            prefixList.add(prefix);
+        }
+    }
+
+    if (prefixList.isEmpty()) {
+        return ex;
+    }
+
+    int[][] prefixes = (int[][])
+        prefixList.toArray(new int[prefixList.size()][]);
+
+    // Since <IDENTIFIER> was one of the possible productions,
+    // we know that the parser will also have included all
+    // of the non-reserved keywords (which are treated as
+    // identifiers in non-keyword contexts).  So, now we need
+    // to clean those out, since they're totally irrelevant.
+
+    final List<int[]> list = new ArrayList<int[]>();
+    Metadata metadata = getMetadata();
+    for (int i = 0; i < ex.expectedTokenSequences.length; ++i) {
+        int [] seq = ex.expectedTokenSequences[i];
+        String tokenImage = ex.tokenImage[seq[seq.length - 1]];
+        String token = SqlParserUtil.getTokenVal(tokenImage);
+        if (token == null  || !metadata.isNonReservedKeyword(token)) {
+            list.add(seq);
+            continue;
+        }
+        boolean match = matchesPrefix(seq, prefixes);
+        if (!match) {
+            list.add(seq);
+        }
+    }
+
+    ex.expectedTokenSequences =
+        (int [][]) list.toArray(new int [list.size()][]);
+    return ex;
+}
+
+JAVACODE boolean matchesPrefix(int[] seq, int[][] prefixes)
+{
+    nextPrefix:
+    for (int[] prefix : prefixes) {
+        if (seq.length == prefix.length + 1) {
+            for (int k = 0; k < prefix.length; k++) {
+                if (prefix[k] != seq[k]) {
+                    continue nextPrefix;
+                }
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+/*****************************************
+ * Syntactical Descriptions              *
+ *****************************************/
+
+SqlNode ExprOrJoinOrOrderedQuery(ExprContext exprContext) :
+{
+    SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+}
+{
+    // Lookhead to distinguish between "TABLE emp" (which will be
+    // matched by ExplicitTable() via Query())
+    // and "TABLE fun(args)" (which will be matched by TableRef())
+    (
+        LOOKAHEAD(2)
+        e = Query(exprContext)
+        e = OrderByLimitOpt(e)
+        { return e; }
+    |
+        e = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN)
+        ( e = JoinTable(e) )*
+        { list.add(e); }
+        ( AddSetOpQuery(list, exprContext) )*
+        { return SqlParserUtil.toTree(list); }
+    )
+}
+
+/**
+ * Parses either a row expression or a query expression with an optional
+ * ORDER BY.
+ *
+ * <p>Postgres syntax for limit:
+ *
+ * <blockquote><pre>
+ *    [ LIMIT { count | ALL } ]
+ *    [ OFFSET start ]</pre>
+ * </blockquote>
+ *
+ * <p>Trino syntax for limit:
+ *
+ * <blockquote><pre>
+ *    [ OFFSET start ]
+ *    [ LIMIT { count | ALL } ]</pre>
+ * </blockquote>
+ *
+ * <p>MySQL syntax for limit:
+ *
+ * <blockquote><pre>
+ *    [ LIMIT { count | start, count } ]</pre>
+ * </blockquote>
+ *
+ * <p>SQL:2008 syntax for limit:
+ *
+ * <blockquote><pre>
+ *    [ OFFSET start { ROW | ROWS } ]
+ *    [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]</pre>
+ * </blockquote>
+ */
+SqlNode OrderedQueryOrExpr(ExprContext exprContext) :
+{
+    SqlNode e;
+}
+{
+    e = QueryOrExpr(exprContext)
+    e = OrderByLimitOpt(e)
+    { return e; }
+}
+
+/** Reads optional "ORDER BY", "LIMIT", "OFFSET", "FETCH" following a query,
+ * {@code e}. If any of them are present, adds them to the query;
+ * otherwise returns the query unchanged.
+ * Throws if they are present and {@code e} is not a query. */
+SqlNode OrderByLimitOpt(SqlNode e) :
+{
+    final SqlNodeList orderBy;
+    final Span s = Span.of();
+    SqlNode[] offsetFetch = {null, null};
+}
+{
+    (
+        // use the syntactic type of the expression we just parsed
+        // to decide whether ORDER BY makes sense
+        orderBy = OrderBy(e.isA(SqlKind.QUERY))
+    |   { orderBy = null; }
+    )
+    [
+        LimitClause(s, offsetFetch)
+        [ OffsetClause(s, offsetFetch) ]
+    |
+        OffsetClause(s, offsetFetch)
+        [
+            LimitClause(s, offsetFetch) {
+                if (!this.conformance.isOffsetLimitAllowed()) {
+                    throw SqlUtil.newContextException(s.end(this),
+                        RESOURCE.offsetLimitNotAllowed());
+                }
+            }
+        |
+            FetchClause(offsetFetch)
+        ]
+    |
+        FetchClause(offsetFetch)
+    ]
+    {
+        if (orderBy != null || offsetFetch[0] != null || offsetFetch[1] != null) {
+            return new SqlOrderBy(getPos(), e,
+                Util.first(orderBy, SqlNodeList.EMPTY),
+                offsetFetch[0], offsetFetch[1]);
+        }
+        return e;
+    }
+}
+
+/**
+ * Parses an OFFSET clause in an ORDER BY expression.
+ */
+void OffsetClause(Span s, SqlNode[] offsetFetch) :
+{
+}
+{
+    // ROW or ROWS is required in SQL:2008 but we make it optional
+    // because it is not present in Postgres-style syntax.
+    <OFFSET> { s.add(this); }
+    offsetFetch[0] = UnsignedNumericLiteralOrParam()
+    [ <ROW> | <ROWS> ]
+}
+
+/**
+ * Parses a FETCH clause in an ORDER BY expression.
+ */
+void FetchClause(SqlNode[] offsetFetch) :
+{
+}
+{
+    // SQL:2008-style syntax. "OFFSET ... FETCH ...".
+    // If you specify both LIMIT and FETCH, FETCH wins.
+    <FETCH> ( <FIRST> | <NEXT> ) offsetFetch[1] = UnsignedNumericLiteralOrParam()
+    ( <ROW> | <ROWS> ) <ONLY>
+}
+
+/**
+ * Parses a LIMIT clause in an ORDER BY expression.
+ */
+void LimitClause(Span s, SqlNode[] offsetFetch) :
+{
+}
+{
+    // Postgres-style syntax. "LIMIT ... OFFSET ..."
+    <LIMIT> { s.add(this); }
+    (
+        // MySQL-style syntax. "LIMIT start, count"
+        LOOKAHEAD(2)
+        offsetFetch[0] = UnsignedNumericLiteralOrParam()
+        <COMMA> offsetFetch[1] = UnsignedNumericLiteralOrParam() {
+            if (!this.conformance.isLimitStartCountAllowed()) {
+                throw SqlUtil.newContextException(s.end(this),
+                    RESOURCE.limitStartCountNotAllowed());
+            }
+        }
+    |
+        offsetFetch[1] = UnsignedNumericLiteralOrParam()
+    |
+        <ALL>
+    )
+}
+
+/**
+ * Parses a leaf in a query expression (SELECT, VALUES or TABLE).
+ */
+SqlNode LeafQuery(ExprContext exprContext) :
+{
+    SqlNode e;
+}
+{
+    {
+        // ensure a query is legal in this context
+        checkQueryExpression(exprContext);
+    }
+    e = SqlSelect() { return e; }
+|
+    e = TableConstructor() { return e; }
+|
+    e = ExplicitTable(getPos()) { return e; }
+}
+
+/**
+ * Parses a parenthesized query or single row expression.
+ * Depending on {@code exprContext}, may also accept a join.
+ */
+SqlNode ParenthesizedExpression(ExprContext exprContext) :
+{
+    SqlNode e;
+}
+{
+    <LPAREN>
+    {
+        // we've now seen left paren, so queries inside should
+        // be allowed as sub-queries
+        switch (exprContext) {
+        case ACCEPT_SUB_QUERY:
+            exprContext = ExprContext.ACCEPT_NONCURSOR;
+            break;
+        case ACCEPT_CURSOR:
+            exprContext = ExprContext.ACCEPT_ALL;
+            break;
+        }
+    }
+    e = ExprOrJoinOrOrderedQuery(exprContext)
+    <RPAREN>
+    {
+        exprContext.throwIfNotCompatible(e);
+        return e;
+    }
+}
+
+/**
+ * Parses a parenthesized query or comma-list of row expressions.
+ *
+ * <p>REVIEW jvs 8-Feb-2004: There's a small hole in this production.  It can be
+ * used to construct something like
+ *
+ * <blockquote><pre>
+ * WHERE x IN (select count(*) from t where c=d,5)</pre>
+ * </blockquote>
+ *
+ * <p>which should be illegal.  The above is interpreted as equivalent to
+ *
+ * <blockquote><pre>
+ * WHERE x IN ((select count(*) from t where c=d),5)</pre>
+ * </blockquote>
+ *
+ * <p>which is a legal use of a sub-query.  The only way to fix the hole is to
+ * be able to remember whether a subexpression was parenthesized or not, which
+ * means preserving parentheses in the SqlNode tree.  This is probably
+ * desirable anyway for use in purely syntactic parsing applications (e.g. SQL
+ * pretty-printer).  However, if this is done, it's important to also make
+ * isA() on the paren node call down to its operand so that we can
+ * always correctly discriminate a query from a row expression.
+ */
+SqlNodeList ParenthesizedQueryOrCommaList(
+    ExprContext exprContext) :
+{
+    SqlNode e;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    ExprContext firstExprContext = exprContext;
+    final Span s;
+}
+{
+    <LPAREN>
+    {
+        // we've now seen left paren, so a query by itself should
+        // be interpreted as a sub-query
+        s = span();
+        switch (exprContext) {
+        case ACCEPT_SUB_QUERY:
+            firstExprContext = ExprContext.ACCEPT_NONCURSOR;
+            break;
+        case ACCEPT_CURSOR:
+            firstExprContext = ExprContext.ACCEPT_ALL;
+            break;
+        }
+    }
+    e = OrderedQueryOrExpr(firstExprContext) { list.add(e); }
+    (
+        <COMMA>
+        {
+            // a comma-list can't appear where only a query is expected
+            checkNonQueryExpression(exprContext);
+        }
+        AddExpression(list, exprContext)
+    )*
+    <RPAREN>
+    {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+/** As ParenthesizedQueryOrCommaList, but allows DEFAULT
+ * in place of any of the expressions. For example,
+ * {@code (x, DEFAULT, null, DEFAULT)}. */
+SqlNodeList ParenthesizedQueryOrCommaListWithDefault(
+    ExprContext exprContext) :
+{
+    SqlNode e;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    ExprContext firstExprContext = exprContext;
+    final Span s;
+}
+{
+    <LPAREN>
+    {
+        // we've now seen left paren, so a query by itself should
+        // be interpreted as a sub-query
+        s = span();
+        switch (exprContext) {
+        case ACCEPT_SUB_QUERY:
+            firstExprContext = ExprContext.ACCEPT_NONCURSOR;
+            break;
+        case ACCEPT_CURSOR:
+            firstExprContext = ExprContext.ACCEPT_ALL;
+            break;
+        }
+    }
+    (
+        e = OrderedQueryOrExpr(firstExprContext) { list.add(e); }
+    |
+        e = Default() { list.add(e); }
+    )
+    (
+        <COMMA>
+        {
+            // a comma-list can't appear where only a query is expected
+            checkNonQueryExpression(exprContext);
+        }
+        (
+            e = Expression(exprContext) { list.add(e); }
+        |
+            e = Default() { list.add(e); }
+        )
+    )*
+    <RPAREN>
+    {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+/**
+ * Parses function parameter lists.
+ * If the list starts with DISTINCT or ALL, it is discarded.
+ */
+List<SqlNode> UnquantifiedFunctionParameterList(ExprContext exprContext) :
+{
+    final List<SqlNode> args;
+}
+{
+    args = FunctionParameterList(exprContext) {
+        args.remove(0); // remove DISTINCT or ALL, if present
+        return args;
+    }
+}
+
+/**
+ * Parses function parameter lists including DISTINCT keyword recognition,
+ * DEFAULT, and named argument assignment.
+ */
+List<SqlNode> FunctionParameterList(ExprContext exprContext) :
+{
+    final SqlLiteral qualifier;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    <LPAREN>
+    (
+        qualifier = AllOrDistinct() { list.add(qualifier); }
+    |
+        { list.add(null); }
+    )
+    AddArg0(list, exprContext)
+    (
+        <COMMA> {
+            // a comma-list can't appear where only a query is expected
+            checkNonQueryExpression(exprContext);
+        }
+        AddArg(list, exprContext)
+    )*
+    <RPAREN>
+    {
+        return list;
+    }
+}
+
+SqlLiteral AllOrDistinct() :
+{
+}
+{
+    <DISTINCT> { return SqlSelectKeyword.DISTINCT.symbol(getPos()); }
+|
+    <ALL> { return SqlSelectKeyword.ALL.symbol(getPos()); }
+}
+
+void AddArg0(List<SqlNode> list, ExprContext exprContext) :
+{
+    final SqlIdentifier name;
+    SqlNode e;
+    final ExprContext firstExprContext;
+    {
+        // we've now seen left paren, so queries inside should
+        // be allowed as sub-queries
+        switch (exprContext) {
+        case ACCEPT_SUB_QUERY:
+            firstExprContext = ExprContext.ACCEPT_NONCURSOR;
+            break;
+        case ACCEPT_CURSOR:
+            firstExprContext = ExprContext.ACCEPT_ALL;
+            break;
+        default:
+            firstExprContext = exprContext;
+            break;
+        }
+    }
+}
+{
+    (
+        LOOKAHEAD(2) name = SimpleIdentifier() <NAMED_ARGUMENT_ASSIGNMENT>
+    |   { name = null; }
+    )
+    (
+        e = Default()
+    |
+        LOOKAHEAD(3)
+        e = TableParam()
+    |
+        e = PartitionedQueryOrQueryOrExpr(firstExprContext)
+    )
+    {
+        if (name != null) {
+            e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
+                Span.of(name, e).pos(), e, name);
+        }
+        list.add(e);
+    }
+}
+
+void AddArg(List<SqlNode> list, ExprContext exprContext) :
+{
+    final SqlIdentifier name;
+    SqlNode e;
+}
+{
+    (
+        LOOKAHEAD(2) name = SimpleIdentifier() <NAMED_ARGUMENT_ASSIGNMENT>
+    |   { name = null; }
+    )
+    (
+        e = Default()
+    |
+        e = Expression(exprContext)
+    |
+        e = TableParam()
+    )
+    {
+        if (name != null) {
+            e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
+                Span.of(name, e).pos(), e, name);
+        }
+        list.add(e);
+    }
+}
+
+SqlNode Default() : {}
+{
+    <DEFAULT_> {
+        return SqlStdOperatorTable.DEFAULT.createCall(getPos());
+    }
+}
+
+/**
+ * Parses a query (SELECT, UNION, INTERSECT, EXCEPT, VALUES, TABLE) followed by
+ * the end-of-file symbol.
+ */
+SqlNode SqlQueryEof() :
+{
+    SqlNode query;
+}
+{
+    query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+    <EOF>
+    { return query; }
+}
+
+/**
+ * Parses a list of SQL statements separated by semicolon.
+ * The semicolon is required between statements, but is
+ * optional at the end.
+ */
+SqlNodeList SqlStmtList() :
+{
+    final List<SqlNode> stmtList = new ArrayList<SqlNode>();
+    SqlNode stmt;
+}
+{
+    stmt = SqlStmt() {
+        stmtList.add(stmt);
+    }
+    (
+        <SEMICOLON>
+        [
+            stmt = SqlStmt() {
+                stmtList.add(stmt);
+            }
+        ]
+    )*
+    <EOF>
+    {
+        return new SqlNodeList(stmtList, Span.of(stmtList).pos());
+    }
+}
+
+/**
+ * Parses an SQL statement.
+ */
+SqlNode SqlStmt() :
+{
+    SqlNode stmt;
+}
+{
+    (
+<#-- Add methods to parse additional statements here -->
+<#list (parser.statementParserMethods!default.parser.statementParserMethods) as method>
+        LOOKAHEAD(2) stmt = ${method}
+    |
+</#list>
+        stmt = SqlSetOption(Span.of(), null)
+    |
+        stmt = SqlAlter()
+    |
+<#if (parser.createStatementParserMethods!default.parser.createStatementParserMethods)?size != 0>
+        stmt = SqlCreate()
+    |
+</#if>
+<#if (parser.dropStatementParserMethods!default.parser.dropStatementParserMethods)?size != 0>
+        stmt = SqlDrop()
+    |
+</#if>
+        stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+    |
+        stmt = SqlExplain()
+    |
+        stmt = SqlDescribe()
+    |
+        stmt = SqlInsert()
+    |
+        stmt = SqlDelete()
+    |
+        stmt = SqlUpdate()
+    |
+        stmt = SqlMerge()
+    |
+        stmt = SqlProcedureCall()
+    )
+    {
+        return stmt;
+    }
+}
+
+/**
+ * Parses an SQL statement followed by the end-of-file symbol.
+ */
+SqlNode SqlStmtEof() :
+{
+    SqlNode stmt;
+}
+{
+    stmt = SqlStmt() <EOF>
+    {
+        return stmt;
+    }
+}
+
+<#-- Add implementations of additional parser statement calls here -->
+<#list (parser.implementationFiles!default.parser.implementationFiles) as file>
+    <#include "/@includes/"+file />
+</#list>
+
+SqlNodeList ParenthesizedKeyValueOptionCommaList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    { s = span(); }
+    <LPAREN>
+    AddKeyValueOption(list)
+    (
+        <COMMA>
+        AddKeyValueOption(list)
+    )*
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+/**
+* Parses an option with format key=val whose key is a simple identifier or string literal
+* and value is a string literal.
+*/
+void AddKeyValueOption(List<SqlNode> list) :
+{
+    final SqlNode key;
+    final SqlNode value;
+}
+{
+    (
+        key = SimpleIdentifier()
+    |
+        key = StringLiteral()
+    )
+    <EQ>
+    value = StringLiteral() {
+        list.add(key);
+        list.add(value);
+    }
+}
+
+/** Parses an option value (either a string or a numeric) and adds to a list. */
+void AddOptionValue(List<SqlNode> list) :
+{
+    final SqlNode value;
+}
+{
+    (
+        value = NumericLiteral() { list.add(value); }
+    |
+        value = StringLiteral() { list.add(value); }
+    )
+}
+
+/**
+ * Parses a literal list separated by comma. The literal is either a string or a numeric.
+ */
+SqlNodeList ParenthesizedLiteralOptionCommaList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    { s = span(); }
+    <LPAREN>
+    AddOptionValue(list) ( <COMMA> AddOptionValue(list) )*
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+void AddHint(List<SqlNode> hints) :
+{
+    final SqlIdentifier hintName;
+    final SqlNodeList hintOptions;
+    final SqlHint.HintOptionFormat optionFormat;
+}
+{
+    hintName = SimpleIdentifier()
+    (
+       LOOKAHEAD(5)
+        hintOptions = ParenthesizedKeyValueOptionCommaList() {
+            optionFormat = SqlHint.HintOptionFormat.KV_LIST;
+        }
+    |
+        LOOKAHEAD(3)
+        hintOptions = ParenthesizedSimpleIdentifierList() {
+            optionFormat = SqlHint.HintOptionFormat.ID_LIST;
+        }
+    |
+        LOOKAHEAD(3)
+        hintOptions = ParenthesizedLiteralOptionCommaList() {
+            optionFormat = SqlHint.HintOptionFormat.LITERAL_LIST;
+        }
+    |
+        LOOKAHEAD(2)
+        [<LPAREN> <RPAREN>]
+        {
+            hintOptions = SqlNodeList.EMPTY;
+            optionFormat = SqlHint.HintOptionFormat.EMPTY;
+        }
+    )
+    {
+        hints.add(
+           new SqlHint(Span.of(hintOptions).end(this), hintName, hintOptions,
+               optionFormat));
+    }
+}
+
+/** Parses hints following a table reference,
+ * and returns the wrapped table reference. */
+SqlNode TableHints(SqlIdentifier tableName) :
+{
+    final List<SqlNode> hints = new ArrayList<SqlNode>();
+}
+{
+    <HINT_BEG> AddHint(hints) ( <COMMA> AddHint(hints) )* <COMMENT_END> {
+        final SqlParserPos pos = Span.of(tableName).addAll(hints).end(this);
+        final SqlNodeList hintList = new SqlNodeList(hints, pos);
+        return new SqlTableRef(pos, tableName, hintList);
+    }
+}
+
+/**
+ * Parses a leaf SELECT expression without ORDER BY.
+ */
+SqlSelect SqlSelect() :
+{
+    final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
+    final SqlLiteral keyword;
+    final SqlNodeList keywordList;
+    final List<SqlNode> selectList = new ArrayList<SqlNode>();
+    final SqlNode fromClause;
+    final SqlNode where;
+    final SqlNodeList groupBy;
+    final SqlNode having;
+    final SqlNodeList windowDecls;
+    final SqlNode qualify;
+    final List<SqlNode> hints = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    <SELECT> { s = span(); }
+    [ <HINT_BEG> AddHint(hints) ( <COMMA> AddHint(hints) )* <COMMENT_END> ]
+    SqlSelectKeywords(keywords)
+    (
+        <STREAM> {
+            keywords.add(SqlSelectKeyword.STREAM.symbol(getPos()));
+        }
+    )?
+    (
+        keyword = AllOrDistinct() { keywords.add(keyword); }
+    )?
+    {
+        keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
+    }
+    AddSelectItem(selectList)
+    ( <COMMA> AddSelectItem(selectList) )*
+    (
+        <FROM> fromClause = FromClause()
+        ( where = Where() | { where = null; } )
+        ( groupBy = GroupBy() | { groupBy = null; } )
+        ( having = Having() | { having = null; } )
+        ( windowDecls = Window() | { windowDecls = null; } )
+        ( qualify = Qualify() | { qualify = null; } )
+    |
+        E() {
+            fromClause = null;
+            where = null;
+            groupBy = null;
+            having = null;
+            windowDecls = null;
+            qualify = null;
+        }
+    )
+    {
+        return new SqlSelect(s.end(this), keywordList,
+            new SqlNodeList(selectList, Span.of(selectList).pos()),
+            fromClause, where, groupBy, having, windowDecls, qualify,
+            null, null, null, new SqlNodeList(hints, getPos()));
+    }
+}
+
+/*
+ * Abstract production:
+ *
+ *    void SqlSelectKeywords(List keywords)
+ *
+ * Parses dialect-specific keywords immediately following the SELECT keyword.
+ */
+
+/**
+ * Parses an EXPLAIN PLAN statement.
+ */
+SqlNode SqlExplain() :
+{
+    SqlNode stmt;
+    SqlExplainLevel detailLevel = SqlExplainLevel.EXPPLAN_ATTRIBUTES;
+    SqlExplain.Depth depth;
+    final SqlExplainFormat format;
+}
+{
+    <EXPLAIN> <PLAN>
+    [ detailLevel = ExplainDetailLevel() ]
+    depth = ExplainDepth()
+    (
+        LOOKAHEAD(2)
+        <AS> <XML> { format = SqlExplainFormat.XML; }
+    |
+        LOOKAHEAD(2)
+        <AS> <JSON> { format = SqlExplainFormat.JSON; }
+    |
+        <AS> <DOT_FORMAT> { format = SqlExplainFormat.DOT; }
+    |
+        { format = SqlExplainFormat.TEXT; }
+    )
+    <FOR> stmt = SqlQueryOrDml() {
+        return new SqlExplain(getPos(),
+            stmt,
+            detailLevel.symbol(SqlParserPos.ZERO),
+            depth.symbol(SqlParserPos.ZERO),
+            format.symbol(SqlParserPos.ZERO),
+            nDynamicParams);
+    }
+}
+
+/** Parses a query (SELECT or VALUES)
+ * or DML statement (INSERT, UPDATE, DELETE, MERGE). */
+SqlNode SqlQueryOrDml() :
+{
+    SqlNode stmt;
+}
+{
+    (
+        stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+    |
+        stmt = SqlInsert()
+    |
+        stmt = SqlDelete()
+    |
+        stmt = SqlUpdate()
+    |
+        stmt = SqlMerge()
+    ) { return stmt; }
+}
+
+/**
+ * Parses WITH TYPE | WITH IMPLEMENTATION | WITHOUT IMPLEMENTATION modifier for
+ * EXPLAIN PLAN.
+ */
+SqlExplain.Depth ExplainDepth() :
+{
+}
+{
+    (
+        LOOKAHEAD(2)
+        <WITH> <TYPE>
+        {
+            return SqlExplain.Depth.TYPE;
+        }
+        |
+        <WITH> <IMPLEMENTATION>
+        {
+            return SqlExplain.Depth.PHYSICAL;
+        }
+        |
+        <WITHOUT> <IMPLEMENTATION>
+        {
+            return SqlExplain.Depth.LOGICAL;
+        }
+        |
+        {
+            return SqlExplain.Depth.PHYSICAL;
+        }
+
+    )
+}
+
+/**
+ * Parses INCLUDING ALL ATTRIBUTES modifier for EXPLAIN PLAN.
+ */
+SqlExplainLevel ExplainDetailLevel() :
+{
+    SqlExplainLevel level = SqlExplainLevel.EXPPLAN_ATTRIBUTES;
+}
+{
+    (
+        <EXCLUDING> <ATTRIBUTES>
+        {
+            level = SqlExplainLevel.NO_ATTRIBUTES;
+        }
+        |
+        <INCLUDING>
+        [ <ALL> { level = SqlExplainLevel.ALL_ATTRIBUTES; } ]
+        <ATTRIBUTES>
+        {
+        }
+    )
+    {
+        return level;
+    }
+}
+
+/**
+ * Parses a DESCRIBE statement.
+ */
+SqlNode SqlDescribe() :
+{
+   final Span s;
+   final SqlIdentifier table;
+   final SqlIdentifier column;
+   final SqlIdentifier id;
+   final SqlNode stmt;
+}
+{
+    <DESCRIBE> { s = span(); }
+    (
+        LOOKAHEAD(2) (<DATABASE> | <CATALOG> | <SCHEMA>)
+        id = CompoundIdentifier() {
+            // DESCRIBE DATABASE and DESCRIBE CATALOG currently do the same as
+            // DESCRIBE SCHEMA but should be different. See
+            //   [CALCITE-1221] Implement DESCRIBE DATABASE, CATALOG, STATEMENT
+            return new SqlDescribeSchema(s.end(id), id);
+        }
+    |
+        // Use syntactic lookahead to determine whether a table name is coming.
+        // We do not allow SimpleIdentifier() because that includes <STATEMENT>.
+        LOOKAHEAD( <TABLE>
+           | <IDENTIFIER>
+           | <HYPHENATED_IDENTIFIER>
+           | <QUOTED_IDENTIFIER>
+           | <BACK_QUOTED_IDENTIFIER>
+           | <BIG_QUERY_BACK_QUOTED_IDENTIFIER>
+           | <BRACKET_QUOTED_IDENTIFIER> )
+        (<TABLE>)?
+        table = CompoundIdentifier()
+        ( column = SimpleIdentifier() | { column = null; } )
+        {
+            return new SqlDescribeTable(s.add(table).addIf(column).pos(),
+                table, column);
+        }
+    |
+        (LOOKAHEAD(1) <STATEMENT>)?
+        stmt = SqlQueryOrDml() {
+            // DESCRIBE STATEMENT currently does the same as EXPLAIN. See
+            //   [CALCITE-1221] Implement DESCRIBE DATABASE, CATALOG, STATEMENT
+            final SqlExplainLevel detailLevel = SqlExplainLevel.EXPPLAN_ATTRIBUTES;
+            final SqlExplain.Depth depth = SqlExplain.Depth.PHYSICAL;
+            final SqlExplainFormat format = SqlExplainFormat.TEXT;
+            return new SqlExplain(s.end(stmt),
+                stmt,
+                detailLevel.symbol(SqlParserPos.ZERO),
+                depth.symbol(SqlParserPos.ZERO),
+                format.symbol(SqlParserPos.ZERO),
+                nDynamicParams);
+        }
+    )
+}
+
+/**
+ * Parses a CALL statement.
+ */
+SqlNode SqlProcedureCall() :
+{
+    final Span s;
+    SqlNode routineCall;
+}
+{
+    <CALL> {
+        s = span();
+    }
+    routineCall = NamedRoutineCall(
+        SqlFunctionCategory.USER_DEFINED_PROCEDURE,
+        ExprContext.ACCEPT_SUB_QUERY)
+    {
+        return SqlStdOperatorTable.PROCEDURE_CALL.createCall(
+            s.end(routineCall), routineCall);
+    }
+}
+
+SqlNode NamedRoutineCall(
+    SqlFunctionCategory routineType,
+    ExprContext exprContext) :
+{
+    final SqlIdentifier name;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    name = CompoundIdentifier() {
+        s = span();
+    }
+    <LPAREN>
+    [
+        AddArg0(list, exprContext)
+        (
+            <COMMA> {
+                // a comma-list can't appear where only a query is expected
+                checkNonQueryExpression(exprContext);
+            }
+            AddArg(list, exprContext)
+        )*
+    ]
+    <RPAREN>
+    {
+        return createCall(name, s.end(this), routineType, null, list);
+    }
+}
+
+/**
+ * Table parameter of a table function.
+ * The input table with set semantics may be partitioned/ordered on one or more columns.
+ */
+SqlNode TableParam() :
+{
+    final Span s;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    SqlNode tableRef;
+}
+{
+    { s = span(); }
+    tableRef = ExplicitTable(getPos())
+    (
+        <PARTITION> <BY>
+        partitionList = SimpleIdentifierOrList()
+    |   { partitionList = SqlNodeList.EMPTY; }
+    )
+    (
+        orderList = OrderByOfSetSemanticsTable()
+     |  { orderList = SqlNodeList.EMPTY; }
+    )
+    { return CreateSetSemanticsTableIfNeeded(s, tableRef, partitionList, orderList); }
+}
+
+SqlNode PartitionedQueryOrQueryOrExpr(ExprContext exprContext) :
+{
+    SqlNode e;
+}
+{
+    e = OrderedQueryOrExpr(exprContext)
+    e = PartitionedByAndOrderBy(e)
+
+    { return e; }
+}
+
+SqlNode PartitionedByAndOrderBy(SqlNode e) :
+{
+    final Span s;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+}
+{
+    { s = span(); }
+    (
+        <PARTITION> <BY>
+        partitionList = SimpleIdentifierOrList()
+    |   { partitionList = SqlNodeList.EMPTY; }
+    )
+    (
+        orderList = OrderByOfSetSemanticsTable()
+     |  { orderList = SqlNodeList.EMPTY; }
+    )
+    { return CreateSetSemanticsTableIfNeeded(s, e, partitionList, orderList); }
+}
+
+SqlNodeList OrderByOfSetSemanticsTable() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+  <ORDER>
+  { s = span(); }
+  <BY>
+  (
+      LOOKAHEAD(2)
+      <LPAREN> AddOrderItem(list)
+      (
+        // NOTE jvs 6-Feb-2004:  See comments at top of file for why
+        // hint is necessary here.
+        LOOKAHEAD(2) <COMMA> AddOrderItem(list)
+      )*
+      <RPAREN> {
+          return new SqlNodeList(list, s.addAll(list).pos());
+      }
+  |
+      AddOrderItem(list)
+      {
+          return new SqlNodeList(list, s.addAll(list).pos());
+      }
+  )
+}
+
+SqlNode CreateSetSemanticsTableIfNeeded(
+    final Span s,
+    final SqlNode e,
+    final SqlNodeList partitionList,
+    final SqlNodeList orderList) :
+{
+
+}
+{
+
+    {
+        if (partitionList.isEmpty() && orderList.isEmpty()) {
+            return e;
+        } else {
+            return SqlStdOperatorTable.SET_SEMANTICS_TABLE.createCall(
+                s.pos(), e, partitionList, orderList);
+        }
+    }
+}
+
+/**
+ * Parses an INSERT statement.
+ */
+SqlNode SqlInsert() :
+{
+    final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
+    final SqlNodeList keywordList;
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    SqlNode source;
+    final SqlNodeList columnList;
+    final Span s;
+    final Pair<SqlNodeList, SqlNodeList> p;
+}
+{
+    (
+        <INSERT>
+    |
+        <UPSERT> { keywords.add(SqlInsertKeyword.UPSERT.symbol(getPos())); }
+    )
+    { s = span(); }
+    SqlInsertKeywords(keywords) {
+        keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
+    }
+    <INTO> tableName = CompoundTableIdentifier()
+    ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+    [ LOOKAHEAD(5) tableRef = ExtendTable(tableRef) ]
+    (
+        LOOKAHEAD(2)
+        p = ParenthesizedCompoundIdentifierList() {
+            if (p.right.size() > 0) {
+                tableRef = extend(tableRef, p.right);
+            }
+            if (p.left.size() > 0) {
+                columnList = p.left;
+            } else {
+                columnList = null;
+            }
+        }
+    |   { columnList = null; }
+    )
+    source = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) {
+        return new SqlInsert(s.end(source), keywordList, tableRef, source,
+            columnList);
+    }
+}
+
+/*
+ * Abstract production:
+ *
+ *    void SqlInsertKeywords(List keywords)
+ *
+ * Parses dialect-specific keywords immediately following the INSERT keyword.
+ */
+
+/**
+ * Parses a DELETE statement.
+ */
+SqlNode SqlDelete() :
+{
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode where;
+    final Span s;
+}
+{
+    <DELETE> {
+        s = span();
+    }
+    <FROM> tableName = CompoundTableIdentifier()
+    ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+    [ tableRef = ExtendTable(tableRef) ]
+    ( [ <AS> ] alias = SimpleIdentifier() | { alias = null; } )
+    ( where = Where() | { where = null; } )
+    {
+        return new SqlDelete(s.add(tableRef).addIf(alias).addIf(where).pos(),
+            tableRef, where, null, alias);
+    }
+}
+
+/**
+ * Parses an UPDATE statement.
+ */
+SqlNode SqlUpdate() :
+{
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode where;
+    final SqlNodeList sourceExpressionList;
+    final SqlNodeList targetColumnList;
+    SqlIdentifier id;
+    final Span s;
+}
+{
+    <UPDATE> {
+        s = span();
+        targetColumnList = new SqlNodeList(s.pos());
+        sourceExpressionList = new SqlNodeList(s.pos());
+    }
+    tableName = CompoundTableIdentifier()
+    ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+    [ tableRef = ExtendTable(tableRef) ]
+    ( [ <AS> ] alias = SimpleIdentifier() | { alias = null; } )
+    <SET> id = SimpleIdentifier() {
+        targetColumnList.add(id);
+    }
+    // TODO:  support DEFAULT also
+    <EQ> AddExpression(sourceExpressionList, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <COMMA>
+        id = SimpleIdentifier() { targetColumnList.add(id); }
+        <EQ> AddExpression(sourceExpressionList, ExprContext.ACCEPT_SUB_QUERY)
+    )*
+    ( where = Where() | { where = null; } )
+    {
+        final SqlParserPos pos = s.addAll(targetColumnList)
+            .addAll(sourceExpressionList).addIf(where).pos();
+        return new SqlUpdate(pos, tableRef, targetColumnList,
+            sourceExpressionList, where, null, alias);
+    }
+}
+
+/**
+ * Parses a MERGE statement.
+ */
+SqlNode SqlMerge() :
+{
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode sourceTableRef;
+    final SqlNode condition;
+    final SqlUpdate updateCall;
+    final SqlInsert insertCall;
+    final Span s;
+}
+{
+    <MERGE> { s = span(); } <INTO> tableName = CompoundTableIdentifier()
+    ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+    [ tableRef = ExtendTable(tableRef) ]
+    ( [ <AS> ] alias = SimpleIdentifier() | { alias = null; } )
+    <USING> sourceTableRef = TableRef()
+    <ON> condition = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    (
+        LOOKAHEAD(2)
+        updateCall = WhenMatchedClause(tableRef, alias)
+        ( insertCall = WhenNotMatchedClause(tableRef) | { insertCall = null; } )
+    |
+        { updateCall = null; }
+        insertCall = WhenNotMatchedClause(tableRef)
+    )
+    {
+        final SqlParserPos pos = s.addIf(updateCall).addIf(insertCall).pos();
+        return new SqlMerge(pos, tableRef, condition, sourceTableRef,
+            updateCall, insertCall, null, alias);
+    }
+}
+
+SqlUpdate WhenMatchedClause(SqlNode table, SqlIdentifier alias) :
+{
+    SqlIdentifier id;
+    final Span s;
+    final SqlNodeList updateColumnList = new SqlNodeList(SqlParserPos.ZERO);
+    final SqlNodeList updateExprList = new SqlNodeList(SqlParserPos.ZERO);
+}
+{
+    <WHEN> { s = span(); } <MATCHED> <THEN>
+    <UPDATE> <SET> id = CompoundIdentifier() {
+        updateColumnList.add(id);
+    }
+    <EQ> AddExpression(updateExprList, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <COMMA>
+        id = CompoundIdentifier() {
+            updateColumnList.add(id);
+        }
+        <EQ> AddExpression(updateExprList, ExprContext.ACCEPT_SUB_QUERY)
+    )*
+    {
+        return new SqlUpdate(s.addAll(updateExprList).pos(), table,
+            updateColumnList, updateExprList, null, null, alias);
+    }
+}
+
+SqlInsert WhenNotMatchedClause(SqlNode table) :
+{
+    final Span insertSpan, valuesSpan;
+    final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
+    final SqlNodeList keywordList;
+    final SqlNodeList insertColumnList;
+    SqlNode rowConstructor;
+    SqlNode insertValues;
+}
+{
+    <WHEN> <NOT> <MATCHED> <THEN> <INSERT> {
+        insertSpan = span();
+    }
+    SqlInsertKeywords(keywords) {
+        keywordList = new SqlNodeList(keywords, insertSpan.end(this));
+    }
+    (
+        LOOKAHEAD(2)
+        insertColumnList = ParenthesizedSimpleIdentifierList()
+    |   { insertColumnList = null; }
+    )
+    (
+        <LPAREN>
+        <VALUES> { valuesSpan = span(); } rowConstructor = RowConstructor()
+        <RPAREN>
+    |
+        <VALUES> { valuesSpan = span(); } rowConstructor = RowConstructor()
+    )
+    {
+        // TODO zfong 5/26/06: note that extra parentheses are accepted above
+        // around the VALUES clause as a hack for unparse, but this is
+        // actually invalid SQL; should fix unparse
+        insertValues = SqlStdOperatorTable.VALUES.createCall(
+            valuesSpan.end(this), rowConstructor);
+        return new SqlInsert(insertSpan.end(this), keywordList,
+            table, insertValues, insertColumnList);
+    }
+}
+
+/**
+ * Parses one item in a select list.
+ */
+void AddSelectItem(List<SqlNode> list) :
+{
+    final SqlNode e;
+    final SqlIdentifier id;
+}
+{
+    e = SelectExpression()
+    (
+        [ <AS> ]
+        (
+            id = SimpleIdentifier()
+        |
+            // Mute the warning about ambiguity between alias and continued
+            // string literal.
+            LOOKAHEAD(1)
+            id = SimpleIdentifierFromStringLiteral()
+        )
+        { list.add(SqlStdOperatorTable.AS.createCall(span().end(e), e, id)); }
+    |   { list.add(e); }
+    )
+}
+
+/**
+ * Parses one unaliased expression in a select list.
+ */
+SqlNode SelectExpression() :
+{
+    SqlNode e;
+}
+{
+    <STAR> {
+        return SqlIdentifier.star(getPos());
+    }
+|
+    e = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+        return e;
+    }
+}
+
+SqlLiteral Natural() :
+{
+}
+{
+    <NATURAL> { return SqlLiteral.createBoolean(true, getPos()); }
+|
+    { return SqlLiteral.createBoolean(false, getPos()); }
+}
+
+SqlLiteral JoinType() :
+{
+    JoinType joinType;
+}
+{
+    (
+    LOOKAHEAD(3) // required for "LEFT SEMI JOIN" in Babel
+<#list (parser.joinTypes!default.parser.joinTypes) as method>
+        joinType = ${method}()
+    |
+</#list>
+        <JOIN> { joinType = JoinType.INNER; }
+    |
+        <INNER> <JOIN> { joinType = JoinType.INNER; }
+    |
+        <LEFT> [ <OUTER> ] <JOIN> { joinType = JoinType.LEFT; }
+    |
+        <RIGHT> [ <OUTER> ] <JOIN> { joinType = JoinType.RIGHT; }
+    |
+        <FULL> [ <OUTER> ] <JOIN> { joinType = JoinType.FULL; }
+    |
+        <CROSS> <JOIN> { joinType = JoinType.CROSS; }
+    )
+    {
+        return joinType.symbol(getPos());
+    }
+}
+
+/**
+ * Parses the FROM clause for a SELECT.
+ *
+ * <p>FROM is mandatory in standard SQL, optional in dialects such as MySQL,
+ * PostgreSQL. The parser allows SELECT without FROM, but the validator fails
+ * if conformance is, say, STRICT_2003.
+ */
+SqlNode FromClause() :
+{
+    SqlNode e, e2;
+    SqlLiteral joinType;
+}
+{
+    e = Join()
+    (
+        // Comma joins should only occur at top-level in the FROM clause.
+        // Valid:
+        //  * FROM a, b
+        //  * FROM (a CROSS JOIN b), c
+        // Not valid:
+        //  * FROM a CROSS JOIN (b, c)
+        LOOKAHEAD(1)
+        <COMMA> { joinType = JoinType.COMMA.symbol(getPos()); }
+        e2 = Join() {
+            e = new SqlJoin(joinType.getParserPosition(),
+                e,
+                SqlLiteral.createBoolean(false, joinType.getParserPosition()),
+                joinType,
+                e2,
+                JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
+                null);
+        }
+    )*
+    { return e; }
+}
+
+SqlNode Join() :
+{
+    SqlNode e;
+}
+{
+    e = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN)
+    (
+        LOOKAHEAD(2)
+        e = JoinTable(e)
+    )*
+    {
+        return e;
+    }
+}
+
+/** Matches "LEFT JOIN t ON ...", "RIGHT JOIN t USING ...", "JOIN t". */
+SqlNode JoinTable(SqlNode e) :
+{
+    SqlNode e2, condition;
+    final SqlLiteral natural, joinType, on, using;
+    SqlNodeList list;
+}
+{
+    // LOOKAHEAD(3) is needed here rather than a LOOKAHEAD(2) because JavaCC
+    // calculates minimum lookahead count incorrectly for choice that contains
+    // zero size child. For instance, with the generated code,
+    // "LOOKAHEAD(2, Natural(), JoinType())"
+    // returns true immediately if it sees a single "<CROSS>" token. Where we
+    // expect the lookahead succeeds after "<CROSS> <APPLY>".
+    //
+    // For more information about the issue,
+    // see https://github.com/javacc/javacc/issues/86
+    //
+    // We allow CROSS JOIN (joinType = CROSS_JOIN) to have a join condition,
+    // even though that is not valid SQL; the validator will catch it.
+    LOOKAHEAD(3)
+    natural = Natural()
+    joinType = JoinType()
+    e2 = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN)
+    (
+        <ON> { on = JoinConditionType.ON.symbol(getPos()); }
+        condition = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+            return new SqlJoin(joinType.getParserPosition(),
+                e,
+                natural,
+                joinType,
+                e2,
+                on,
+                condition);
+        }
+    |
+        <USING> { using = JoinConditionType.USING.symbol(getPos()); }
+        list = ParenthesizedSimpleIdentifierList() {
+            return new SqlJoin(joinType.getParserPosition(),
+                e,
+                natural,
+                joinType,
+                e2,
+                using,
+                new SqlNodeList(list, Span.of(using).end(this)));
+        }
+    |
+        {
+            return new SqlJoin(joinType.getParserPosition(),
+                e,
+                natural,
+                joinType,
+                e2,
+                JoinConditionType.NONE.symbol(joinType.getParserPosition()),
+                null);
+        }
+    )
+|
+    <CROSS> { joinType = JoinType.CROSS.symbol(getPos()); } <APPLY>
+    e2 = TableRef2(true) {
+        if (!this.conformance.isApplyAllowed()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());
+        }
+        return new SqlJoin(joinType.getParserPosition(),
+            e,
+            SqlLiteral.createBoolean(false, joinType.getParserPosition()),
+            joinType,
+            e2,
+            JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
+            null);
+    }
+|
+    <OUTER> { joinType = JoinType.LEFT.symbol(getPos()); } <APPLY>
+    e2 = TableRef2(true) {
+        if (!this.conformance.isApplyAllowed()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());
+        }
+        return new SqlJoin(joinType.getParserPosition(),
+            e,
+            SqlLiteral.createBoolean(false, joinType.getParserPosition()),
+            joinType,
+            e2,
+            JoinConditionType.ON.symbol(SqlParserPos.ZERO),
+            SqlLiteral.createBoolean(true, joinType.getParserPosition()));
+    }
+}
+
+/**
+ * Parses a table reference in a FROM clause, not lateral unless LATERAL
+ * is explicitly specified.
+ */
+SqlNode TableRef() :
+{
+    final SqlNode e;
+}
+{
+    e = TableRef3(ExprContext.ACCEPT_QUERY, false) { return e; }
+}
+
+SqlNode TableRef1(ExprContext exprContext) :
+{
+    final SqlNode e;
+}
+{
+    e = TableRef3(exprContext, false) { return e; }
+}
+
+/**
+ * Parses a table reference in a FROM clause.
+ */
+SqlNode TableRef2(boolean lateral) :
+{
+    final SqlNode e;
+}
+{
+    e = TableRef3(ExprContext.ACCEPT_QUERY, lateral) { return e; }
+}
+
+SqlNode TableRef3(ExprContext exprContext, boolean lateral) :
+{
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final Span s;
+    SqlNodeList args;
+    final SqlNodeList columnAliasList;
+    SqlUnnestOperator unnestOp = SqlStdOperatorTable.UNNEST;
+}
+{
+    (
+        LOOKAHEAD(2)
+        tableName = CompoundTableIdentifier()
+        ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+        [ tableRef = ExtendTable(tableRef) ]
+        tableRef = Over(tableRef)
+        [ tableRef = Snapshot(tableRef) ]
+        [ tableRef = MatchRecognize(tableRef) ]
+    |
+        LOOKAHEAD(2)
+        [ <LATERAL> { lateral = true; } ]
+        tableRef = ParenthesizedExpression(exprContext)
+        tableRef = Over(tableRef)
+        tableRef = addLateral(tableRef, lateral)
+        [ tableRef = MatchRecognize(tableRef) ]
+    |
+        <UNNEST> { s = span(); }
+        args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUB_QUERY)
+        [
+            <WITH> <ORDINALITY> {
+                unnestOp = SqlStdOperatorTable.UNNEST_WITH_ORDINALITY;
+            }
+        ]
+        {
+            tableRef = unnestOp.createCall(s.end(this), (List<SqlNode>) args);
+        }
+    |
+        [ <LATERAL> { lateral = true; } ]
+        tableRef = TableFunctionCall()
+        tableRef = addLateral(tableRef, lateral)
+    |
+        tableRef = ExtendedTableRef()
+    )
+    [
+        LOOKAHEAD(2)
+        tableRef = Pivot(tableRef)
+    ]
+    [
+        LOOKAHEAD(2)
+        tableRef = Unpivot(tableRef)
+    ]
+    [
+        [ <AS> ] alias = SimpleIdentifier()
+        (
+            columnAliasList = ParenthesizedSimpleIdentifierList()
+        |   { columnAliasList = null; }
+        )
+        {
+            // Standard SQL (and Postgres) allow applying "AS alias" to a JOIN,
+            // e.g. "FROM (a CROSS JOIN b) AS c". The new alias obscures the
+            // internal aliases, and columns cannot be referenced if they are
+            // not unique. TODO: Support this behavior; see
+            // [CALCITE-5168] Allow AS after parenthesized JOIN
+            checkNotJoin(tableRef);
+            if (columnAliasList == null) {
+                tableRef = SqlStdOperatorTable.AS.createCall(
+                    Span.of(tableRef).end(this), tableRef, alias);
+            } else {
+                List<SqlNode> idList = new ArrayList<SqlNode>();
+                idList.add(tableRef);
+                idList.add(alias);
+                idList.addAll(columnAliasList.getList());
+                tableRef = SqlStdOperatorTable.AS.createCall(
+                    Span.of(tableRef).end(this), idList);
+            }
+        }
+    ]
+    [ tableRef = Tablesample(tableRef) ]
+    { return tableRef; }
+}
+
+SqlNode Tablesample(SqlNode tableRef) :
+{
+    final Span s;
+    final SqlNode sample;
+    final boolean isBernoulli;
+    final SqlNumericLiteral samplePercentage;
+    boolean isRepeatable = false;
+    int repeatableSeed = 0;
+}
+{
+    <TABLESAMPLE> { s = span(); checkNotJoin(tableRef); }
+    (
+        <SUBSTITUTE> <LPAREN> sample = StringLiteral() <RPAREN>
+        {
+            String sampleName =
+                SqlLiteral.unchain(sample).getValueAs(String.class);
+            SqlSampleSpec sampleSpec = SqlSampleSpec.createNamed(sampleName);
+            final SqlLiteral sampleLiteral =
+                SqlLiteral.createSample(sampleSpec, s.end(this));
+            tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
+                s.add(tableRef).end(this), tableRef, sampleLiteral);
+        }
+    |
+        (
+            <BERNOULLI> { isBernoulli = true; }
+        |
+            <SYSTEM> { isBernoulli = false; }
+        )
+        <LPAREN> samplePercentage = UnsignedNumericLiteral() <RPAREN>
+        [
+            <REPEATABLE> <LPAREN> repeatableSeed = IntLiteral() <RPAREN>
+            {
+                isRepeatable = true;
+            }
+        ]
+        {
+            final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100L);
+            BigDecimal rate = samplePercentage.bigDecimalValue();
+            if (rate.compareTo(BigDecimal.ZERO) < 0
+                || rate.compareTo(ONE_HUNDRED) > 0)
+            {
+                throw SqlUtil.newContextException(getPos(), RESOURCE.invalidSampleSize());
+            }
+
+            // Treat TABLESAMPLE(0) and TABLESAMPLE(100) as no table
+            // sampling at all.  Not strictly correct: TABLESAMPLE(0)
+            // should produce no output, but it simplifies implementation
+            // to know that some amount of sampling will occur.
+            // In practice values less than ~1E-43% are treated as 0.0 and
+            // values greater than ~99.999997% are treated as 1.0
+            float fRate = rate.divide(ONE_HUNDRED).floatValue();
+            if (fRate > 0.0f && fRate < 1.0f) {
+                SqlSampleSpec tableSampleSpec =
+                    isRepeatable
+                        ? SqlSampleSpec.createTableSample(
+                            isBernoulli, fRate, repeatableSeed)
+                        : SqlSampleSpec.createTableSample(isBernoulli, fRate);
+
+                SqlLiteral tableSampleLiteral =
+                    SqlLiteral.createSample(tableSampleSpec, s.end(this));
+                tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
+                    s.end(this), tableRef, tableSampleLiteral);
+            }
+        }
+    )
+    { return tableRef; }
+}
+
+/** Wraps a table reference in a call to EXTEND if an optional "EXTEND" clause
+ * is present. */
+SqlNode ExtendTable(SqlNode tableRef) :
+{
+    final SqlNodeList extendList;
+}
+{
+    [ <EXTEND> ]
+    extendList = ExtendList() {
+        return extend(tableRef, extendList);
+    }
+}
+
+SqlNodeList ExtendList() :
+{
+    final Span s;
+    List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    <LPAREN> { s = span(); }
+    AddColumnType(list)
+    (
+        <COMMA> AddColumnType(list)
+    )*
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+void AddColumnType(List<SqlNode> list) :
+{
+    final SqlIdentifier name;
+    final SqlDataTypeSpec type;
+    final boolean nullable;
+}
+{
+    name = CompoundIdentifier()
+    type = DataType()
+    nullable = NotNullOpt()
+    {
+        list.add(name);
+        list.add(type.withNullable(nullable, getPos()));
+    }
+}
+
+/**
+ * Parses a compound identifier with optional type.
+ */
+void AddCompoundIdentifierType(List<SqlNode> list, List<SqlNode> extendList) :
+{
+    final SqlIdentifier name;
+    final SqlDataTypeSpec type;
+    final boolean nullable;
+}
+{
+    name = CompoundIdentifier()
+    (
+        type = DataType()
+        nullable = NotNullOpt()
+    |
+        { type = null; nullable = true; }
+    )
+    {
+        if (type != null) {
+            if (!this.conformance.allowExtend()) {
+                throw SqlUtil.newContextException(type.getParserPosition(),
+                    RESOURCE.extendNotAllowed());
+            }
+            extendList.add(name);
+            extendList.add(type.withNullable(nullable, getPos()));
+        }
+        list.add(name);
+    }
+}
+
+SqlNode TableFunctionCall() :
+{
+    final Span s;
+    final SqlNode call;
+    SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION;
+}
+{
+    <TABLE> { s = span(); } <LPAREN>
+    [
+        <SPECIFIC>
+        {
+            funcType = SqlFunctionCategory.USER_DEFINED_TABLE_SPECIFIC_FUNCTION;
+        }
+    ]
+    call = NamedRoutineCall(funcType, ExprContext.ACCEPT_CURSOR)
+    <RPAREN>
+    {
+        return SqlStdOperatorTable.COLLECTION_TABLE.createCall(s.end(this), call);
+    }
+}
+
+/**
+ * Abstract production:
+ *    SqlNode ExtendedTableRef()
+ *
+ * <p>Allows parser to be extended with new types of table references.  The
+ * default implementation of this production is empty.
+ */
+
+/*
+ * Abstract production:
+ *
+ *    SqlNode TableOverOpt()
+ *
+ * Allows an OVER clause following a table expression as an extension to
+ * standard SQL syntax. The default implementation of this production is empty.
+ */
+
+/**
+ * Parses an explicit TABLE t reference.
+ */
+SqlNode ExplicitTable(SqlParserPos pos) :
+{
+    SqlNode tableRef;
+}
+{
+    <TABLE> tableRef = CompoundIdentifier()
+    {
+        return SqlStdOperatorTable.EXPLICIT_TABLE.createCall(pos, tableRef);
+    }
+}
+
+/**
+ * Parses a VALUES leaf query expression.
+ */
+SqlNode TableConstructor() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    (
+        <VALUES> { s = span(); }
+    |
+        <VALUE>
+        {
+            s = span();
+            if (!this.conformance.isValueAllowed()) {
+                throw SqlUtil.newContextException(getPos(), RESOURCE.valueNotAllowed());
+            }
+        }
+    )
+    AddRowConstructor(list)
+    (
+        LOOKAHEAD(2)
+        <COMMA> AddRowConstructor(list)
+    )*
+    {
+        return SqlStdOperatorTable.VALUES.createCall(s.end(this), list);
+    }
+}
+
+/** Parses a row constructor and adds it to a list. */
+void AddRowConstructor(List<SqlNode> list) :
+{
+    SqlNode e;
+}
+{
+    e = RowConstructor() { list.add(e); }
+}
+
+/**
+ * Parses a row constructor in the context of a VALUES expression.
+ */
+SqlNode RowConstructor() :
+{
+    final SqlNodeList valueList;
+    final SqlNode value;
+    final Span s;
+}
+{
+    // hints are necessary here due to common LPAREN prefixes
+    (
+        // TODO jvs 8-Feb-2004: extra parentheses are accepted here as a hack
+        // for unparse, but this is actually invalid SQL; should
+        // fix unparse
+        LOOKAHEAD(3)
+        <LPAREN> { s = span(); }
+        <ROW>
+        valueList = ParenthesizedQueryOrCommaListWithDefault(ExprContext.ACCEPT_NONCURSOR)
+        <RPAREN> { s.add(this); }
+    |
+        LOOKAHEAD(3)
+        (
+            <ROW> { s = span(); }
+        |
+            { s = Span.of(); }
+        )
+        valueList = ParenthesizedQueryOrCommaListWithDefault(ExprContext.ACCEPT_NONCURSOR)
+    |
+        value = Expression(ExprContext.ACCEPT_NONCURSOR)
+        {
+            // NOTE: A bare value here is standard SQL syntax, believe it or
+            // not.  Taken together with multi-row table constructors, it leads
+            // to very easy mistakes if you forget the parentheses on a
+            // single-row constructor.  This is also the reason for the
+            // LOOKAHEAD in TableConstructor().  It would be so much more
+            // reasonable to require parentheses.  Sigh.
+            s = Span.of(value);
+            valueList = new SqlNodeList(ImmutableList.of(value),
+                value.getParserPosition());
+        }
+    )
+    {
+        // REVIEW jvs 8-Feb-2004: Should we discriminate between scalar
+        // sub-queries inside of ROW and row sub-queries?  The standard does,
+        // but the distinction seems to be purely syntactic.
+        return SqlStdOperatorTable.ROW.createCall(s.end(valueList),
+            (List<SqlNode>) valueList);
+    }
+}
+
+/** Parses a WHERE clause for SELECT, DELETE, and UPDATE. */
+SqlNode Where() :
+{
+    SqlNode condition;
+}
+{
+    <WHERE> condition = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+        return condition;
+    }
+}
+
+/** Parses a GROUP BY clause for SELECT. */
+SqlNodeList GroupBy() :
+{
+    final List<SqlNode> list;
+    final boolean distinct;
+    final Span s;
+}
+{
+    <GROUP> { s = span(); }
+    <BY>
+    (
+        <DISTINCT> { distinct = true; }
+    |   <ALL> { distinct = false; }
+    |   { distinct = false; }
+    )
+    list = GroupingElementList() {
+        final SqlParserPos pos = s.end(this);
+        final List<SqlNode> list2 = distinct
+            ? ImmutableList.of(
+                SqlInternalOperators.GROUP_BY_DISTINCT.createCall(pos, list))
+            : list;
+        return new SqlNodeList(list2, pos);
+    }
+}
+
+List<SqlNode> GroupingElementList() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    AddGroupingElement(list)
+    ( LOOKAHEAD(2) <COMMA> AddGroupingElement(list) )*
+    { return list; }
+}
+
+void AddGroupingElement(List<SqlNode> list) :
+{
+    final List<SqlNode> subList;
+    final SqlNodeList nodes;
+    final Span s;
+}
+{
+    LOOKAHEAD(2)
+    <GROUPING> { s = span(); }
+    <SETS> <LPAREN> subList = GroupingElementList() <RPAREN> {
+        list.add(
+            SqlStdOperatorTable.GROUPING_SETS.createCall(s.end(this), subList));
+    }
+|   <ROLLUP> { s = span(); }
+    <LPAREN> nodes = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        list.add(
+            SqlStdOperatorTable.ROLLUP.createCall(s.end(this), nodes.getList()));
+    }
+|   <CUBE> { s = span(); }
+    <LPAREN> nodes = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        list.add(
+            SqlStdOperatorTable.CUBE.createCall(s.end(this), nodes.getList()));
+    }
+|   LOOKAHEAD(3)
+    <LPAREN> { s = span(); } <RPAREN> {
+        list.add(new SqlNodeList(s.end(this)));
+    }
+|   AddExpression(list, ExprContext.ACCEPT_SUB_QUERY)
+}
+
+/**
+ * Parses a list of expressions separated by commas.
+ */
+SqlNodeList ExpressionCommaList(
+    final Span s,
+    ExprContext exprContext) :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    AddExpressions(list, exprContext) {
+        return new SqlNodeList(list, s.addAll(list).pos());
+    }
+}
+
+/**
+ * Parses a list of expressions separated by commas,
+ * appending expressions to a given list.
+ */
+void AddExpressions(List<SqlNode> list, ExprContext exprContext) :
+{
+}
+{
+    AddExpression(list, exprContext)
+    (
+        // NOTE jvs 6-Feb-2004:  See comments at top of file for why
+        // hint is necessary here.
+        LOOKAHEAD(2)
+        <COMMA> AddExpression(list, ExprContext.ACCEPT_SUB_QUERY)
+    )*
+}
+
+/** Parses a HAVING clause for SELECT. */
+SqlNode Having() :
+{
+    SqlNode e;
+}
+{
+    <HAVING> e = Expression(ExprContext.ACCEPT_SUB_QUERY) { return e; }
+}
+
+/** Parses a WINDOW clause for SELECT. */
+SqlNodeList Window() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    <WINDOW> { s = span(); }
+    AddWindowSpec(list)
+    (
+        LOOKAHEAD(2)
+        <COMMA> AddWindowSpec(list)
+    )*
+    {
+        return new SqlNodeList(list, s.addAll(list).pos());
+    }
+}
+
+void AddWindowSpec(List<SqlNode> list) :
+{
+    final SqlIdentifier id;
+    final SqlWindow e;
+}
+{
+    id = SimpleIdentifier() <AS> e = WindowSpecification() {
+        e.setDeclName(id);
+        list.add(e);
+    }
+}
+
+/**
+ * Parses a window specification.
+ */
+SqlWindow WindowSpecification() :
+{
+    final SqlIdentifier id;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    final SqlLiteral isRows;
+    final SqlNode lowerBound, upperBound;
+    final Span s, s1, s2;
+    final SqlLiteral allowPartial;
+}
+{
+    <LPAREN> { s = span(); }
+    (
+        id = SimpleIdentifier()
+    |   { id = null; }
+    )
+    (
+        <PARTITION> { s1 = span(); }
+        <BY>
+        partitionList = ExpressionCommaList(s1, ExprContext.ACCEPT_NON_QUERY)
+    |   { partitionList = SqlNodeList.EMPTY; }
+    )
+    (
+        orderList = OrderBy(true)
+    |   { orderList = SqlNodeList.EMPTY; }
+    )
+    (
+        (
+            <ROWS> { isRows = SqlLiteral.createBoolean(true, getPos()); }
+        |
+            <RANGE> { isRows = SqlLiteral.createBoolean(false, getPos()); }
+        )
+        (
+            <BETWEEN> lowerBound = WindowRange()
+            <AND> upperBound = WindowRange()
+        |
+            lowerBound = WindowRange()
+            { upperBound = null; }
+        )
+    |
+        {
+            isRows = SqlLiteral.createBoolean(false, SqlParserPos.ZERO);
+            lowerBound = upperBound = null;
+        }
+    )
+    (
+        <ALLOW> { s2 = span(); } <PARTIAL> {
+            allowPartial = SqlLiteral.createBoolean(true, s2.end(this));
+        }
+    |
+        <DISALLOW> { s2 = span(); } <PARTIAL> {
+            allowPartial = SqlLiteral.createBoolean(false, s2.end(this));
+        }
+    |   { allowPartial = null; }
+    )
+    <RPAREN>
+    {
+        return SqlWindow.create(null, id, partitionList, orderList,
+            isRows, lowerBound, upperBound, allowPartial, s.end(this));
+    }
+}
+
+SqlNode WindowRange() :
+{
+    final SqlNode e;
+    final Span s;
+}
+{
+    LOOKAHEAD(2)
+    <CURRENT> { s = span(); } <ROW> {
+        return SqlWindow.createCurrentRow(s.end(this));
+    }
+|
+    LOOKAHEAD(2)
+    <UNBOUNDED> { s = span(); }
+    (
+        <PRECEDING> {
+            return SqlWindow.createUnboundedPreceding(s.end(this));
+        }
+    |
+        <FOLLOWING> {
+            return SqlWindow.createUnboundedFollowing(s.end(this));
+        }
+    )
+|
+    e = Expression(ExprContext.ACCEPT_NON_QUERY)
+    (
+        <PRECEDING> {
+            return SqlWindow.createPreceding(e, getPos());
+        }
+    |
+        <FOLLOWING> {
+            return SqlWindow.createFollowing(e, getPos());
+        }
+    )
+}
+
+/** Parses a QUALIFY clause for SELECT. */
+SqlNode Qualify() :
+{
+    SqlNode e;
+}
+{
+    <QUALIFY> e = Expression(ExprContext.ACCEPT_SUB_QUERY) { return e; }
+}
+
+/**
+ * Parses an ORDER BY clause.
+ */
+SqlNodeList OrderBy(boolean accept) :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    <ORDER> {
+        s = span();
+        if (!accept) {
+            // Someone told us ORDER BY wasn't allowed here.  So why
+            // did they bother calling us?  To get the correct
+            // parser position for error reporting.
+            throw SqlUtil.newContextException(s.pos(), RESOURCE.illegalOrderBy());
+        }
+    }
+    <BY> AddOrderItem(list)
+    (
+        // NOTE jvs 6-Feb-2004:  See comments at top of file for why
+        // hint is necessary here.
+        LOOKAHEAD(2) <COMMA> AddOrderItem(list)
+    )*
+    {
+        return new SqlNodeList(list, s.addAll(list).pos());
+    }
+}
+
+/**
+ * Parses one item in an ORDER BY clause, and adds it to a list.
+ */
+void AddOrderItem(List<SqlNode> list) :
+{
+    SqlNode e;
+}
+{
+    e = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <ASC>
+    |   <DESC> {
+            e = SqlStdOperatorTable.DESC.createCall(getPos(), e);
+        }
+    )?
+    (
+        LOOKAHEAD(2)
+        <NULLS> <FIRST> {
+            e = SqlStdOperatorTable.NULLS_FIRST.createCall(getPos(), e);
+        }
+    |
+        <NULLS> <LAST> {
+            e = SqlStdOperatorTable.NULLS_LAST.createCall(getPos(), e);
+        }
+    )?
+    {
+        list.add(e);
+    }
+}
+
+/** Wraps a table reference in a call to OVER if an optional "OVER" clause
+ * is present (if the dialect supports OVER for table expressions). */
+SqlNode Over(SqlNode tableRef) :
+{
+    final SqlNode over;
+}
+{
+    over = TableOverOpt() {
+        if (over != null) {
+            return SqlStdOperatorTable.OVER.createCall(
+                getPos(), checkNotJoin(tableRef), over);
+        } else {
+            return tableRef;
+        }
+    }
+}
+
+/** Wraps a table reference in a call to LATERAL if {@code lateral} is true. */
+JAVACODE SqlNode addLateral(SqlNode tableRef, boolean lateral) {
+    return lateral
+        ? SqlStdOperatorTable.LATERAL.createCall(getPos(),
+            checkNotJoin(tableRef))
+        : tableRef;
+}
+
+/**
+ * Parses a FOR SYSTEM_TIME clause following a table expression.
+ */
+SqlSnapshot Snapshot(SqlNode tableRef) :
+{
+    final Span s;
+    final SqlNode e;
+}
+{
+    { s = span(); } <FOR> <SYSTEM_TIME> <AS> <OF>
+    // Syntax for temporal table in
+    // standard SQL 2011 IWD 9075-2:201?(E) 7.6 <table reference>
+    // supports grammar as following:
+    // 1. datetime literal
+    // 2. datetime value function, i.e. CURRENT_TIMESTAMP
+    // 3. datetime term in 1 or 2 +(or -) interval term
+
+    // We extend to support column reference, use Expression
+    // to simplify the parsing code.
+    e = Expression(ExprContext.ACCEPT_NON_QUERY) {
+        return new SqlSnapshot(s.end(this), tableRef, e);
+    }
+}
+
+/** Parses a PIVOT clause following a table expression. */
+SqlNode Pivot(SqlNode tableRef) :
+{
+    final Span s;
+    final Span s2;
+    final List<SqlNode> aggList = new ArrayList<SqlNode>();
+    final List<SqlNode> valueList = new ArrayList<SqlNode>();
+    final SqlNodeList axisList;
+    final SqlNodeList inList;
+}
+{
+    <PIVOT> { s = span(); checkNotJoin(tableRef); }
+    <LPAREN>
+    AddPivotAgg(aggList) ( <COMMA> AddPivotAgg(aggList) )*
+    <FOR> axisList = SimpleIdentifierOrList()
+    <IN> <LPAREN> { s2 = span(); }
+    [ AddPivotValue(valueList) ( <COMMA> AddPivotValue(valueList) )* ]
+    <RPAREN> {
+        inList = new SqlNodeList(valueList, s2.end(this));
+    }
+    <RPAREN>
+    {
+        return new SqlPivot(s.end(this), tableRef,
+            new SqlNodeList(aggList, SqlParserPos.sum(aggList)),
+            axisList, inList);
+    }
+}
+
+void AddPivotAgg(List<SqlNode> list) :
+{
+    final SqlNode e;
+    final SqlIdentifier alias;
+}
+{
+    e = NamedFunctionCall()
+    (
+        // Because babel put FOR into non-reserved keyword set.
+        LOOKAHEAD({getToken(1).kind != COMMA && getToken(1).kind != FOR})
+        [ <AS> ] alias = SimpleIdentifier() {
+            list.add(
+                SqlStdOperatorTable.AS.createCall(Span.of(e).end(this), e,
+                    alias));
+        }
+    |
+        { list.add(e); }
+    )
+}
+
+void AddPivotValue(List<SqlNode> list) :
+{
+    final SqlNode e;
+    final SqlNodeList tuple;
+    final SqlIdentifier alias;
+}
+{
+    e = RowConstructor() { tuple = SqlParserUtil.stripRow(e); }
+    (
+        [ <AS> ] alias = SimpleIdentifier() {
+            list.add(
+                SqlStdOperatorTable.AS.createCall(Span.of(tuple).end(this),
+                    tuple, alias));
+        }
+    |
+        { list.add(tuple); }
+    )
+}
+
+/** Parses an UNPIVOT clause following a table expression. */
+SqlNode Unpivot(SqlNode tableRef) :
+{
+    final Span s;
+    final boolean includeNulls;
+    final SqlNodeList measureList;
+    final SqlNodeList axisList;
+    final Span s2;
+    final List<SqlNode> values = new ArrayList<SqlNode>();
+    final SqlNodeList inList;
+}
+{
+    <UNPIVOT> { s = span(); checkNotJoin(tableRef); }
+    (
+        <INCLUDE> <NULLS> { includeNulls = true; }
+    |   <EXCLUDE> <NULLS> { includeNulls = false; }
+    |   { includeNulls = false; }
+    )
+    <LPAREN>
+    measureList = SimpleIdentifierOrList()
+    <FOR> axisList = SimpleIdentifierOrList()
+    <IN>
+    <LPAREN> { s2 = span(); }
+    AddUnpivotValue(values) ( <COMMA> AddUnpivotValue(values) )*
+    <RPAREN>
+    { inList = new SqlNodeList(values, s2.end(this)); }
+    <RPAREN> {
+        return new SqlUnpivot(s.end(this), tableRef, includeNulls, measureList,
+            axisList, inList);
+    }
+}
+
+void AddUnpivotValue(List<SqlNode> list) :
+{
+    final SqlNodeList columnList;
+    final SqlNode values;
+}
+{
+    columnList = SimpleIdentifierOrList()
+    (
+        <AS> values = RowConstructor() {
+            final SqlNodeList valueList = SqlParserUtil.stripRow(values);
+            list.add(
+                SqlStdOperatorTable.AS.createCall(Span.of(columnList).end(this),
+                    columnList, valueList));
+        }
+    |
+        { list.add(columnList); }
+    )
+}
+
+/**
+ * Parses a MATCH_RECOGNIZE clause following a table expression.
+ */
+SqlMatchRecognize MatchRecognize(SqlNode tableRef) :
+{
+    final Span s, s0, s1, s2;
+    final SqlNodeList measureList;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    final SqlNode pattern;
+    final SqlLiteral interval;
+    final SqlNodeList patternDefList;
+    final SqlNode after;
+    final SqlNode var;
+    final SqlLiteral rowsPerMatch;
+    final SqlNodeList subsetList;
+    final SqlLiteral isStrictStarts;
+    final SqlLiteral isStrictEnds;
+}
+{
+    <MATCH_RECOGNIZE> { s = span(); checkNotJoin(tableRef); } <LPAREN>
+    (
+        <PARTITION> { s2 = span(); } <BY>
+        partitionList = ExpressionCommaList(s2, ExprContext.ACCEPT_NON_QUERY)
+    |
+        { partitionList = SqlNodeList.EMPTY; }
+    )
+    (
+        orderList = OrderBy(true)
+    |
+        { orderList = SqlNodeList.EMPTY; }
+    )
+    (
+        <MEASURES>
+        measureList = MeasureColumnCommaList(span())
+    |
+        { measureList = SqlNodeList.EMPTY; }
+    )
+    (
+        <ONE> { s0 = span(); } <ROW> <PER> <MATCH> {
+            rowsPerMatch = SqlMatchRecognize.RowsPerMatchOption.ONE_ROW.symbol(s0.end(this));
+        }
+    |
+        <ALL> { s0 = span(); } <ROWS> <PER> <MATCH> {
+            rowsPerMatch = SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS.symbol(s0.end(this));
+        }
+    |   { rowsPerMatch = null; }
+    )
+    (
+        <AFTER> { s1 = span(); } <MATCH> <SKIP_>
+        (
+            <TO>
+            (
+                LOOKAHEAD(2)
+                <NEXT> <ROW> {
+                    after = SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW
+                        .symbol(s1.end(this));
+                }
+            |
+                LOOKAHEAD(2)
+                <FIRST> var = SimpleIdentifier() {
+                    after = SqlMatchRecognize.SKIP_TO_FIRST.createCall(
+                        s1.end(var), var);
+                }
+            |
+                // This "LOOKAHEAD({true})" is a workaround for Babel.
+                // Because of babel parser uses option "LOOKAHEAD=2" globally,
+                // JavaCC generates something like "LOOKAHEAD(2, [<LAST>] SimpleIdentifier())"
+                // here. But the correct LOOKAHEAD should be
+                // "LOOKAHEAD(2, [ LOOKAHEAD(2, <LAST> SimpleIdentifier()) <LAST> ]
+                // SimpleIdentifier())" which have the syntactic lookahead for <LAST> considered.
+                //
+                // Overall LOOKAHEAD({true}) is even better as this is the last branch in the
+                // choice.
+                LOOKAHEAD({true})
+                [ LOOKAHEAD(2, <LAST> SimpleIdentifier()) <LAST> ] var = SimpleIdentifier() {
+                    after = SqlMatchRecognize.SKIP_TO_LAST.createCall(
+                        s1.end(var), var);
+                }
+            )
+        |
+            <PAST> <LAST> <ROW> {
+                 after = SqlMatchRecognize.AfterOption.SKIP_PAST_LAST_ROW
+                     .symbol(s1.end(this));
+            }
+        )
+    |   { after = null; }
+    )
+    <PATTERN>
+    <LPAREN>
+    (
+        <CARET> { isStrictStarts = SqlLiteral.createBoolean(true, getPos()); }
+    |   { isStrictStarts = SqlLiteral.createBoolean(false, getPos()); }
+    )
+    pattern = PatternExpression()
+    (
+        <DOLLAR> { isStrictEnds = SqlLiteral.createBoolean(true, getPos()); }
+    |   { isStrictEnds = SqlLiteral.createBoolean(false, getPos()); }
+    )
+    <RPAREN>
+    (
+        <WITHIN> interval = IntervalLiteral()
+    |   { interval = null; }
+    )
+    (
+        <SUBSET> subsetList = SubsetDefinitionCommaList(span())
+    |   { subsetList = SqlNodeList.EMPTY; }
+    )
+    <DEFINE>
+    patternDefList = PatternDefinitionCommaList(span())
+    <RPAREN> {
+        return new SqlMatchRecognize(s.end(this), tableRef,
+            pattern, isStrictStarts, isStrictEnds, patternDefList, measureList,
+            after, subsetList, rowsPerMatch, partitionList, orderList, interval);
+    }
+}
+
+SqlNodeList MeasureColumnCommaList(Span s) :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    AddMeasureColumn(list)
+    ( <COMMA> AddMeasureColumn(list) )*
+    { return new SqlNodeList(list, s.addAll(list).pos()); }
+}
+
+void AddMeasureColumn(List<SqlNode> list) :
+{
+    final SqlNode e;
+    final SqlIdentifier alias;
+}
+{
+    e = Expression(ExprContext.ACCEPT_NON_QUERY)
+    <AS>
+    alias = SimpleIdentifier() {
+        list.add(SqlStdOperatorTable.AS.createCall(Span.of(e).end(this), e, alias));
+    }
+}
+
+SqlNode PatternExpression() :
+{
+    SqlNode left;
+    SqlNode right;
+}
+{
+    left = PatternTerm()
+    (
+        <VERTICAL_BAR>
+        right = PatternTerm() {
+            left = SqlStdOperatorTable.PATTERN_ALTER.createCall(
+                Span.of(left).end(right), left, right);
+        }
+    )*
+    {
+        return left;
+    }
+}
+
+SqlNode PatternTerm() :
+{
+    SqlNode left;
+    SqlNode right;
+}
+{
+    left = PatternFactor()
+    (
+        right = PatternFactor() {
+            left = SqlStdOperatorTable.PATTERN_CONCAT.createCall(
+                Span.of(left).end(right), left, right);
+        }
+    )*
+    {
+        return left;
+    }
+}
+
+SqlNode PatternFactor() :
+{
+    final SqlNode e;
+    final SqlNode extra;
+    final SqlLiteral startNum;
+    final SqlLiteral endNum;
+    final SqlLiteral reluctant;
+}
+{
+    e = PatternPrimary()
+    (
+        LOOKAHEAD(1)
+        (
+            <STAR> {
+                startNum = LITERAL_ZERO;
+                endNum = LITERAL_MINUS_ONE;
+            }
+        |
+            <PLUS> {
+                startNum = LITERAL_ONE;
+                endNum = LITERAL_MINUS_ONE;
+            }
+        |
+            <HOOK> {
+                startNum = LITERAL_ZERO;
+                endNum = LITERAL_ONE;
+            }
+        |
+            <LBRACE>
+            (
+                startNum = UnsignedNumericLiteral()
+                (
+                    <COMMA>
+                    (
+                        endNum = UnsignedNumericLiteral()
+                    |
+                        { endNum = LITERAL_MINUS_ONE; }
+                    )
+                |
+                     { endNum = startNum; }
+                )
+                <RBRACE>
+            |
+                <COMMA>
+                endNum = UnsignedNumericLiteral()
+                <RBRACE>
+                { startNum = LITERAL_MINUS_ONE; }
+            |
+                <MINUS> extra = PatternExpression() <MINUS> <RBRACE> {
+                    return SqlStdOperatorTable.PATTERN_CONCAT.createCall(
+                        Span.of(e).end(this), e,
+                        SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(
+                            Span.of(extra).end(this), extra));
+                }
+            )
+        )
+        (
+            <HOOK> {
+                reluctant = SqlLiteral.createBoolean(
+                    startNum.intValue(true) != endNum.intValue(true),
+                    SqlParserPos.ZERO);
+            }
+        |
+            { reluctant = SqlLiteral.createBoolean(false, SqlParserPos.ZERO); }
+        )
+    |
+        { return e; }
+    )
+    {
+        return SqlStdOperatorTable.PATTERN_QUANTIFIER.createCall(
+            span().end(e), e, startNum, endNum, reluctant);
+    }
+}
+
+SqlNode PatternPrimary() :
+{
+    final Span s;
+    SqlNode e;
+    final List<SqlNode> list;
+}
+{
+    e = SimpleIdentifier() { return e; }
+|
+    <LPAREN> e = PatternExpression() <RPAREN> { return e; }
+|
+    <LBRACE> { s = span(); }
+    <MINUS> e = PatternExpression()
+    <MINUS> <RBRACE> {
+        return SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(s.end(this), e);
+    }
+|
+    (
+        <PERMUTE> { s = span(); list = new ArrayList<SqlNode>(); }
+        <LPAREN>
+        e = PatternExpression() { list.add(e); }
+        ( <COMMA> e = PatternExpression() { list.add(e); } )*
+        <RPAREN> {
+            return SqlStdOperatorTable.PATTERN_PERMUTE.createCall(
+                s.end(this), list);
+        }
+    )
+}
+
+SqlNodeList SubsetDefinitionCommaList(Span s) :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    AddSubsetDefinition(list)
+    ( <COMMA> AddSubsetDefinition(list) )*
+    { return new SqlNodeList(list, s.addAll(list).pos()); }
+}
+
+void AddSubsetDefinition(List<SqlNode> list) :
+{
+    final SqlNode var;
+    final SqlNodeList varList;
+}
+{
+    var = SimpleIdentifier()
+    <EQ>
+    <LPAREN>
+    varList = ExpressionCommaList(span(), ExprContext.ACCEPT_NON_QUERY)
+    <RPAREN> {
+        list.add(
+            SqlStdOperatorTable.EQUALS.createCall(span().end(var), var,
+                varList));
+    }
+}
+
+SqlNodeList PatternDefinitionCommaList(Span s) :
+{
+    SqlNode e;
+    final List<SqlNode> eList = new ArrayList<SqlNode>();
+}
+{
+    e = PatternDefinition() {
+        eList.add(e);
+    }
+    (
+        <COMMA>
+        e = PatternDefinition() {
+            eList.add(e);
+        }
+    )*
+    {
+        return new SqlNodeList(eList, s.addAll(eList).pos());
+    }
+}
+
+SqlNode PatternDefinition() :
+{
+    final SqlNode var;
+    final SqlNode e;
+}
+{
+    var = SimpleIdentifier()
+    <AS>
+    e = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+        return SqlStdOperatorTable.AS.createCall(Span.of(var, e).pos(), e, var);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Expressions
+
+/**
+ * Parses a SQL expression (such as might occur in a WHERE clause) followed by
+ * the end-of-file symbol.
+ */
+SqlNode SqlExpressionEof() :
+{
+    SqlNode e;
+}
+{
+    e = Expression(ExprContext.ACCEPT_SUB_QUERY) (<EOF>)
+    {
+        return e;
+    }
+}
+
+/**
+ * Parses either a row expression or a query expression without ORDER BY.
+ *
+ * <p>Examples of valid queries:
+ * <ul>
+ * <li>{@code SELECT c FROM t}
+ * <li>{@code SELECT c} (valid in some dialects)
+ * <li>{@code SELECT c FROM t UNION SELECT c2 FROM t2}
+ * <li>{@code WITH q AS (SELECT 1) SELECT * FROM q}
+ * <li>{@code VALUES (1, 2)}
+ * <li>{@code TABLE t}
+ * </ul>
+ *
+ * <p>Non-examples:
+ * <ul>
+ * <li>{@code emp CROSS JOIN dept}
+ * <li>{@code SELECT c FROM t ORDER BY c}
+ * <li>{@code (SELECT c FROM t)}
+ * </ul>
+ */
+SqlNode QueryOrExpr(ExprContext exprContext) :
+{
+    SqlNodeList withList = null;
+    final SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+}
+{
+    [ withList = WithList() ]
+    e = LeafQueryOrExpr(exprContext) { list.add(e); }
+    ( AddSetOpQuery(list, exprContext) )*
+    { return addWith(withList, SqlParserUtil.toTree(list)); }
+}
+
+SqlNode Query(ExprContext exprContext) :
+{
+    SqlNodeList withList = null;
+    final SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+}
+{
+    [ withList = WithList() ]
+    e = LeafQuery(exprContext) { list.add(e); }
+    ( AddSetOpQuery(list, exprContext) )*
+    { return addWith(withList, SqlParserUtil.toTree(list)); }
+}
+
+JAVACODE SqlNode addWith(SqlNodeList withList, SqlNode e) {
+    return withList == null
+        ? e
+        : new SqlWith(withList.getParserPosition(), withList, e);
+}
+
+/** Parses a set operator (e.g. UNION or INTERSECT)
+ * followed by a query or expression,
+ * and adds both to {@code list}. */
+void AddSetOpQueryOrExpr(List<Object> list, ExprContext exprContext) :
+{
+    final SqlOperator op;
+    final SqlParserPos pos;
+    final SqlNode e;
+}
+{
+    {
+        if (list.size() == 1 && !((SqlNode) list.get(0)).isA(SqlKind.QUERY)) {
+            // whoops, expression we just parsed wasn't a query,
+            // but we're about to see something like UNION, so
+            // force an exception retroactively
+            checkNonQueryExpression(ExprContext.ACCEPT_QUERY);
+        }
+    }
+    op = BinaryQueryOperator() {
+        // ensure a query is legal in this context
+        pos = getPos();
+        checkQueryExpression(exprContext);
+    }
+    e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY) {
+        list.add(new SqlParserUtil.ToTreeListItem(op, pos));
+        list.add(e);
+    }
+}
+
+/** Parses a set operator (e.g. UNION or INTERSECT)
+ * followed by a query,
+ * and adds both to {@code list}. */
+void AddSetOpQuery(List<Object> list, ExprContext exprContext) :
+{
+    final SqlOperator op;
+    final SqlParserPos pos;
+    final SqlNode e;
+}
+{
+    {
+        if (list.size() == 1 && !((SqlNode) list.get(0)).isA(SqlKind.QUERY)) {
+            // whoops, expression we just parsed wasn't a query,
+            // but we're about to see something like UNION, so
+            // force an exception retroactively
+            checkNonQueryExpression(ExprContext.ACCEPT_QUERY);
+        }
+    }
+    op = BinaryQueryOperator() {
+        // ensure a query is legal in this context
+        pos = getPos();
+        checkQueryExpression(exprContext);
+    }
+    e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY) {
+        list.add(new SqlParserUtil.ToTreeListItem(op, pos));
+        list.add(e);
+    }
+}
+
+SqlNodeList WithList() :
+{
+    final Span s;
+    final List<SqlWithItem> list = new ArrayList<SqlWithItem>();
+}
+{
+    <WITH> { s = span(); }
+    AddWithItem(list) ( <COMMA> AddWithItem(list) )*
+    { return new SqlNodeList(list, s.end(this)); }
+}
+
+void AddWithItem(List<SqlWithItem> list) :
+{
+    final SqlIdentifier id;
+    final SqlNodeList columnList;
+    final SqlNode definition;
+}
+{
+    id = SimpleIdentifier()
+    ( columnList = ParenthesizedSimpleIdentifierList() | { columnList = null; } )
+    <AS>
+    definition = ParenthesizedExpression(ExprContext.ACCEPT_QUERY)
+    { list.add(new SqlWithItem(id.getParserPosition(), id, columnList, definition)); }
+}
+
+/**
+ * Parses either a row expression, a leaf query expression, or
+ * a parenthesized expression of any kind.
+ */
+SqlNode LeafQueryOrExpr(ExprContext exprContext) :
+{
+    SqlNode e;
+}
+{
+    e = LeafQuery(exprContext) { return e; }
+|
+    e = Expression(exprContext) { return e; }
+}
+
+/** As {@link #Expression} but appends to a list. */
+void AddExpression(List<SqlNode> list, ExprContext exprContext) :
+{
+    final SqlNode e;
+}
+{
+    e = Expression(exprContext) { list.add(e); }
+}
+
+/**
+ * Parses a row expression or a parenthesized expression of any kind.
+ */
+SqlNode Expression(ExprContext exprContext) :
+{
+    final List<Object> list;
+}
+{
+    list = Expression2(exprContext) { return SqlParserUtil.toTree(list); }
+}
+
+void AddExpression2b(List<Object> list, ExprContext exprContext) :
+{
+    SqlNode e;
+    SqlOperator op;
+    SqlNode ext;
+}
+{
+    (
+        LOOKAHEAD(1)
+        op = PrefixRowOperator() {
+            checkNonQueryExpression(exprContext);
+            list.add(new SqlParserUtil.ToTreeListItem(op, getPos()));
+        }
+    )*
+    e = Expression3(exprContext) {
+        list.add(e);
+    }
+    (
+        LOOKAHEAD(2) <DOT>
+        ext = RowExpressionExtension() {
+            list.add(
+                new SqlParserUtil.ToTreeListItem(
+                    SqlStdOperatorTable.DOT, getPos()));
+            list.add(ext);
+        }
+    )*
+}
+
+/**
+ * Parses a binary row expression, or a parenthesized expression of any
+ * kind.
+ *
+ * <p>The result is as a flat list of operators and operands. The top-level
+ * call to get an expression should call {@link #Expression}, but lower-level
+ * calls should call this, to give the parser the opportunity to associate
+ * operator calls.
+ *
+ * <p>For example 'a = b like c = d' should come out '((a = b) like c) = d'
+ * because LIKE and '=' have the same precedence, but tends to come out as '(a
+ * = b) like (c = d)' because (a = b) and (c = d) are parsed as separate
+ * expressions.
+ */
+List<Object> Expression2(ExprContext exprContext) :
+{
+    final List<Object> list = new ArrayList();
+    List<Object> list2;
+    final List<Object> list3 = new ArrayList();
+    SqlNodeList nodeList;
+    SqlNode e;
+    SqlOperator op;
+    SqlIdentifier p;
+    final Span s = span();
+}
+{
+    AddExpression2b(list, exprContext)
+    (
+        LOOKAHEAD(2)
+        (
+            LOOKAHEAD(2)
+            (
+                // Special case for "IN", because RHS of "IN" is the only place
+                // that an expression-list is allowed ("exp IN (exp1, exp2)").
+                LOOKAHEAD(2) {
+                    checkNonQueryExpression(exprContext);
+                }
+                (
+                    <NOT> <IN> { op = SqlStdOperatorTable.NOT_IN; }
+                |
+                    <IN> { op = SqlStdOperatorTable.IN; }
+                |
+                    { final SqlKind k; }
+                    k = comp()
+                    (
+                        <SOME> { op = SqlStdOperatorTable.some(k); }
+                    |
+                        <ANY> { op = SqlStdOperatorTable.some(k); }
+                    |
+                        <ALL> { op = SqlStdOperatorTable.all(k); }
+                    )
+                )
+                { s.clear().add(this); }
+                nodeList = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_NONCURSOR)
+                {
+                    list.add(new SqlParserUtil.ToTreeListItem(op, s.pos()));
+                    s.add(nodeList);
+                    // special case for stuff like IN (s1 UNION s2)
+                    if (nodeList.size() == 1) {
+                        SqlNode item = nodeList.get(0);
+                        if (item.isA(SqlKind.QUERY)) {
+                            list.add(item);
+                        } else {
+                            list.add(nodeList);
+                        }
+                    } else {
+                        list.add(nodeList);
+                    }
+                }
+            |
+                LOOKAHEAD(2) {
+                    checkNonQueryExpression(exprContext);
+                }
+                (
+                    <NOT> <BETWEEN> {
+                        op = SqlStdOperatorTable.NOT_BETWEEN;
+                        s.clear().add(this);
+                    }
+                    [
+                        <SYMMETRIC> { op = SqlStdOperatorTable.SYMMETRIC_NOT_BETWEEN; }
+                    |
+                        <ASYMMETRIC>
+                    ]
+                |
+                    <BETWEEN>
+                    {
+                        op = SqlStdOperatorTable.BETWEEN;
+                        s.clear().add(this);
+                    }
+                    [
+                        <SYMMETRIC> { op = SqlStdOperatorTable.SYMMETRIC_BETWEEN; }
+                    |
+                        <ASYMMETRIC>
+                    ]
+                )
+                AddExpression2b(list3, ExprContext.ACCEPT_SUB_QUERY) {
+                    list.add(new SqlParserUtil.ToTreeListItem(op, s.pos()));
+                    list.addAll(list3);
+                    list3.clear();
+                }
+            |
+                LOOKAHEAD(2) {
+                    checkNonQueryExpression(exprContext);
+                    s.clear().add(this);
+                }
+                (
+                    (
+                        <NOT>
+                        (
+                            <LIKE> { op = SqlStdOperatorTable.NOT_LIKE; }
+                        |
+                            <ILIKE> { op = SqlLibraryOperators.NOT_ILIKE; }
+                        |
+                            <RLIKE> { op = SqlLibraryOperators.NOT_RLIKE; }
+                        |
+                            <SIMILAR> <TO> { op = SqlStdOperatorTable.NOT_SIMILAR_TO; }
+                        )
+                    |
+                        <LIKE> { op = SqlStdOperatorTable.LIKE; }
+                    |
+                        <ILIKE> { op = SqlLibraryOperators.ILIKE; }
+                    |
+                        <RLIKE> { op = SqlLibraryOperators.RLIKE; }
+                    |
+                        <SIMILAR> <TO> { op = SqlStdOperatorTable.SIMILAR_TO; }
+                    )
+                <#if (parser.includePosixOperators!default.parser.includePosixOperators)>
+                |
+                    <NEGATE> <TILDE> { op = SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE; }
+                    [ <STAR> { op = SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE; } ]
+                |
+                    <TILDE> { op = SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE; }
+                    [ <STAR> { op = SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE; } ]
+                </#if>
+                )
+                list2 = Expression2(ExprContext.ACCEPT_SUB_QUERY) {
+                    list.add(new SqlParserUtil.ToTreeListItem(op, s.pos()));
+                    list.addAll(list2);
+                }
+                [
+                    LOOKAHEAD(2)
+                    <ESCAPE> e = Expression3(ExprContext.ACCEPT_SUB_QUERY) {
+                        s.clear().add(this);
+                        list.add(
+                            new SqlParserUtil.ToTreeListItem(
+                                SqlStdOperatorTable.ESCAPE, s.pos()));
+                        list.add(e);
+                    }
+                ]
+            |
+            <#list (parser.extraBinaryExpressions!default.parser.extraBinaryExpressions) as extra >
+                ${extra}(list, exprContext, s)
+            |
+            </#list>
+                LOOKAHEAD(3) op = BinaryRowOperator() {
+                    checkNonQueryExpression(exprContext);
+                    list.add(new SqlParserUtil.ToTreeListItem(op, getPos()));
+                }
+                AddExpression2b(list, ExprContext.ACCEPT_SUB_QUERY)
+            |
+                <LBRACKET>
+                e = Expression(ExprContext.ACCEPT_SUB_QUERY)
+                <RBRACKET> {
+                    list.add(
+                        new SqlParserUtil.ToTreeListItem(
+                            SqlStdOperatorTable.ITEM, getPos()));
+                    list.add(e);
+                }
+                (
+                    LOOKAHEAD(2) <DOT>
+                    p = SimpleIdentifier() {
+                        list.add(
+                            new SqlParserUtil.ToTreeListItem(
+                                SqlStdOperatorTable.DOT, getPos()));
+                        list.add(p);
+                    }
+                )*
+            |
+                {
+                    checkNonQueryExpression(exprContext);
+                }
+                op = PostfixRowOperator() {
+                    list.add(new SqlParserUtil.ToTreeListItem(op, getPos()));
+                }
+            )
+        )+
+        {
+            return list;
+        }
+    |
+        {
+            return list;
+        }
+    )
+}
+
+/** Parses a comparison operator inside a SOME / ALL predicate. */
+SqlKind comp() :
+{
+}
+{
+    <LT> { return SqlKind.LESS_THAN; }
+|
+    <LE> { return SqlKind.LESS_THAN_OR_EQUAL; }
+|
+    <GT> { return SqlKind.GREATER_THAN; }
+|
+    <GE> { return SqlKind.GREATER_THAN_OR_EQUAL; }
+|
+    <EQ> { return SqlKind.EQUALS; }
+|
+    <NE> { return SqlKind.NOT_EQUALS; }
+|
+    <NE2> {
+        if (!this.conformance.isBangEqualAllowed()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.bangEqualNotAllowed());
+        }
+        return SqlKind.NOT_EQUALS;
+    }
+}
+
+/**
+ * Parses a unary row expression, or a parenthesized expression of any
+ * kind.
+ */
+SqlNode Expression3(ExprContext exprContext) :
+{
+    final SqlNode e;
+    final SqlNodeList list;
+    final SqlNodeList list1;
+    final Span s;
+    final Span rowSpan;
+}
+{
+    LOOKAHEAD(2)
+    e = AtomicRowExpression()
+    {
+        checkNonQueryExpression(exprContext);
+        return e;
+    }
+|
+    e = CursorExpression(exprContext) { return e; }
+|
+    LOOKAHEAD(3)
+    <ROW> {
+        s = span();
+    }
+    list = ParenthesizedQueryOrCommaList(exprContext) {
+        if (exprContext != ExprContext.ACCEPT_ALL
+            && exprContext != ExprContext.ACCEPT_CURSOR
+            && !this.conformance.allowExplicitRowValueConstructor())
+        {
+            throw SqlUtil.newContextException(s.end(list),
+                RESOURCE.illegalRowExpression());
+        }
+        return SqlStdOperatorTable.ROW.createCall(list);
+    }
+|
+    (
+        <ROW> { rowSpan = span(); }
+    |   { rowSpan = null; }
+    )
+    list1 = ParenthesizedQueryOrCommaList(exprContext) {
+        if (rowSpan != null) {
+            // interpret as row constructor
+            return SqlStdOperatorTable.ROW.createCall(rowSpan.end(list1),
+                (List<SqlNode>) list1);
+        }
+    }
+    [
+        LOOKAHEAD(2)
+        /* TODO:
+        (
+            op = periodOperator()
+            list2 = ParenthesizedQueryOrCommaList(exprContext)
+            {
+                if (list1.size() != 2 || list2.size() != 2) {
+                    throw SqlUtil.newContextException(
+                        list1.getParserPosition().plus(
+                            list2.getParserPosition()),
+                        RESOURCE.illegalOverlaps());
+                }
+                for (SqlNode node : list2) {
+                    list1.add(node);
+                }
+                return op.createCall(
+                    list1.getParserPosition().plus(list2.getParserPosition()),
+                    list1.toArray());
+            }
+        )
+    |
+        */
+        (
+            e = IntervalQualifier()
+            {
+                if ((list1.size() == 1)
+                    && list1.get(0) instanceof SqlCall)
+                {
+                    final SqlCall call = (SqlCall) list1.get(0);
+                    if (call.getKind() == SqlKind.MINUS
+                            && call.operandCount() == 2) {
+                        return SqlStdOperatorTable.MINUS_DATE.createCall(
+                            Span.of(list1).end(this), call.operand(0),
+                            call.operand(1), e);
+                     }
+                }
+                throw SqlUtil.newContextException(span().end(list1),
+                    RESOURCE.illegalMinusDate());
+            }
+        )
+    ]
+    {
+        if (list1.size() == 1) {
+            // interpret as single value or query
+            return list1.get(0);
+        } else {
+            // interpret as row constructor
+            return SqlStdOperatorTable.ROW.createCall(span().end(list1),
+                (List<SqlNode>) list1);
+        }
+    }
+}
+
+SqlOperator periodOperator() :
+{
+}
+{
+     <OVERLAPS> { return SqlStdOperatorTable.OVERLAPS; }
+|
+     LOOKAHEAD(2)
+     <IMMEDIATELY> <PRECEDES> { return SqlStdOperatorTable.IMMEDIATELY_PRECEDES; }
+|
+     <PRECEDES> { return SqlStdOperatorTable.PRECEDES; }
+|
+     <IMMEDIATELY> <SUCCEEDS> { return SqlStdOperatorTable.IMMEDIATELY_SUCCEEDS; }
+|
+     <SUCCEEDS> { return SqlStdOperatorTable.SUCCEEDS; }
+|
+     <EQUALS> { return SqlStdOperatorTable.PERIOD_EQUALS; }
+}
+
+/**
+ * Parses a COLLATE clause
+ */
+SqlCollation CollateClause() :
+{
+}
+{
+    <COLLATE> <COLLATION_ID>
+    {
+        return new SqlCollation(
+            getToken(0).image, SqlCollation.Coercibility.EXPLICIT);
+    }
+}
+
+/**
+ * Numeric literal or parameter; used in LIMIT, OFFSET and FETCH clauses.
+ */
+SqlNode UnsignedNumericLiteralOrParam() :
+{
+    final SqlNode e;
+}
+{
+    (
+        e = UnsignedNumericLiteral()
+    |
+        e = DynamicParam()
+    )
+    { return e; }
+}
+
+/**
+ * Parses a row expression extension, it can be either an identifier,
+ * or a call to a named function.
+ */
+SqlNode RowExpressionExtension() :
+{
+    final SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_FUNCTION;
+    final SqlIdentifier p;
+    final Span s;
+    final List<SqlNode> args;
+    final SqlLiteral quantifier;
+}
+{
+    p = SimpleIdentifier()
+    (
+        LOOKAHEAD( <LPAREN> ) { s = span(); }
+        (
+            LOOKAHEAD(2) <LPAREN> <STAR> {
+                quantifier = null;
+                args = ImmutableList.of(SqlIdentifier.star(getPos()));
+            }
+            <RPAREN>
+        |
+            LOOKAHEAD(2) <LPAREN> <RPAREN> {
+                quantifier = null;
+                args = ImmutableList.of();
+            }
+        |
+            args = FunctionParameterList(ExprContext.ACCEPT_SUB_QUERY) {
+                quantifier = (SqlLiteral) args.get(0);
+                args.remove(0);
+            }
+        )
+        { return createCall(p, s.end(this), funcType, quantifier, args); }
+    |
+        { return p; }
+    )
+}
+
+/**
+ * Parses a call to the STRING_AGG aggregate function (or to an aggregate
+ * function with similar syntax: ARRAY_AGG, ARRAY_CONCAT_AGG, GROUP_CONCAT).
+ */
+SqlCall StringAggFunctionCall() :
+{
+    final Span s, s2;
+    final SqlOperator op;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final SqlLiteral qualifier;
+    final SqlNodeList orderBy;
+    final Pair<SqlParserPos, SqlOperator> nullTreatment;
+    final SqlNode separator;
+}
+{
+    (
+        <ARRAY_AGG> { s = span(); op = SqlLibraryOperators.ARRAY_AGG; }
+    |   <ARRAY_CONCAT_AGG> { s = span(); op = SqlLibraryOperators.ARRAY_CONCAT_AGG; }
+    |   <GROUP_CONCAT> { s = span(); op = SqlLibraryOperators.GROUP_CONCAT; }
+    |   <STRING_AGG> { s = span(); op = SqlLibraryOperators.STRING_AGG; }
+    )
+    <LPAREN>
+    (
+        qualifier = AllOrDistinct()
+    |   { qualifier = null; }
+    )
+    AddArg(args, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <COMMA> {
+            // a comma-list can't appear where only a query is expected
+            // TODO: the following line is a no-op; remove it?
+            checkNonQueryExpression(ExprContext.ACCEPT_SUB_QUERY);
+        }
+        AddArg(args, ExprContext.ACCEPT_SUB_QUERY)
+    )*
+    (
+        nullTreatment = NullTreatment()
+    |   { nullTreatment = null; }
+    )
+    [
+        orderBy = OrderBy(true) {
+            args.add(orderBy);
+        }
+    ]
+    [
+        <SEPARATOR> { s2 = span(); } separator = StringLiteral() {
+            args.add(SqlInternalOperators.SEPARATOR.createCall(s2.end(this), separator));
+        }
+    ]
+    <RPAREN>
+    {
+        SqlCall call = op.createCall(qualifier, s.end(this), args);
+        if (nullTreatment != null) {
+            // Wrap in RESPECT_NULLS or IGNORE_NULLS.
+            call = nullTreatment.right.createCall(nullTreatment.left, call);
+        }
+        return call;
+    }
+}
+
+/**
+ * Parses an atomic row expression.
+ */
+SqlNode AtomicRowExpression() :
+{
+    final SqlNode e;
+}
+{
+    (
+        LOOKAHEAD(2)
+        e = LiteralOrIntervalExpression()
+    |
+        e = DynamicParam()
+    |
+        LOOKAHEAD(2)
+        e = BuiltinFunctionCall()
+    |
+        e = JdbcFunctionCall()
+    |
+        e = MultisetConstructor()
+    |
+        e = ArrayConstructor()
+    |
+        LOOKAHEAD(3)
+        e = MapConstructor()
+    |
+        e = PeriodConstructor()
+    |
+        // NOTE jvs 18-Jan-2005:  use syntactic lookahead to discriminate
+        // compound identifiers from function calls in which the function
+        // name is a compound identifier
+        LOOKAHEAD( [<SPECIFIC>] FunctionName() <LPAREN>)
+        e = NamedFunctionCall()
+    |
+        e = ContextVariable()
+    |
+        e = CompoundIdentifier()
+    |
+        e = NewSpecification()
+    |
+        e = CaseExpression()
+    |
+        e = SequenceExpression()
+    )
+    { return e; }
+}
+
+SqlNode CaseExpression() :
+{
+    final Span whenSpan = Span.of();
+    final Span thenSpan = Span.of();
+    final Span s;
+    SqlNode e;
+    final SqlNode caseIdentifier;
+    final SqlNode elseClause;
+    final List<SqlNode> whenList = new ArrayList<SqlNode>();
+    final List<SqlNode> thenList = new ArrayList<SqlNode>();
+}
+{
+    <CASE> { s = span(); }
+    (
+        caseIdentifier = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    |   { caseIdentifier = null; }
+    )
+    (
+        <WHEN> { whenSpan.add(this); }
+        e = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY) {
+            if (((SqlNodeList) e).size() == 1) {
+                e = ((SqlNodeList) e).get(0);
+            }
+            whenList.add(e);
+        }
+        <THEN> { thenSpan.add(this); }
+        e = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+            thenList.add(e);
+        }
+    )+
+    (
+        <ELSE> elseClause = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    |   { elseClause = null; }
+    )
+    <END> {
+        return SqlCase.createSwitched(s.end(this), caseIdentifier,
+            new SqlNodeList(whenList, whenSpan.addAll(whenList).pos()),
+            new SqlNodeList(thenList, thenSpan.addAll(thenList).pos()),
+            elseClause);
+    }
+}
+
+SqlCall SequenceExpression() :
+{
+    final Span s;
+    final SqlOperator f;
+    final SqlNode sequenceRef;
+}
+{
+    (
+        <NEXT> { f = SqlStdOperatorTable.NEXT_VALUE; s = span(); }
+    |
+        LOOKAHEAD(3)
+        <CURRENT> { f = SqlStdOperatorTable.CURRENT_VALUE; s = span(); }
+    )
+    <VALUE> <FOR> sequenceRef = CompoundIdentifier() {
+        return f.createCall(s.end(sequenceRef), sequenceRef);
+    }
+}
+
+/**
+ * Parses "SET &lt;NAME&gt; = VALUE" or "RESET &lt;NAME&gt;", without a leading
+ * "ALTER &lt;SCOPE&gt;".
+ */
+SqlSetOption SqlSetOption(Span s, String scope) :
+{
+    SqlIdentifier name;
+    final SqlNode val;
+}
+{
+    (
+        <SET> {
+            s.add(this);
+        }
+        name = CompoundIdentifier()
+        <EQ>
+        (
+            val = Literal()
+        |
+            val = SimpleIdentifier()
+        |
+            <ON> {
+                // OFF is handled by SimpleIdentifier, ON handled here.
+                val = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT),
+                    getPos());
+            }
+        )
+        {
+            return new SqlSetOption(s.end(val), scope, name, val);
+        }
+    |
+        <RESET> {
+            s.add(this);
+        }
+        (
+            name = CompoundIdentifier()
+        |
+            <ALL> {
+                name = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT),
+                    getPos());
+            }
+        )
+        {
+            return new SqlSetOption(s.end(name), scope, name, null);
+        }
+    )
+}
+
+/**
+ * Parses an expression for setting or resetting an option in SQL, such as QUOTED_IDENTIFIERS,
+ * or explain plan level (physical/logical).
+ */
+SqlAlter SqlAlter() :
+{
+    final Span s;
+    final String scope;
+    final SqlAlter alterNode;
+}
+{
+    <ALTER> { s = span(); }
+    scope = Scope()
+    (
+<#-- additional literal parser methods are included here -->
+<#list (parser.alterStatementParserMethods!default.parser.alterStatementParserMethods) as method>
+        alterNode = ${method}(s, scope)
+    |
+</#list>
+
+        alterNode = SqlSetOption(s, scope)
+    )
+    {
+        return alterNode;
+    }
+}
+
+String Scope() :
+{
+}
+{
+    ( <SYSTEM> | <SESSION> ) { return token.image.toUpperCase(Locale.ROOT); }
+}
+
+<#if (parser.createStatementParserMethods!default.parser.createStatementParserMethods)?size != 0>
+/**
+ * Parses a CREATE statement.
+ */
+SqlCreate SqlCreate() :
+{
+    final Span s;
+    boolean replace = false;
+    final SqlCreate create;
+}
+{
+    <CREATE> { s = span(); }
+    [
+        <OR> <REPLACE> {
+            replace = true;
+        }
+    ]
+    (
+<#-- additional literal parser methods are included here -->
+<#list (parser.createStatementParserMethods!default.parser.createStatementParserMethods) as method>
+        create = ${method}(s, replace)
+        <#sep>| LOOKAHEAD(2) </#sep>
+</#list>
+    )
+    {
+        return create;
+    }
+}
+</#if>
+
+<#if (parser.dropStatementParserMethods!default.parser.dropStatementParserMethods)?size != 0>
+/**
+ * Parses a DROP statement.
+ */
+SqlDrop SqlDrop() :
+{
+    final Span s;
+    boolean replace = false;
+    final SqlDrop drop;
+}
+{
+    <DROP> { s = span(); }
+    (
+<#-- additional literal parser methods are included here -->
+<#list (parser.dropStatementParserMethods!default.parser.dropStatementParserMethods) as method>
+        drop = ${method}(s, replace)
+        <#sep>|</#sep>
+</#list>
+    )
+    {
+        return drop;
+    }
+}
+</#if>
+
+/**
+ * Parses a literal expression, allowing continued string literals.
+ * Usually returns an SqlLiteral, but a continued string literal
+ * is an SqlCall expression, which concatenates 2 or more string
+ * literals; the validator reduces this.
+ *
+ * <p>If the context allows both literals and expressions,
+ * use {@link #LiteralOrIntervalExpression}, which requires less
+ * lookahead.
+ */
+SqlNode Literal() :
+{
+    SqlNode e;
+}
+{
+    (
+        e = NonIntervalLiteral()
+    |
+        e = IntervalLiteral()
+    )
+    { return e; }
+}
+
+/** Parses a literal that is not an interval literal. */
+SqlNode NonIntervalLiteral() :
+{
+    final SqlNode e;
+}
+{
+    (
+        e = NumericLiteral()
+    |
+        e = StringLiteral()
+    |
+        e = SpecialLiteral()
+    |
+        e = DateTimeLiteral()
+<#-- additional literal parser methods are included here -->
+<#list (parser.literalParserMethods!default.parser.literalParserMethods) as method>
+    |
+        e = ${method}
+</#list>
+    )
+    {
+        return e;
+    }
+}
+
+/** Parses a literal or an interval expression.
+ *
+ * <p>We include them in the same production because it is difficult to
+ * distinguish interval literals from interval expression (both of which
+ * start with the {@code INTERVAL} keyword); this way, we can use less
+ * LOOKAHEAD. */
+SqlNode LiteralOrIntervalExpression() :
+{
+    final SqlNode e;
+}
+{
+    (
+        e = IntervalLiteralOrExpression()
+    |
+        e = NonIntervalLiteral()
+    )
+    { return e; }
+}
+
+/** Parses a unsigned numeric literal */
+SqlNumericLiteral UnsignedNumericLiteral() :
+{
+}
+{
+    <UNSIGNED_INTEGER_LITERAL> {
+        return SqlLiteral.createExactNumeric(token.image, getPos());
+    }
+|
+    <DECIMAL_NUMERIC_LITERAL> {
+        return SqlLiteral.createExactNumeric(token.image, getPos());
+    }
+|
+    <APPROX_NUMERIC_LITERAL> {
+        return SqlLiteral.createApproxNumeric(token.image, getPos());
+    }
+}
+
+/** Parses a numeric literal (can be signed) */
+SqlLiteral NumericLiteral() :
+{
+    final SqlNumericLiteral num;
+    final Span s;
+}
+{
+    <PLUS> num = UnsignedNumericLiteral() {
+        return num;
+    }
+|
+    <MINUS> { s = span(); } num = UnsignedNumericLiteral() {
+        return SqlLiteral.createNegative(num, s.end(this));
+    }
+|
+    num = UnsignedNumericLiteral() {
+        return num;
+    }
+}
+
+/** Parse a special literal keyword */
+SqlLiteral SpecialLiteral() :
+{
+}
+{
+    <TRUE> { return SqlLiteral.createBoolean(true, getPos()); }
+|
+    <FALSE> { return SqlLiteral.createBoolean(false, getPos()); }
+|
+    <UNKNOWN> { return SqlLiteral.createUnknown(getPos()); }
+|
+    <NULL> { return SqlLiteral.createNull(getPos()); }
+}
+
+/**
+ * Parses a string literal. The literal may be continued onto several
+ * lines.  For a simple literal, the result is an SqlLiteral.  For a continued
+ * literal, the result is an SqlCall expression, which concatenates 2 or more
+ * string literals; the validator reduces this.
+ *
+ * @see SqlLiteral#unchain(SqlNode)
+ * @see SqlLiteral#stringValue(SqlNode)
+ *
+ * @return a literal expression
+ */
+SqlNode StringLiteral() :
+{
+    String p;
+    final List<SqlLiteral> frags;
+    char unicodeEscapeChar = 0;
+    String charSet = null;
+    SqlCharStringLiteral literal;
+}
+{
+    // A continued string literal consists of a head fragment and one or more
+    // tail fragments. Since comments may occur between the fragments, and
+    // comments are special tokens, each fragment is a token. But since spaces
+    // or comments may not occur between the prefix and the first quote, the
+    // head fragment, with any prefix, is one token.
+
+    <BINARY_STRING_LITERAL>
+    {
+        frags = new ArrayList<SqlLiteral>();
+        try {
+            p = SqlParserUtil.trim(token.image, "xX'");
+            frags.add(SqlLiteral.createBinaryString(p, getPos()));
+        } catch (NumberFormatException ex) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.illegalBinaryString(token.image));
+        }
+    }
+    (
+        // The grammar is ambiguous when a continued literals and a character
+        // string alias are both possible. For example, in
+        //   SELECT x'01'\n'ab'
+        // we prefer that 'ab' continues the literal, and is not an alias.
+        // The following LOOKAHEAD mutes the warning about ambiguity.
+        LOOKAHEAD(1)
+        <QUOTED_STRING>
+        {
+            try {
+                p = SqlParserUtil.trim(token.image, "'"); // no embedded quotes
+                frags.add(SqlLiteral.createBinaryString(p, getPos()));
+            } catch (NumberFormatException ex) {
+                throw SqlUtil.newContextException(getPos(),
+                    RESOURCE.illegalBinaryString(token.image));
+            }
+        }
+    )*
+    {
+        assert !frags.isEmpty();
+        if (frags.size() == 1) {
+            return frags.get(0); // just the head fragment
+        } else {
+            SqlParserPos pos2 = SqlParserPos.sum(frags);
+            return SqlStdOperatorTable.LITERAL_CHAIN.createCall(pos2, frags);
+        }
+    }
+|
+    (
+        <PREFIXED_STRING_LITERAL>
+        { charSet = SqlParserUtil.getCharacterSet(token.image); }
+    |   <QUOTED_STRING>
+    |   <UNICODE_STRING_LITERAL> {
+            // TODO jvs 2-Feb-2009:  support the explicit specification of
+            // a character set for Unicode string literals, per SQL:2003
+            unicodeEscapeChar = BACKSLASH;
+            charSet = "UTF16";
+        }
+    )
+    {
+        frags = new ArrayList<SqlLiteral>();
+        p = SqlParserUtil.parseString(token.image);
+        try {
+            literal = SqlLiteral.createCharString(p, charSet, getPos());
+            frags.add(literal);
+        } catch (java.nio.charset.UnsupportedCharsetException e) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.unknownCharacterSet(charSet));
+        }
+    }
+    (
+        // The grammar is ambiguous when a continued literals and a character
+        // string alias are both possible. For example, in
+        //   SELECT 'taxi'\n'cab'
+        // we prefer that 'cab' continues the literal, and is not an alias.
+        // The following LOOKAHEAD mutes the warning about ambiguity.
+        LOOKAHEAD(1)
+        <QUOTED_STRING>
+        {
+            p = SqlParserUtil.parseString(token.image);
+            try {
+                literal = SqlLiteral.createCharString(p, charSet, getPos());
+                frags.add(literal);
+            } catch (java.nio.charset.UnsupportedCharsetException e) {
+                throw SqlUtil.newContextException(getPos(),
+                    RESOURCE.unknownCharacterSet(charSet));
+            }
+        }
+    )*
+    [
+        <UESCAPE> <QUOTED_STRING>
+        {
+            if (unicodeEscapeChar == 0) {
+                throw SqlUtil.newContextException(getPos(),
+                    RESOURCE.unicodeEscapeUnexpected());
+            }
+            String s = SqlParserUtil.parseString(token.image);
+            unicodeEscapeChar = SqlParserUtil.checkUnicodeEscapeChar(s);
+        }
+    ]
+    {
+        assert !frags.isEmpty();
+        if (frags.size() == 1) {
+            // just the head fragment
+            SqlLiteral lit = (SqlLiteral) frags.get(0);
+            return lit.unescapeUnicode(unicodeEscapeChar);
+        } else {
+            SqlNode[] rands = (SqlNode[]) frags.toArray(new SqlNode[0]);
+            for (int i = 0; i < rands.length; ++i) {
+                rands[i] = ((SqlLiteral) rands[i]).unescapeUnicode(
+                    unicodeEscapeChar);
+            }
+            SqlParserPos pos2 = SqlParserPos.sum(rands);
+            return SqlStdOperatorTable.LITERAL_CHAIN.createCall(pos2, rands);
+        }
+    }
+|
+    <C_STYLE_ESCAPED_STRING_LITERAL>
+    {
+        try {
+            p = SqlParserUtil.parseCString(getToken(0).image);
+        } catch (SqlParserUtil.MalformedUnicodeEscape e) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.unicodeEscapeMalformed(e.i));
+       }
+       return SqlLiteral.createCharString(p, "UTF16", getPos());
+    }
+|
+    <BIG_QUERY_DOUBLE_QUOTED_STRING>
+    {
+        p = SqlParserUtil.stripQuotes(getToken(0).image, DQ, DQ, "\\\"",
+            Casing.UNCHANGED);
+        try {
+            return SqlLiteral.createCharString(p, charSet, getPos());
+        } catch (java.nio.charset.UnsupportedCharsetException e) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.unknownCharacterSet(charSet));
+        }
+    }
+|
+    <BIG_QUERY_QUOTED_STRING>
+    {
+        p = SqlParserUtil.stripQuotes(getToken(0).image, "'", "'", "\\'",
+            Casing.UNCHANGED);
+        try {
+            return SqlLiteral.createCharString(p, charSet, getPos());
+        } catch (java.nio.charset.UnsupportedCharsetException e) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.unknownCharacterSet(charSet));
+        }
+    }
+}
+
+/** Parses a character literal.
+ * Matches a single-quoted string, such as 'foo';
+ * on BigQuery also matches a double-quoted string, such as "foo".
+ * Returns the value of the string with quotes removed. */
+String SimpleStringLiteral() :
+{
+}
+{
+    <QUOTED_STRING> {
+        return SqlParserUtil.parseString(token.image);
+    }
+|
+    <BIG_QUERY_QUOTED_STRING> {
+        return SqlParserUtil.stripQuotes(token.image, "'", "'", "\\'", Casing.UNCHANGED);
+    }
+|
+    <BIG_QUERY_DOUBLE_QUOTED_STRING> {
+        return SqlParserUtil.stripQuotes(token.image, DQ, DQ, "\\\"", Casing.UNCHANGED);
+    }
+}
+
+/**
+ * Parses a date/time literal.
+ */
+SqlLiteral DateTimeLiteral() :
+{
+    final String p;
+    final Span s;
+}
+{
+    <LBRACE_D> <QUOTED_STRING> {
+        p = SqlParserUtil.parseString(token.image);
+    }
+    <RBRACE> {
+        return SqlParserUtil.parseDateLiteral(p, getPos());
+    }
+|
+    <LBRACE_T> <QUOTED_STRING> {
+        p = SqlParserUtil.parseString(token.image);
+    }
+    <RBRACE> {
+        return SqlParserUtil.parseTimeLiteral(p, getPos());
+    }
+|
+    <LBRACE_TS> { s = span(); } <QUOTED_STRING> {
+        p = SqlParserUtil.parseString(token.image);
+    }
+    <RBRACE> {
+        return SqlParserUtil.parseTimestampLiteral(p, s.end(this));
+    }
+|
+    <DATE> { s = span(); } p = SimpleStringLiteral() {
+      return SqlLiteral.createUnknown("DATE", p, s.end(this));
+    }
+|
+    <DATETIME> { s = span(); } p = SimpleStringLiteral() {
+        return SqlLiteral.createUnknown("DATETIME", p, s.end(this));
+    }
+|
+    <TIME> { s = span(); } p = SimpleStringLiteral() {
+      return SqlLiteral.createUnknown("TIME", p, s.end(this));
+    }
+|
+    LOOKAHEAD(2)
+    <TIMESTAMP> { s = span(); } p = SimpleStringLiteral() {
+        return SqlLiteral.createUnknown("TIMESTAMP", p, s.end(this));
+    }
+|
+    <TIMESTAMP> { s = span(); } <WITH> <LOCAL> <TIME> <ZONE> p = SimpleStringLiteral() {
+        return SqlLiteral.createUnknown("TIMESTAMP WITH LOCAL TIME ZONE", p, s.end(this));
+    }
+}
+
+/** Parses a Date/Time constructor function, for example "DATE(1969, 7, 21)"
+ * or "DATETIME(d, t)". Enabled in some libraries (e.g. BigQuery). */
+SqlNode DateTimeConstructorCall() :
+{
+    final SqlFunctionCategory funcType = SqlFunctionCategory.TIMEDATE;
+    final SqlIdentifier qualifiedName;
+    final Span s;
+    final SqlLiteral quantifier;
+    final List<? extends SqlNode> args;
+}
+{
+    (<DATE> | <TIME> | <DATETIME> | <TIMESTAMP>) {
+        s = span();
+        qualifiedName = new SqlIdentifier(unquotedIdentifier(), getPos());
+    }
+    args = FunctionParameterList(ExprContext.ACCEPT_SUB_QUERY) {
+        quantifier = (SqlLiteral) args.get(0);
+        args.remove(0);
+        return createCall(qualifiedName, s.end(this), funcType, quantifier, args);
+    }
+}
+
+/** Parses a MULTISET constructor */
+SqlNode MultisetConstructor() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+    final Span s;
+}
+{
+    <MULTISET> { s = span(); }
+    (
+        LOOKAHEAD(2)
+        <LPAREN>
+        // by sub query "MULTISET(SELECT * FROM T)"
+        e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY)
+        <RPAREN> {
+            return SqlStdOperatorTable.MULTISET_QUERY.createCall(
+                s.end(this), e);
+        }
+    |
+        // by enumeration "MULTISET[e0, e1, ..., eN]"
+        <LBRACKET> // TODO: do trigraph as well ??( ??)
+        AddExpression(args, ExprContext.ACCEPT_NON_QUERY)
+        ( <COMMA> AddExpression(args, ExprContext.ACCEPT_NON_QUERY) )*
+        <RBRACKET>
+        {
+            return SqlStdOperatorTable.MULTISET_VALUE.createCall(
+                s.end(this), args);
+        }
+    )
+}
+
+/** Parses an ARRAY constructor */
+SqlNode ArrayConstructor() :
+{
+    SqlNodeList args;
+    SqlNode e;
+    final Span s;
+    final String p;
+}
+{
+    <ARRAY> { s = span(); }
+    (
+        LOOKAHEAD(1)
+        <LPAREN>
+        // by sub query "MULTISET(SELECT * FROM T)"
+        e = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+        <RPAREN>
+        {
+            return SqlStdOperatorTable.ARRAY_QUERY.createCall(
+                s.end(this), e);
+        }
+    |
+        // by enumeration "ARRAY[e0, e1, ..., eN]"
+        <LBRACKET> // TODO: do trigraph as well ??( ??)
+        (
+            args = ExpressionCommaList(s, ExprContext.ACCEPT_NON_QUERY)
+        |
+            { args = SqlNodeList.EMPTY; }
+        )
+        <RBRACKET>
+        {
+            return SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR.createCall(
+                s.end(this), args.getList());
+        }
+<#if (parser.includeParsingStringLiteralAsArrayLiteral!default.parser.includeParsingStringLiteralAsArrayLiteral) >
+    |
+        p = SimpleStringLiteral() {
+            try {
+                return SqlParserUtil.parseArrayLiteral(p);
+            } catch (SqlParseException ex) {
+                throw SqlUtil.newContextException(getPos(),
+                    RESOURCE.illegalArrayExpression(p));
+            }
+        }
+</#if>
+    )
+}
+
+SqlCall ArrayLiteral() :
+{
+    final List<SqlNode> list;
+    SqlNode e;
+    final Span s;
+}
+{
+    <LBRACE> { s = span(); }
+    (
+        e = Literal() { list = startList(e); }
+        ( <COMMA> e = Literal() { list.add(e); } )*
+    |
+        e = ArrayLiteral() { list = startList(e); }
+        ( <COMMA> e = ArrayLiteral() { list.add(e); } )*
+    |
+        { list = Collections.emptyList(); }
+    )
+    <RBRACE> {
+       return SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR.createCall(s.end(this), list);
+    }
+}
+
+/** Parses a MAP constructor */
+SqlNode MapConstructor() :
+{
+    SqlNodeList args;
+    SqlNode e;
+    final Span s;
+}
+{
+    <MAP> { s = span(); }
+    (
+        LOOKAHEAD(1)
+        <LPAREN>
+        // by sub query "MAP (SELECT empno, deptno FROM emp)"
+        e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY)
+        <RPAREN>
+        {
+            return SqlStdOperatorTable.MAP_QUERY.createCall(
+                s.end(this), e);
+        }
+    |
+        // by enumeration "MAP[k0, v0, ..., kN, vN]"
+        <LBRACKET> // TODO: do trigraph as well ??( ??)
+        (
+            args = ExpressionCommaList(s, ExprContext.ACCEPT_NON_QUERY)
+        |
+            { args = SqlNodeList.EMPTY; }
+        )
+        <RBRACKET>
+        {
+            return SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR.createCall(
+                s.end(this), args.getList());
+        }
+    )
+}
+
+/** Parses a PERIOD constructor */
+SqlNode PeriodConstructor() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    <PERIOD> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        return SqlStdOperatorTable.ROW.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses an interval literal.
+ */
+SqlLiteral IntervalLiteral() :
+{
+    final String p;
+    final SqlIntervalQualifier intervalQualifier;
+    int sign = 1;
+    final Span s;
+}
+{
+    <INTERVAL> { s = span(); }
+    [
+        <MINUS> { sign = -1; }
+    |
+        <PLUS> { sign = 1; }
+    ]
+    p = SimpleStringLiteral()
+    intervalQualifier = IntervalQualifier() {
+        return SqlParserUtil.parseIntervalLiteral(s.end(intervalQualifier),
+            sign, p, intervalQualifier);
+    }
+}
+
+/** Parses an interval literal (e.g. {@code INTERVAL '2:3' HOUR TO MINUTE})
+ * or an interval expression (e.g. {@code INTERVAL emp.empno MINUTE}
+ * or {@code INTERVAL 3 MONTHS}). */
+SqlNode IntervalLiteralOrExpression() :
+{
+    final String p;
+    final SqlIntervalQualifier intervalQualifier;
+    int sign = 1;
+    final Span s;
+    SqlNode e;
+}
+{
+    <INTERVAL> { s = span(); }
+    [
+        <MINUS> { sign = -1; }
+    |
+        <PLUS> { sign = 1; }
+    ]
+    (
+        // literal (with quoted string)
+        p = SimpleStringLiteral()
+        intervalQualifier = IntervalQualifier() {
+            return SqlParserUtil.parseIntervalLiteral(s.end(intervalQualifier),
+                sign, p, intervalQualifier);
+        }
+    |
+        // To keep parsing simple, any expressions besides numeric literal and
+        // identifiers must be enclosed in parentheses.
+        (
+            <LPAREN>
+            e = Expression(ExprContext.ACCEPT_SUB_QUERY)
+            <RPAREN>
+        |
+            e = UnsignedNumericLiteral()
+        |
+            e = CompoundIdentifier()
+        )
+        intervalQualifier = IntervalQualifierStart() {
+            if (sign == -1) {
+                e = SqlStdOperatorTable.UNARY_MINUS.createCall(e.getParserPosition(), e);
+            }
+            return SqlStdOperatorTable.INTERVAL.createCall(s.end(this), e,
+                intervalQualifier);
+        }
+    )
+}
+
+TimeUnit Year() :
+{
+}
+{
+    <YEAR> { return TimeUnit.YEAR; }
+|
+    <YEARS> { return warn(TimeUnit.YEAR); }
+}
+
+TimeUnit Quarter() :
+{
+}
+{
+    <QUARTER> { return TimeUnit.QUARTER; }
+|
+    <QUARTERS> { return warn(TimeUnit.QUARTER); }
+}
+
+TimeUnit Month() :
+{
+}
+{
+    <MONTH> { return TimeUnit.MONTH; }
+|
+    <MONTHS> { return warn(TimeUnit.MONTH); }
+}
+
+TimeUnit Week() :
+{
+}
+{
+    <WEEK> { return TimeUnit.WEEK; }
+|
+    <WEEKS> { return warn(TimeUnit.WEEK); }
+}
+
+TimeUnit Day() :
+{
+}
+{
+    <DAY> { return TimeUnit.DAY; }
+|
+    <DAYS> { return warn(TimeUnit.DAY); }
+}
+
+TimeUnit Hour() :
+{
+}
+{
+    <HOUR> { return TimeUnit.HOUR; }
+|
+    <HOURS> { return warn(TimeUnit.HOUR); }
+}
+
+TimeUnit Minute() :
+{
+}
+{
+    <MINUTE> { return TimeUnit.MINUTE; }
+|
+    <MINUTES> { return warn(TimeUnit.MINUTE); }
+}
+
+TimeUnit Second() :
+{
+}
+{
+    <SECOND> { return TimeUnit.SECOND; }
+|
+    <SECONDS> { return warn(TimeUnit.SECOND); }
+}
+
+SqlIntervalQualifier IntervalQualifier() :
+{
+    final Span s;
+    final TimeUnit start;
+    final TimeUnit end;
+    final int startPrec;
+    int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+}
+{
+    (
+        start = Year() { s = span(); } startPrec = PrecisionOpt()
+        (
+            LOOKAHEAD(2) <TO> end = Month()
+        |   { end = null; }
+        )
+    |
+        start = Quarter() { s = span(); } startPrec = PrecisionOpt()
+        { end = null; }
+    |
+        start = Month() { s = span(); } startPrec = PrecisionOpt()
+        { end = null; }
+    |
+        start = Week() { s = span(); } startPrec = PrecisionOpt()
+        { end = null; }
+    |
+        start = Day() { s = span(); } startPrec = PrecisionOpt()
+        (
+            LOOKAHEAD(2) <TO>
+            (
+                end = Hour()
+            |
+                end = Minute()
+            |
+                end = Second() secondFracPrec = PrecisionOpt()
+            )
+        |   { end = null; }
+        )
+    |
+        start = Hour() { s = span(); } startPrec = PrecisionOpt()
+        (
+            LOOKAHEAD(2) <TO>
+            (
+                end = Minute()
+            |
+                end = Second()
+                [ <LPAREN> secondFracPrec = UnsignedIntLiteral() <RPAREN> ]
+            )
+        |   { end = null; }
+        )
+    |
+        start = Minute() { s = span(); } startPrec = PrecisionOpt()
+        (
+            LOOKAHEAD(2) <TO>
+            end = Second()
+            [ <LPAREN> secondFracPrec = UnsignedIntLiteral() <RPAREN> ]
+        |   { end = null; }
+        )
+    |
+        start = Second() { s = span(); }
+        (
+            <LPAREN> startPrec = UnsignedIntLiteral()
+            [ <COMMA> secondFracPrec = UnsignedIntLiteral() ]
+            <RPAREN>
+        |   { startPrec = -1; }
+        )
+        { end = null; }
+    )
+    {
+        return new SqlIntervalQualifier(start, startPrec, end, secondFracPrec,
+            s.end(this));
+    }
+}
+
+/** Interval qualifier without 'TO unit'. */
+SqlIntervalQualifier IntervalQualifierStart() :
+{
+    final Span s;
+    final TimeUnit start;
+    int startPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+    int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+}
+{
+    (
+        (
+            start = Year()
+        |   start = Quarter()
+        |   start = Month()
+        |   start = Week()
+        |   start = Day()
+        |   start = Hour()
+        |   start = Minute()
+        )
+        { s = span(); }
+        startPrec = PrecisionOpt()
+    |
+        start = Second() { s = span(); }
+        [   <LPAREN> startPrec = UnsignedIntLiteral()
+            [ <COMMA> secondFracPrec = UnsignedIntLiteral() ]
+            <RPAREN>
+        ]
+    )
+    {
+        return new SqlIntervalQualifier(start, startPrec, null, secondFracPrec,
+            s.end(this));
+    }
+}
+
+/** Parses a built-in time unit (e.g. "YEAR")
+ * or user-defined time frame (e.g. "MINUTE15")
+ * and in each case returns a {@link SqlIntervalQualifier}.
+ *
+ * <p>The units are used in several functions, incuding CEIL, FLOOR, EXTRACT.
+ * Includes NANOSECOND, MILLISECOND, which were previously allowed in EXTRACT
+ * but not CEIL, FLOOR.
+ *
+ * <p>Includes {@code WEEK} and {@code WEEK(SUNDAY)} through
+  {@code WEEK(SATURDAY)}.
+ *
+ * <p>Does not include SQL_TSI_DAY, SQL_TSI_FRAC_SECOND etc. These will be
+ * parsed as identifiers and can be resolved in the validator if they are
+ * registered as abbreviations in your time frame set.
+ */
+SqlIntervalQualifier TimeUnitOrName() : {
+    final SqlIdentifier unitName;
+    final SqlIntervalQualifier intervalQualifier;
+}
+{
+    // When we see a time unit that is also a non-reserved keyword, such as
+    // NANOSECOND, there is a choice between using the TimeUnit enum
+    // (TimeUnit.NANOSECOND) or the name. The following LOOKAHEAD directive
+    // tells the parser that we prefer the former.
+    //
+    // Reserved keywords, such as SECOND, cannot be identifiers, and are
+    // therefore not ambiguous.
+    LOOKAHEAD(2)
+    intervalQualifier = TimeUnit() {
+        return intervalQualifier;
+    }
+|   unitName = SimpleIdentifier() {
+        return new SqlIntervalQualifier(unitName.getSimple(),
+            unitName.getParserPosition());
+    }
+}
+
+/** Parses a built-in time unit (e.g. "YEAR")
+ * and returns a {@link SqlIntervalQualifier}.
+ *
+ * <p>Includes {@code WEEK} and {@code WEEK(SUNDAY)} through
+  {@code WEEK(SATURDAY)}.
+ *
+ * <p>Does not include SQL_TSI_DAY, SQL_TSI_FRAC_SECOND etc. These will be
+ * parsed as identifiers and can be resolved in the validator if they are
+ * registered as abbreviations in your time frame set.
+ */
+SqlIntervalQualifier TimeUnit() : {
+    final Span span;
+    final String w;
+}
+{
+    <NANOSECOND> { return new SqlIntervalQualifier(TimeUnit.NANOSECOND, null, getPos()); }
+|   <MICROSECOND> { return new SqlIntervalQualifier(TimeUnit.MICROSECOND, null, getPos()); }
+|   <MILLISECOND> { return new SqlIntervalQualifier(TimeUnit.MILLISECOND, null, getPos()); }
+|   <SECOND> { return new SqlIntervalQualifier(TimeUnit.SECOND, null, getPos()); }
+|   <MINUTE> { return new SqlIntervalQualifier(TimeUnit.MINUTE, null, getPos()); }
+|   <HOUR> { return new SqlIntervalQualifier(TimeUnit.HOUR, null, getPos()); }
+|   <DAY> { return new SqlIntervalQualifier(TimeUnit.DAY, null, getPos()); }
+|   <DOW> { return new SqlIntervalQualifier(TimeUnit.DOW, null, getPos()); }
+|   <DOY> { return new SqlIntervalQualifier(TimeUnit.DOY, null, getPos()); }
+|   <ISODOW> { return new SqlIntervalQualifier(TimeUnit.ISODOW, null, getPos()); }
+|   <ISOYEAR> { return new SqlIntervalQualifier(TimeUnit.ISOYEAR, null, getPos()); }
+|   <WEEK> { span = span(); }
+    (
+        // There is a choice between "WEEK(weekday)" and "WEEK". We prefer
+        // the former, and the parser will look ahead for '('.
+        LOOKAHEAD(2)
+        <LPAREN> w = weekdayName() <RPAREN> {
+            return new SqlIntervalQualifier(w, span.end(this));
+        }
+    |
+        { return new SqlIntervalQualifier(TimeUnit.WEEK, null, getPos()); }
+    )
+|   <MONTH> { return new SqlIntervalQualifier(TimeUnit.MONTH, null, getPos()); }
+|   <QUARTER> { return new SqlIntervalQualifier(TimeUnit.QUARTER, null, getPos()); }
+|   <YEAR> { return new SqlIntervalQualifier(TimeUnit.YEAR, null, getPos()); }
+|   <EPOCH> { return new SqlIntervalQualifier(TimeUnit.EPOCH, null, getPos()); }
+|   <DECADE> { return new SqlIntervalQualifier(TimeUnit.DECADE, null, getPos()); }
+|   <CENTURY> { return new SqlIntervalQualifier(TimeUnit.CENTURY, null, getPos()); }
+|   <MILLENNIUM> { return new SqlIntervalQualifier(TimeUnit.MILLENNIUM, null, getPos()); }
+}
+
+String weekdayName() :
+{
+}
+{
+    <SUNDAY> { return "WEEK_SUNDAY"; }
+|   <MONDAY> { return "WEEK_MONDAY"; }
+|   <TUESDAY> { return "WEEK_TUESDAY"; }
+|   <WEDNESDAY> { return "WEEK_WEDNESDAY"; }
+|   <THURSDAY> { return "WEEK_THURSDAY"; }
+|   <FRIDAY> { return "WEEK_FRIDAY"; }
+|   <SATURDAY> { return "WEEK_SATURDAY"; }
+}
+
+/**
+ * Parses a dynamic parameter marker.
+ */
+SqlDynamicParam DynamicParam() :
+{
+}
+{
+    <HOOK> {
+        return new SqlDynamicParam(nDynamicParams++, getPos());
+    }
+}
+
+/**
+ * Parses one segment of an identifier that may be composite.
+ *
+ * <p>Each time it reads an identifier it writes one element to each list;
+ * the entry in {@code positions} records its position and whether the
+ * segment was quoted.
+ */
+void AddIdentifierSegment(List<String> names, List<SqlParserPos> positions) :
+{
+    final String id;
+    char unicodeEscapeChar = BACKSLASH;
+    final SqlParserPos pos;
+    final Span span;
+}
+{
+    (
+        <IDENTIFIER> {
+            id = unquotedIdentifier();
+            pos = getPos();
+        }
+    |
+        <HYPHENATED_IDENTIFIER> {
+            id = unquotedIdentifier();
+            pos = getPos();
+        }
+    |
+        <QUOTED_IDENTIFIER> {
+            id = SqlParserUtil.stripQuotes(getToken(0).image, DQ, DQ, DQDQ,
+                quotedCasing);
+            pos = getPos().withQuoting(true);
+        }
+    |
+        <BACK_QUOTED_IDENTIFIER> {
+            id = SqlParserUtil.stripQuotes(getToken(0).image, "`", "`", "``",
+                quotedCasing);
+            pos = getPos().withQuoting(true);
+        }
+    |
+        <BIG_QUERY_BACK_QUOTED_IDENTIFIER> {
+            id = SqlParserUtil.stripQuotes(getToken(0).image, "`", "`", "\\`",
+                quotedCasing);
+            pos = getPos().withQuoting(true);
+        }
+    |
+        <BRACKET_QUOTED_IDENTIFIER> {
+            id = SqlParserUtil.stripQuotes(getToken(0).image, "[", "]", "]]",
+                quotedCasing);
+            pos = getPos().withQuoting(true);
+        }
+    |
+        <UNICODE_QUOTED_IDENTIFIER> {
+            span = span();
+            String image = getToken(0).image;
+            image = image.substring(image.indexOf('"'));
+            image = SqlParserUtil.stripQuotes(image, DQ, DQ, DQDQ, quotedCasing);
+        }
+        [
+            <UESCAPE> <QUOTED_STRING> {
+                String s = SqlParserUtil.parseString(token.image);
+                unicodeEscapeChar = SqlParserUtil.checkUnicodeEscapeChar(s);
+            }
+        ]
+        {
+            pos = span.end(this).withQuoting(true);
+            SqlLiteral lit = SqlLiteral.createCharString(image, "UTF16", pos);
+            lit = lit.unescapeUnicode(unicodeEscapeChar);
+            id = lit.toValue();
+        }
+    |
+        id = NonReservedKeyWord() {
+            pos = getPos();
+        }
+    )
+    {
+        if (id.length() > this.identifierMaxLength) {
+            throw SqlUtil.newContextException(pos,
+                RESOURCE.identifierTooLong(id, this.identifierMaxLength));
+        }
+        names.add(id);
+        if (positions != null) {
+            positions.add(pos);
+        }
+    }
+}
+
+/** As {@link #AddIdentifierSegment} but part of a table name (for example,
+ * following {@code FROM}, {@code INSERT} or {@code UPDATE}).
+ *
+ * <p>In some dialects the lexical rules for table names are different from
+ * for other identifiers. For example, in BigQuery, table names may contain
+ * hyphens. */
+void AddTableIdentifierSegment(List<String> names, List<SqlParserPos> positions) :
+{
+}
+{
+    AddIdentifierSegment(names, positions) {
+        final int n = names.size();
+        if (n > 0
+                && positions.size() == n
+                && names.get(n - 1).contains(".")
+                && positions.get(n - 1).isQuoted()
+                && this.conformance.splitQuotedTableName()) {
+            final String name = names.remove(n - 1);
+            final SqlParserPos pos = positions.remove(n - 1);
+            final String[] splitNames = name.split("\\.");
+            for (String splitName : splitNames) {
+                names.add(splitName);
+                positions.add(pos);
+            }
+        }
+    }
+}
+
+/**
+ * Parses a simple identifier as a String.
+ */
+String Identifier() :
+{
+    final List<String> names = new ArrayList<String>();
+}
+{
+    AddIdentifierSegment(names, null) {
+        return names.get(0);
+    }
+}
+
+/**
+ * Parses a simple identifier as an SqlIdentifier.
+ */
+SqlIdentifier SimpleIdentifier() :
+{
+    final List<String> names = new ArrayList<String>();
+    final List<SqlParserPos> positions = new ArrayList<SqlParserPos>();
+}
+{
+    AddIdentifierSegment(names, positions) {
+        return new SqlIdentifier(names.get(0), positions.get(0));
+    }
+}
+
+/**
+ * Parses a character literal as an SqlIdentifier.
+ * Only valid for column aliases in certain dialects.
+ */
+SqlIdentifier SimpleIdentifierFromStringLiteral() :
+{
+}
+{
+    <QUOTED_STRING> {
+        if (!this.conformance.allowCharLiteralAlias()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.charLiteralAliasNotValid());
+        }
+        final String s = SqlParserUtil.parseString(token.image);
+        return new SqlIdentifier(s, getPos());
+    }
+}
+
+/**
+ * Parses a comma-separated list of simple identifiers.
+ */
+void AddSimpleIdentifiers(List<SqlNode> list) :
+{
+    SqlIdentifier id;
+}
+{
+    id = SimpleIdentifier() {list.add(id);}
+    (
+        <COMMA> id = SimpleIdentifier() {
+            list.add(id);
+        }
+    )*
+}
+
+/**
+  * List of simple identifiers in parentheses. The position extends from the
+  * open parenthesis to the close parenthesis.
+  */
+SqlNodeList ParenthesizedSimpleIdentifierList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    <LPAREN> { s = span(); }
+    AddSimpleIdentifiers(list)
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+
+/** List of simple identifiers in parentheses or one simple identifier.
+ *
+ * <ul>Examples:
+ * <li>{@code DEPTNO}
+ * <li>{@code (EMPNO, DEPTNO)}
+ * </ul>
+ */
+SqlNodeList SimpleIdentifierOrList() :
+{
+    SqlIdentifier id;
+    SqlNodeList list;
+}
+{
+    id = SimpleIdentifier() {
+        return new SqlNodeList(Collections.singletonList(id), id.getParserPosition());
+    }
+|
+    list = ParenthesizedSimpleIdentifierList() {
+        return list;
+    }
+}
+
+<#if (parser.includeCompoundIdentifier!default.parser.includeCompoundIdentifier) >
+/**
+ * Parses a compound identifier.
+ */
+SqlIdentifier CompoundIdentifier() :
+{
+    final List<String> nameList = new ArrayList<String>();
+    final List<SqlParserPos> posList = new ArrayList<SqlParserPos>();
+    boolean star = false;
+}
+{
+    AddIdentifierSegment(nameList, posList)
+    (
+        LOOKAHEAD(2)
+        <DOT>
+        AddIdentifierSegment(nameList, posList)
+    )*
+    (
+        LOOKAHEAD(2)
+        <DOT>
+        <STAR> {
+            star = true;
+            nameList.add("");
+            posList.add(getPos());
+        }
+    )?
+    {
+        SqlParserPos pos = SqlParserPos.sum(posList);
+        if (star) {
+            return SqlIdentifier.star(nameList, pos, posList);
+        }
+        return new SqlIdentifier(nameList, null, pos, posList);
+    }
+}
+
+/**
+ * Parses a compound identifier in the FROM clause.
+ */
+SqlIdentifier CompoundTableIdentifier() :
+{
+    final List<String> nameList = new ArrayList<String>();
+    final List<SqlParserPos> posList = new ArrayList<SqlParserPos>();
+}
+{
+    AddTableIdentifierSegment(nameList, posList)
+    (
+        LOOKAHEAD(2)
+        <DOT>
+        AddTableIdentifierSegment(nameList, posList)
+    )*
+    {
+        SqlParserPos pos = SqlParserPos.sum(posList);
+        return new SqlIdentifier(nameList, null, pos, posList);
+    }
+}
+
+/**
+ * Parses a comma-separated list of compound identifiers.
+ */
+void AddCompoundIdentifierTypes(List<SqlNode> list, List<SqlNode> extendList) :
+{
+}
+{
+    AddCompoundIdentifierType(list, extendList)
+    (<COMMA> AddCompoundIdentifierType(list, extendList))*
+}
+
+/**
+ * List of compound identifiers in parentheses. The position extends from the
+ * open parenthesis to the close parenthesis.
+ */
+Pair<SqlNodeList, SqlNodeList> ParenthesizedCompoundIdentifierList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final List<SqlNode> extendList = new ArrayList<SqlNode>();
+}
+{
+    <LPAREN> { s = span(); }
+    AddCompoundIdentifierTypes(list, extendList)
+    <RPAREN> {
+        return Pair.of(new SqlNodeList(list, s.end(this)), new SqlNodeList(extendList, s.end(this)));
+    }
+}
+<#else>
+  <#include "/@includes/compoundIdentifier.ftl" />
+</#if>
+
+/**
+ * Parses a NEW UDT(...) expression.
+ */
+SqlNode NewSpecification() :
+{
+    final Span s;
+    final SqlNode routineCall;
+}
+{
+    <NEW> { s = span(); }
+    routineCall =
+        NamedRoutineCall(SqlFunctionCategory.USER_DEFINED_CONSTRUCTOR,
+            ExprContext.ACCEPT_SUB_QUERY) {
+        return SqlStdOperatorTable.NEW.createCall(s.end(routineCall), routineCall);
+    }
+}
+
+//TODO: real parse errors.
+int UnsignedIntLiteral() :
+{
+    Token t;
+}
+{
+    t = <UNSIGNED_INTEGER_LITERAL>
+    {
+        try {
+            return Integer.parseInt(t.image);
+        } catch (NumberFormatException ex) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.invalidLiteral(t.image, Integer.class.getCanonicalName()));
+        }
+    }
+}
+
+int IntLiteral() :
+{
+    Token t;
+}
+{
+    (
+        t = <UNSIGNED_INTEGER_LITERAL>
+    |
+        <PLUS> t = <UNSIGNED_INTEGER_LITERAL>
+    )
+    {
+        try {
+            return Integer.parseInt(t.image);
+        } catch (NumberFormatException ex) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.invalidLiteral(t.image, Integer.class.getCanonicalName()));
+        }
+    }
+|
+    <MINUS> t = <UNSIGNED_INTEGER_LITERAL> {
+        try {
+            return -Integer.parseInt(t.image);
+        } catch (NumberFormatException ex) {
+            throw SqlUtil.newContextException(getPos(),
+                RESOURCE.invalidLiteral(t.image, Integer.class.getCanonicalName()));
+        }
+    }
+}
+
+// Type name with optional scale and precision.
+SqlDataTypeSpec DataType() :
+{
+    SqlTypeNameSpec typeName;
+    final Span s;
+}
+{
+    typeName = TypeName() {
+        s = Span.of(typeName.getParserPos());
+    }
+    (
+        typeName = CollectionsTypeName(typeName)
+    )*
+    {
+        return new SqlDataTypeSpec(typeName, s.add(typeName.getParserPos()).pos());
+    }
+}
+
+// Some SQL type names need special handling due to the fact that they have
+// spaces in them but are not quoted.
+SqlTypeNameSpec TypeName() :
+{
+    final SqlTypeNameSpec typeNameSpec;
+    final SqlIdentifier typeName;
+    final Span s = Span.of();
+}
+{
+    (
+<#-- additional types are included here -->
+<#-- put custom data types in front of Calcite core data types -->
+<#list (parser.dataTypeParserMethods!default.parser.dataTypeParserMethods) as method>
+        LOOKAHEAD(2)
+        typeNameSpec = ${method}
+    |
+</#list>
+        LOOKAHEAD(2)
+        typeNameSpec = SqlTypeName(s)
+    |
+        typeNameSpec = RowTypeName()
+    |
+        typeName = CompoundIdentifier() {
+            typeNameSpec = new SqlUserDefinedTypeNameSpec(typeName, s.end(this));
+        }
+    )
+    {
+        return typeNameSpec;
+    }
+}
+
+// Types used for JDBC and ODBC scalar conversion function
+SqlTypeNameSpec SqlTypeName(Span s) :
+{
+    final SqlTypeNameSpec sqlTypeNameSpec;
+}
+{
+    (
+        sqlTypeNameSpec = SqlTypeName1(s)
+    |
+        sqlTypeNameSpec = SqlTypeName2(s)
+    |
+        sqlTypeNameSpec = SqlTypeName3(s)
+    |
+        sqlTypeNameSpec = CharacterTypeName(s)
+    |
+        sqlTypeNameSpec = DateTimeTypeName()
+    )
+    {
+        return sqlTypeNameSpec;
+    }
+}
+
+// Parse sql type name that don't allow any extra specifications except the type name.
+// For extra specification, we mean precision, scale, charSet, etc.
+SqlTypeNameSpec SqlTypeName1(Span s) :
+{
+    final SqlTypeName sqlTypeName;
+}
+{
+    (
+        <GEOMETRY> {
+            if (!this.conformance.allowGeometry()) {
+                throw SqlUtil.newContextException(getPos(), RESOURCE.geometryDisabled());
+            }
+            s.add(this);
+            sqlTypeName = SqlTypeName.GEOMETRY;
+        }
+    |
+        <BOOLEAN> { s.add(this); sqlTypeName = SqlTypeName.BOOLEAN; }
+    |
+        ( <INTEGER> | <INT> ) { s.add(this); sqlTypeName = SqlTypeName.INTEGER; }
+    |
+        <TINYINT> { s.add(this); sqlTypeName = SqlTypeName.TINYINT; }
+    |
+        <SMALLINT> { s.add(this); sqlTypeName = SqlTypeName.SMALLINT; }
+    |
+        <BIGINT> { s.add(this); sqlTypeName = SqlTypeName.BIGINT; }
+    |
+        <REAL> { s.add(this); sqlTypeName = SqlTypeName.REAL; }
+    |
+        <DOUBLE> { s.add(this); }
+        [ <PRECISION> ] { sqlTypeName = SqlTypeName.DOUBLE; }
+    |
+        <FLOAT> { s.add(this); sqlTypeName = SqlTypeName.FLOAT; }
+    )
+    {
+        return new SqlBasicTypeNameSpec(sqlTypeName, s.end(this));
+    }
+}
+
+// Parse sql type name that allows precision specification.
+SqlTypeNameSpec SqlTypeName2(Span s) :
+{
+    final SqlTypeName sqlTypeName;
+    int precision = -1;
+}
+{
+    (
+        <BINARY> { s.add(this); }
+        (
+            <VARYING> { sqlTypeName = SqlTypeName.VARBINARY; }
+        |
+            { sqlTypeName = SqlTypeName.BINARY; }
+        )
+    |
+        <VARBINARY> { s.add(this); sqlTypeName = SqlTypeName.VARBINARY; }
+    )
+    precision = PrecisionOpt()
+    {
+        return new SqlBasicTypeNameSpec(sqlTypeName, precision, s.end(this));
+    }
+}
+
+// Parse sql type name that allows precision and scale specifications.
+SqlTypeNameSpec SqlTypeName3(Span s) :
+{
+    final SqlTypeName sqlTypeName;
+    int precision = -1;
+    int scale = -1;
+}
+{
+    (
+        (<DECIMAL> | <DEC> | <NUMERIC>) { s.add(this); sqlTypeName = SqlTypeName.DECIMAL; }
+    |
+        <ANY> { s.add(this); sqlTypeName = SqlTypeName.ANY; }
+    )
+    [
+        <LPAREN>
+        precision = UnsignedIntLiteral()
+        [
+            <COMMA>
+            scale = UnsignedIntLiteral()
+        ]
+        <RPAREN>
+    ]
+    {
+        return new SqlBasicTypeNameSpec(sqlTypeName, precision, scale, s.end(this));
+    }
+}
+
+// Types used for for JDBC and ODBC scalar conversion function
+SqlJdbcDataTypeName JdbcOdbcDataTypeName() :
+{
+}
+{
+    (<SQL_CHAR> | <CHAR>) { return SqlJdbcDataTypeName.SQL_CHAR; }
+|   (<SQL_VARCHAR> | <VARCHAR>) { return SqlJdbcDataTypeName.SQL_VARCHAR; }
+|   (<SQL_DATE> | <DATE>) { return SqlJdbcDataTypeName.SQL_DATE; }
+|   (<SQL_TIME> | <TIME>) { return SqlJdbcDataTypeName.SQL_TIME; }
+|   (<SQL_TIMESTAMP> | <TIMESTAMP>) { return SqlJdbcDataTypeName.SQL_TIMESTAMP; }
+|   (<SQL_DECIMAL> | <DECIMAL>) { return SqlJdbcDataTypeName.SQL_DECIMAL; }
+|   (<SQL_NUMERIC> | <NUMERIC>) { return SqlJdbcDataTypeName.SQL_NUMERIC; }
+|   (<SQL_BOOLEAN> | <BOOLEAN>) { return SqlJdbcDataTypeName.SQL_BOOLEAN; }
+|   (<SQL_INTEGER> | <INTEGER>) { return SqlJdbcDataTypeName.SQL_INTEGER; }
+|   (<SQL_BINARY> | <BINARY>) { return SqlJdbcDataTypeName.SQL_BINARY; }
+|   (<SQL_VARBINARY> | <VARBINARY>) { return SqlJdbcDataTypeName.SQL_VARBINARY; }
+|   (<SQL_TINYINT> | <TINYINT>) { return SqlJdbcDataTypeName.SQL_TINYINT; }
+|   (<SQL_SMALLINT> | <SMALLINT>) { return SqlJdbcDataTypeName.SQL_SMALLINT; }
+|   (<SQL_BIGINT> | <BIGINT>) { return SqlJdbcDataTypeName.SQL_BIGINT; }
+|   (<SQL_REAL>| <REAL>) { return SqlJdbcDataTypeName.SQL_REAL; }
+|   (<SQL_DOUBLE> | <DOUBLE>) { return SqlJdbcDataTypeName.SQL_DOUBLE; }
+|   (<SQL_FLOAT> | <FLOAT>) { return SqlJdbcDataTypeName.SQL_FLOAT; }
+|   <SQL_INTERVAL_YEAR> { return SqlJdbcDataTypeName.SQL_INTERVAL_YEAR; }
+|   <SQL_INTERVAL_YEAR_TO_MONTH> { return SqlJdbcDataTypeName.SQL_INTERVAL_YEAR_TO_MONTH; }
+|   <SQL_INTERVAL_MONTH> { return SqlJdbcDataTypeName.SQL_INTERVAL_MONTH; }
+|   <SQL_INTERVAL_DAY> { return SqlJdbcDataTypeName.SQL_INTERVAL_DAY; }
+|   <SQL_INTERVAL_DAY_TO_HOUR> { return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_HOUR; }
+|   <SQL_INTERVAL_DAY_TO_MINUTE> { return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_MINUTE; }
+|   <SQL_INTERVAL_DAY_TO_SECOND> { return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_SECOND; }
+|   <SQL_INTERVAL_HOUR> { return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR; }
+|   <SQL_INTERVAL_HOUR_TO_MINUTE> { return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR_TO_MINUTE; }
+|   <SQL_INTERVAL_HOUR_TO_SECOND> { return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR_TO_SECOND; }
+|   <SQL_INTERVAL_MINUTE> { return SqlJdbcDataTypeName.SQL_INTERVAL_MINUTE; }
+|   <SQL_INTERVAL_MINUTE_TO_SECOND> { return SqlJdbcDataTypeName.SQL_INTERVAL_MINUTE_TO_SECOND; }
+|   <SQL_INTERVAL_SECOND> { return SqlJdbcDataTypeName.SQL_INTERVAL_SECOND; }
+}
+
+SqlLiteral JdbcOdbcDataType() :
+{
+    SqlJdbcDataTypeName typeName;
+}
+{
+    typeName = JdbcOdbcDataTypeName() {
+        return typeName.symbol(getPos());
+    }
+}
+
+/**
+* Parse a collection type name, the input element type name may
+* also be a collection type.
+*/
+SqlTypeNameSpec CollectionsTypeName(SqlTypeNameSpec elementTypeName) :
+{
+    final SqlTypeName collectionTypeName;
+}
+{
+    (
+        <MULTISET> { collectionTypeName = SqlTypeName.MULTISET; }
+    |
+        <ARRAY> { collectionTypeName = SqlTypeName.ARRAY; }
+    )
+    {
+        return new SqlCollectionTypeNameSpec(elementTypeName,
+                collectionTypeName, getPos());
+    }
+}
+
+/**
+* Parse a nullable option, default is true.
+*/
+boolean NullableOptDefaultTrue() :
+{
+}
+{
+    <NULL> { return true; }
+|
+    <NOT> <NULL> { return false; }
+|
+    { return true; }
+}
+
+/**
+* Parse a nullable option, default is false.
+*/
+boolean NullableOptDefaultFalse() :
+{
+}
+{
+    <NULL> { return true; }
+|
+    <NOT> <NULL> { return false; }
+|
+    { return false; }
+}
+
+/** Parses NOT NULL and returns false, or parses nothing and returns true. */
+boolean NotNullOpt() :
+{
+}
+{
+    <NOT> <NULL> { return false; }
+|
+    { return true; }
+}
+
+/**
+* Parse a "name1 type1 [NULL | NOT NULL], name2 type2 [NULL | NOT NULL] ..." list,
+* the field type default is not nullable.
+*/
+void AddFieldNameTypes(List<SqlIdentifier> fieldNames,
+    List<SqlDataTypeSpec> fieldTypes) :
+{
+}
+{
+    AddFieldNameType(fieldNames, fieldTypes)
+    ( <COMMA> AddFieldNameType(fieldNames, fieldTypes) )*
+}
+
+void AddFieldNameType(List<SqlIdentifier> fieldNames,
+    List<SqlDataTypeSpec> fieldTypes) :
+{
+    final SqlIdentifier fName;
+    final SqlDataTypeSpec fType;
+    final boolean nullable;
+}
+{
+    fName = SimpleIdentifier()
+    fType = DataType()
+    nullable = NullableOptDefaultFalse()
+    {
+        fieldNames.add(fName);
+        fieldTypes.add(fType.withNullable(nullable, getPos()));
+    }
+}
+
+/**
+* Parse Row type with format: Row(name1 type1, name2 type2).
+* Every field type can have suffix of `NULL` or `NOT NULL` to indicate if this type is nullable.
+* i.e. Row(f0 int not null, f1 varchar null).
+*/
+SqlTypeNameSpec RowTypeName() :
+{
+    List<SqlIdentifier> fieldNames = new ArrayList<SqlIdentifier>();
+    List<SqlDataTypeSpec> fieldTypes = new ArrayList<SqlDataTypeSpec>();
+}
+{
+    <ROW>
+    <LPAREN> AddFieldNameTypes(fieldNames, fieldTypes) <RPAREN>
+    {
+        return new SqlRowTypeNameSpec(getPos(), fieldNames, fieldTypes);
+    }
+}
+
+/**
+* Parse character types: char, varchar.
+*/
+SqlTypeNameSpec CharacterTypeName(Span s) :
+{
+    int precision = -1;
+    final SqlTypeName sqlTypeName;
+    String charSetName = null;
+}
+{
+    (
+        (<CHARACTER> | <CHAR>) { s.add(this); }
+        (
+            <VARYING> { sqlTypeName = SqlTypeName.VARCHAR; }
+        |
+            { sqlTypeName = SqlTypeName.CHAR; }
+        )
+    |
+        <VARCHAR> { s.add(this); sqlTypeName = SqlTypeName.VARCHAR; }
+    )
+    precision = PrecisionOpt()
+    [
+        <CHARACTER> <SET>
+        charSetName = Identifier()
+    ]
+    {
+        return new SqlBasicTypeNameSpec(sqlTypeName, precision, charSetName, s.end(this));
+    }
+}
+
+/**
+* Parse datetime types: date, time, timestamp.
+*/
+SqlTypeNameSpec DateTimeTypeName() :
+{
+    int precision = -1;
+    SqlTypeName typeName;
+    boolean withLocalTimeZone = false;
+    final Span s;
+}
+{
+    <DATE> {
+        typeName = SqlTypeName.DATE;
+        return new SqlBasicTypeNameSpec(typeName, getPos());
+    }
+|
+    LOOKAHEAD(2)
+    <TIME> { s = span(); }
+    precision = PrecisionOpt()
+    withLocalTimeZone = TimeZoneOpt()
+    {
+        if (withLocalTimeZone) {
+            typeName = SqlTypeName.TIME_WITH_LOCAL_TIME_ZONE;
+        } else {
+            typeName = SqlTypeName.TIME;
+        }
+        return new SqlBasicTypeNameSpec(typeName, precision, s.end(this));
+    }
+|
+    <TIMESTAMP> { s = span(); }
+    precision = PrecisionOpt()
+    withLocalTimeZone = TimeZoneOpt()
+    {
+        if (withLocalTimeZone) {
+            typeName = SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE;
+        } else {
+            typeName = SqlTypeName.TIMESTAMP;
+        }
+        return new SqlBasicTypeNameSpec(typeName, precision, s.end(this));
+    }
+}
+
+// Parse an optional data type precision, default is -1.
+int PrecisionOpt() :
+{
+    int precision = -1;
+}
+{
+    <LPAREN>
+    precision = UnsignedIntLiteral()
+    <RPAREN>
+    { return precision; }
+|
+    { return -1; }
+}
+
+/**
+* Parse a time zone suffix for DateTime types. According to SQL-2011,
+* "with time zone" and "without time zone" belong to standard SQL but we
+* only implement the "without time zone".
+*
+* <p>We also support "with local time zone".
+*
+* @return true if this is "with local time zone".
+*/
+boolean TimeZoneOpt() :
+{
+}
+{
+    LOOKAHEAD(3)
+    <WITHOUT> <TIME> <ZONE> { return false; }
+|
+    <WITH> <LOCAL> <TIME> <ZONE> { return true; }
+|
+    { return false; }
+}
+
+/**
+ * Parses a CURSOR(query) expression.  The parser allows these
+ * anywhere, but the validator restricts them to appear only as
+ * arguments to table functions.
+ */
+SqlNode CursorExpression(ExprContext exprContext) :
+{
+    final SqlNode e;
+    final Span s;
+}
+{
+    <CURSOR> {
+        s = span();
+        if (exprContext != ExprContext.ACCEPT_ALL
+                && exprContext != ExprContext.ACCEPT_CURSOR) {
+            throw SqlUtil.newContextException(s.end(this),
+                RESOURCE.illegalCursorExpression());
+        }
+    }
+    e = Expression(ExprContext.ACCEPT_QUERY) {
+        return SqlStdOperatorTable.CURSOR.createCall(s.end(e), e);
+    }
+}
+
+/**
+ * Parses a call to a builtin function with special syntax.
+ */
+SqlNode BuiltinFunctionCall() :
+{
+    final SqlIdentifier name;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+    final Span s;
+    SqlDataTypeSpec dt;
+    final SqlIntervalQualifier unit;
+    final SqlNode node;
+}
+{
+    //~ FUNCTIONS WITH SPECIAL SYNTAX ---------------------------------------
+    (
+        <CAST> { s = span(); }
+        <LPAREN> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        <AS>
+        (
+            dt = DataType() { args.add(dt); }
+        |
+            <INTERVAL> e = IntervalQualifier() { args.add(e); }
+        )
+        <RPAREN> {
+            return SqlStdOperatorTable.CAST.createCall(s.end(this), args);
+        }
+    |
+        <EXTRACT> { s = span(); }
+        <LPAREN> unit = TimeUnitOrName() {
+            args.add(unit);
+        }
+        <FROM>
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        <RPAREN> {
+            return SqlStdOperatorTable.EXTRACT.createCall(s.end(this), args);
+        }
+    |
+        <POSITION> { s = span(); }
+        <LPAREN>
+        // FIXME jvs 31-Aug-2006:  FRG-192:  This should be
+        // Expression(ExprContext.ACCEPT_SUB_QUERY), but that doesn't work
+        // because it matches the other kind of IN.
+        e = AtomicRowExpression() { args.add(e); }
+        <IN>
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        [ <FROM> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY) ]
+        <RPAREN> {
+            return SqlStdOperatorTable.POSITION.createCall(s.end(this), args);
+        }
+    |
+        <CONVERT> { s = span(); }
+        <LPAREN>
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        <USING> name = SimpleIdentifier() { args.add(name); }
+        <RPAREN> {
+            return SqlStdOperatorTable.CONVERT.createCall(s.end(this), args);
+        }
+    |
+        <TRANSLATE> { s = span(); }
+        <LPAREN>
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        (
+            <USING> name = SimpleIdentifier() { args.add(name); }
+            <RPAREN> {
+                return SqlStdOperatorTable.TRANSLATE.createCall(s.end(this),
+                    args);
+            }
+        |
+            ( <COMMA> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY) )*
+            <RPAREN> {
+                return SqlLibraryOperators.TRANSLATE3.createCall(s.end(this),
+                    args);
+            }
+        )
+    |
+        <OVERLAY> { s = span(); }
+        <LPAREN> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        <PLACING> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        <FROM> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        [ <FOR> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY) ]
+        <RPAREN> {
+            return SqlStdOperatorTable.OVERLAY.createCall(s.end(this), args);
+        }
+    |
+        <FLOOR> { s = span(); }
+        e = FloorCeilOptions(s, true) {
+            return e;
+        }
+    |
+        ( <CEIL> | <CEILING>) { s = span(); }
+        e = FloorCeilOptions(s, false) {
+            return e;
+        }
+    |
+        <SUBSTRING> { s = span(); }
+        <LPAREN>
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        ( <FROM> | <COMMA>)
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        [
+            (<FOR> | <COMMA>)
+            AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+        ]
+        <RPAREN> {
+            return SqlStdOperatorTable.SUBSTRING.createCall(
+                s.end(this), args);
+        }
+    |
+        <TRIM> {
+            SqlLiteral flag = null;
+            SqlNode trimChars = null;
+            s = span();
+        }
+        <LPAREN>
+        [
+            LOOKAHEAD(2)
+            [
+                <BOTH> {
+                    s.add(this);
+                    flag = SqlTrimFunction.Flag.BOTH.symbol(getPos());
+                }
+            |
+                <TRAILING> {
+                    s.add(this);
+                    flag = SqlTrimFunction.Flag.TRAILING.symbol(getPos());
+                }
+            |
+                <LEADING> {
+                    s.add(this);
+                    flag = SqlTrimFunction.Flag.LEADING.symbol(getPos());
+                }
+            ]
+            [ trimChars = Expression(ExprContext.ACCEPT_SUB_QUERY) ]
+            (
+                <FROM> {
+                    if (null == flag && null == trimChars) {
+                        throw SqlUtil.newContextException(getPos(),
+                            RESOURCE.illegalFromEmpty());
+                    }
+                }
+            |
+                <RPAREN> {
+                    // This is to handle the case of TRIM(x)
+                    // (FRG-191).
+                    if (flag == null) {
+                        flag = SqlTrimFunction.Flag.BOTH.symbol(SqlParserPos.ZERO);
+                    }
+                    args.add(flag);
+                    args.add(null); // no trim chars
+                    args.add(trimChars); // reinterpret trimChars as source
+                    return SqlStdOperatorTable.TRIM.createCall(s.end(this),
+                        args);
+                }
+            )
+        ]
+        e = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+            if (flag == null) {
+                flag = SqlTrimFunction.Flag.BOTH.symbol(SqlParserPos.ZERO);
+            }
+            args.add(flag);
+            args.add(trimChars);
+            args.add(e);
+        }
+        <RPAREN> {
+            return SqlStdOperatorTable.TRIM.createCall(s.end(this), args);
+        }
+    |
+        node = DateTimeConstructorCall() { return node; }
+    |
+        node = DateTruncFunctionCall() { return node; }
+    |
+        node = TimestampAddFunctionCall() { return node; }
+    |
+        node = TimestampDiffFunctionCall() { return node; }
+    |
+        node = TimestampDiff3FunctionCall() { return node; }
+    |
+        node = TimestampTruncFunctionCall() { return node; }
+    |
+        node = TimeDiffFunctionCall() { return node; }
+    |
+        node = TimeTruncFunctionCall() { return node; }
+    |
+<#list (parser.builtinFunctionCallMethods!default.parser.builtinFunctionCallMethods) as method>
+        node = ${method} { return node; }
+    |
+</#list>
+        node = MatchRecognizeFunctionCall() { return node; }
+    |
+        node = JsonExistsFunctionCall() { return node; }
+    |
+        node = JsonValueFunctionCall() { return node; }
+    |
+        node = JsonQueryFunctionCall() { return node; }
+    |
+        node = JsonObjectFunctionCall() { return node; }
+    |
+        node = JsonObjectAggFunctionCall() { return node; }
+    |
+        node = JsonArrayFunctionCall() { return node; }
+    |
+        node = JsonArrayAggFunctionCall() { return node; }
+    |
+        node = GroupByWindowingCall() { return node; }
+    )
+}
+
+SqlJsonEncoding JsonRepresentation() :
+{
+}
+{
+    <JSON>
+    [
+        // Encoding is currently ignored.
+        LOOKAHEAD(2) <ENCODING>
+        (
+            <UTF8> { return SqlJsonEncoding.UTF8; }
+        |
+            <UTF16> { return SqlJsonEncoding.UTF16; }
+        |
+            <UTF32> { return SqlJsonEncoding.UTF32; }
+        )
+    ]
+    {
+        return SqlJsonEncoding.UTF8;
+    }
+}
+
+void JsonInputClause() :
+{
+}
+{
+    <FORMAT> JsonRepresentation()
+}
+
+SqlDataTypeSpec JsonReturningClause() :
+{
+    SqlDataTypeSpec dt;
+}
+{
+    <RETURNING> dt = DataType() { return dt; }
+}
+
+SqlDataTypeSpec JsonOutputClause() :
+{
+    SqlDataTypeSpec dataType;
+}
+{
+    dataType = JsonReturningClause()
+    [
+        <FORMAT> JsonRepresentation()
+    ]
+    {
+        return dataType;
+    }
+}
+
+SqlNode JsonPathSpec() :
+{
+    SqlNode e;
+}
+{
+    e = StringLiteral() {
+        return e;
+    }
+}
+
+List<SqlNode> JsonApiCommonSyntax() :
+{
+    SqlNode e;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+}
+{
+    AddExpression(args, ExprContext.ACCEPT_NON_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_NON_QUERY)
+    [
+        // We currently don't support JSON passing clause, leave the java code blocks no-op
+        <PASSING> e = Expression(ExprContext.ACCEPT_NON_QUERY) {
+            // no-op
+        }
+        <AS> e = SimpleIdentifier() {
+            // no-op
+        }
+        (
+            <COMMA>
+            e = Expression(ExprContext.ACCEPT_NON_QUERY) {
+                // no-op
+            }
+            <AS> e = SimpleIdentifier() {
+                // no-op
+            }
+        )*
+    ]
+    {
+        return args;
+    }
+}
+
+SqlJsonExistsErrorBehavior JsonExistsErrorBehavior() :
+{
+
+}
+{
+    <TRUE> { return SqlJsonExistsErrorBehavior.TRUE; }
+    |
+    <FALSE> { return SqlJsonExistsErrorBehavior.FALSE; }
+    |
+    <UNKNOWN> { return SqlJsonExistsErrorBehavior.UNKNOWN; }
+    |
+    <ERROR> { return SqlJsonExistsErrorBehavior.ERROR; }
+}
+
+SqlCall JsonExistsFunctionCall() :
+{
+    List<SqlNode> args = new ArrayList<SqlNode>();
+    List<SqlNode> commonSyntax;
+    final Span span;
+    SqlJsonExistsErrorBehavior errorBehavior;
+}
+{
+    <JSON_EXISTS> { span = span(); }
+    <LPAREN> commonSyntax = JsonApiCommonSyntax() {
+        args.addAll(commonSyntax);
+    }
+    [
+        errorBehavior = JsonExistsErrorBehavior() { args.add(errorBehavior.symbol(getPos())); }
+        <ON> <ERROR>
+    ]
+    <RPAREN> {
+        return SqlStdOperatorTable.JSON_EXISTS.createCall(span.end(this), args);
+    }
+}
+
+List<SqlNode> JsonValueEmptyOrErrorBehavior() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    (
+        <ERROR> {
+            list.add(SqlJsonValueEmptyOrErrorBehavior.ERROR.symbol(getPos()));
+        }
+    |
+        <NULL> {
+            list.add(SqlJsonValueEmptyOrErrorBehavior.NULL.symbol(getPos()));
+        }
+    |
+        <DEFAULT_> {
+            list.add(SqlJsonValueEmptyOrErrorBehavior.DEFAULT.symbol(getPos()));
+        }
+        AddExpression(list, ExprContext.ACCEPT_NON_QUERY)
+    )
+    <ON>
+    (
+        <EMPTY> {
+            list.add(SqlJsonEmptyOrError.EMPTY.symbol(getPos()));
+        }
+    |
+        <ERROR> {
+            list.add(SqlJsonEmptyOrError.ERROR.symbol(getPos()));
+        }
+    )
+    { return list; }
+}
+
+SqlCall JsonValueFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>(7);
+    SqlNode e;
+    List<SqlNode> commonSyntax;
+    final Span span;
+    List<SqlNode> behavior;
+}
+{
+    <JSON_VALUE> { span = span(); }
+    <LPAREN> commonSyntax = JsonApiCommonSyntax() {
+        args.addAll(commonSyntax);
+    }
+    [
+        e = JsonReturningClause() {
+            args.add(SqlJsonValueReturning.RETURNING.symbol(getPos()));
+            args.add(e);
+        }
+    ]
+    (
+        behavior = JsonValueEmptyOrErrorBehavior() {
+            args.addAll(behavior);
+        }
+    )*
+    <RPAREN> {
+        return SqlStdOperatorTable.JSON_VALUE.createCall(span.end(this), args);
+    }
+}
+
+List<SqlNode> JsonQueryEmptyOrErrorBehavior() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+}
+{
+    (
+        <ERROR> {
+            list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.ERROR, getPos()));
+        }
+    |
+        <NULL> {
+            list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.NULL, getPos()));
+        }
+    |
+        LOOKAHEAD(2)
+        <EMPTY> <ARRAY> {
+            list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.EMPTY_ARRAY, getPos()));
+        }
+    |
+        <EMPTY> <OBJECT> {
+            list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.EMPTY_OBJECT, getPos()));
+        }
+    )
+    <ON>
+    (
+        <EMPTY> {
+            list.add(SqlLiteral.createSymbol(SqlJsonEmptyOrError.EMPTY, getPos()));
+        }
+    |
+        <ERROR> {
+            list.add(SqlLiteral.createSymbol(SqlJsonEmptyOrError.ERROR, getPos()));
+        }
+    )
+    { return list; }
+}
+
+SqlNode JsonQueryWrapperBehavior() :
+{
+}
+{
+    <WITHOUT> [<ARRAY>] {
+        return SqlLiteral.createSymbol(SqlJsonQueryWrapperBehavior.WITHOUT_ARRAY, getPos());
+    }
+|
+    LOOKAHEAD(2)
+    <WITH> <CONDITIONAL> [<ARRAY>] {
+        return SqlLiteral.createSymbol(SqlJsonQueryWrapperBehavior.WITH_CONDITIONAL_ARRAY, getPos());
+    }
+|
+    <WITH> [<UNCONDITIONAL>] [<ARRAY>] {
+        return SqlLiteral.createSymbol(SqlJsonQueryWrapperBehavior.WITH_UNCONDITIONAL_ARRAY, getPos());
+    }
+}
+
+SqlCall JsonQueryFunctionCall() :
+{
+    final SqlNode[] args = new SqlNode[5];
+    SqlNode e;
+    List<SqlNode> commonSyntax;
+    final Span span;
+    List<SqlNode> behavior;
+}
+{
+    <JSON_QUERY> { span = span(); }
+    <LPAREN> commonSyntax = JsonApiCommonSyntax() {
+        args[0] = commonSyntax.get(0);
+        args[1] = commonSyntax.get(1);
+    }
+    [
+        e = JsonQueryWrapperBehavior() <WRAPPER> {
+            args[2] = e;
+        }
+    ]
+    (
+        behavior = JsonQueryEmptyOrErrorBehavior() {
+            final SqlJsonEmptyOrError symbol =
+                ((SqlLiteral) behavior.get(1)).getValueAs(SqlJsonEmptyOrError.class);
+            switch (symbol) {
+            case EMPTY:
+                args[3] = behavior.get(0);
+                break;
+            case ERROR:
+                args[4] = behavior.get(0);
+                break;
+            }
+        }
+    )*
+    <RPAREN> {
+        return SqlStdOperatorTable.JSON_QUERY.createCall(span.end(this), args);
+    }
+}
+
+SqlNode JsonName() :
+{
+    final SqlNode e;
+}
+{
+     e = Expression(ExprContext.ACCEPT_NON_QUERY) {
+        return e;
+     }
+}
+
+List<SqlNode> JsonNameAndValue() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final SqlNode e;
+    boolean kvMode = false;
+}
+{
+    [
+        LOOKAHEAD(2, <KEY> JsonName())
+        <KEY> { kvMode = true; }
+    ]
+    e = JsonName() {
+        list.add(e);
+    }
+    (
+        <VALUE>
+    |
+        <COLON> {
+            if (kvMode) {
+                throw SqlUtil.newContextException(getPos(), RESOURCE.illegalColon());
+            }
+        }
+    )
+    AddExpression(list, ExprContext.ACCEPT_NON_QUERY)
+    {
+        return list;
+    }
+}
+
+SqlNode JsonConstructorNullClause() :
+{
+}
+{
+    <NULL> <ON> <NULL> {
+        return SqlLiteral.createSymbol(SqlJsonConstructorNullClause.NULL_ON_NULL, getPos());
+    }
+|
+    <ABSENT> <ON> <NULL> {
+        return SqlLiteral.createSymbol(SqlJsonConstructorNullClause.ABSENT_ON_NULL, getPos());
+    }
+}
+
+SqlCall JsonObjectFunctionCall() :
+{
+    final List<SqlNode> nvArgs = new ArrayList<SqlNode>();
+    final SqlNode[] otherArgs = new SqlNode[1];
+    SqlNode e;
+    List<SqlNode> list;
+    final Span span;
+}
+{
+    <JSON_OBJECT> { span = span(); }
+    <LPAREN> [
+        LOOKAHEAD(2)
+        list = JsonNameAndValue() {
+            nvArgs.addAll(list);
+        }
+        (
+            <COMMA>
+            list = JsonNameAndValue() {
+                nvArgs.addAll(list);
+            }
+        )*
+    ]
+    [
+        e = JsonConstructorNullClause() {
+            otherArgs[0] = e;
+        }
+    ]
+    <RPAREN> {
+        final List<SqlNode> args = new ArrayList();
+        args.addAll(Arrays.asList(otherArgs));
+        args.addAll(nvArgs);
+        return SqlStdOperatorTable.JSON_OBJECT.createCall(span.end(this), args);
+    }
+}
+
+SqlCall JsonObjectAggFunctionCall() :
+{
+    final SqlNode[] args = new SqlNode[2];
+    List<SqlNode> list;
+    final Span span;
+    SqlJsonConstructorNullClause nullClause =
+        SqlJsonConstructorNullClause.NULL_ON_NULL;
+    final SqlNode e;
+}
+{
+    <JSON_OBJECTAGG> { span = span(); }
+    <LPAREN> list = JsonNameAndValue() {
+        args[0] = list.get(0);
+        args[1] = list.get(1);
+    }
+    [
+        e = JsonConstructorNullClause() {
+            nullClause = (SqlJsonConstructorNullClause) ((SqlLiteral) e).getValue();
+        }
+    ]
+    <RPAREN> {
+        return SqlStdOperatorTable.JSON_OBJECTAGG.with(nullClause)
+            .createCall(span.end(this), args);
+    }
+}
+
+SqlCall JsonArrayFunctionCall() :
+{
+    final List<SqlNode> elements = new ArrayList<SqlNode>();
+    final SqlNode[] otherArgs = new SqlNode[1];
+    SqlNode e;
+    final Span span;
+}
+{
+    <JSON_ARRAY> { span = span(); }
+    <LPAREN> [
+        LOOKAHEAD(2)
+        AddExpression(elements, ExprContext.ACCEPT_NON_QUERY)
+        ( <COMMA> AddExpression(elements, ExprContext.ACCEPT_NON_QUERY) )*
+    ]
+    [
+        e = JsonConstructorNullClause() {
+            otherArgs[0] = e;
+        }
+    ]
+    <RPAREN> {
+        final List<SqlNode> args = new ArrayList();
+        args.addAll(Arrays.asList(otherArgs));
+        args.addAll(elements);
+        return SqlStdOperatorTable.JSON_ARRAY.createCall(span.end(this), args);
+    }
+}
+
+SqlNodeList JsonArrayAggOrderByClause() :
+{
+    final SqlNodeList orderList;
+}
+{
+    orderList = OrderBy(true)
+    { return orderList; }
+}
+
+SqlCall JsonArrayAggFunctionCall() :
+{
+    final SqlNode valueExpr;
+    final SqlNodeList orderList;
+    final Span span;
+    final SqlJsonConstructorNullClause nullClause;
+    SqlNode e;
+    final SqlNode aggCall;
+}
+{
+    <JSON_ARRAYAGG> { span = span(); }
+    <LPAREN> e = Expression(ExprContext.ACCEPT_NON_QUERY) {
+        valueExpr = e;
+    }
+    ( orderList = JsonArrayAggOrderByClause() | { orderList = null; } )
+    (
+        e = JsonConstructorNullClause() {
+            nullClause = (SqlJsonConstructorNullClause) ((SqlLiteral) e).getValue();
+        }
+    |   { nullClause = SqlJsonConstructorNullClause.ABSENT_ON_NULL; }
+    )
+    <RPAREN>
+    {
+        aggCall = SqlStdOperatorTable.JSON_ARRAYAGG.with(nullClause)
+            .createCall(span.end(this), valueExpr, orderList);
+    }
+    [
+        e = withinGroup(aggCall) {
+            if (orderList != null) {
+                throw SqlUtil.newContextException(span.pos().plus(e.getParserPosition()),
+                    RESOURCE.ambiguousSortOrderInJsonArrayAggFunc());
+            }
+            return (SqlCall) e;
+        }
+    ]
+    {
+        if (orderList == null) {
+            return SqlStdOperatorTable.JSON_ARRAYAGG.with(nullClause)
+                .createCall(span.end(this), valueExpr);
+        }
+        return SqlStdOperatorTable.JSON_ARRAYAGG.with(nullClause)
+            .createCall(span.end(this), valueExpr, orderList);
+    }
+}
+
+/**
+ * Parses a call to TIMESTAMPADD.
+ */
+SqlCall TimestampAddFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIMESTAMPADD> { s = span(); }
+    <LPAREN>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        return SqlStdOperatorTable.TIMESTAMP_ADD.createCall(
+            s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to TIMESTAMPDIFF.
+ */
+SqlCall TimestampDiffFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIMESTAMPDIFF> { s = span(); }
+    <LPAREN>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        return SqlStdOperatorTable.TIMESTAMP_DIFF.createCall(
+            s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to BigQuery's TIMESTAMP_DIFF.
+ *
+ * <p>The difference between TIMESTAMPDIFF and TIMESTAMP_DIFF is the ordering of
+ * the parameters and the arrangement of the subtraction.
+ * TIMESTAMPDIFF uses (unit, timestamp1, timestamp2) with (t2 - t1), while
+ * TIMESTAMP_DIFF uses (timestamp1, timestamp2, unit) with (t1 - t2).
+ */
+SqlCall TimestampDiff3FunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIMESTAMP_DIFF> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <RPAREN> {
+        return SqlLibraryOperators.TIMESTAMP_DIFF3.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to DATE_TRUNC.
+ */
+SqlCall DateTruncFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <DATE_TRUNC> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    // A choice of arguments allows us to support both
+    // the BigQuery variant, e.g. "DATE_TRUNC(d, YEAR)",
+    // and the Redshift variant, e.g. "DATE_TRUNC('year', DATE '2008-09-08')".
+    (
+        LOOKAHEAD(2)
+        unit = TimeUnit() { args.add(unit); }
+    |
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    )
+    <RPAREN> {
+        return SqlLibraryOperators.DATE_TRUNC.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to TIMESTAMP_TRUNC.
+ */
+SqlCall TimestampTruncFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIMESTAMP_TRUNC> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <RPAREN> {
+        return SqlLibraryOperators.TIMESTAMP_TRUNC.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to BigQuery's TIME_DIFF.
+ */
+SqlCall TimeDiffFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIME_DIFF> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <RPAREN> {
+        return SqlLibraryOperators.TIME_DIFF.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to TIME_TRUNC.
+ */
+SqlCall TimeTruncFunctionCall() :
+{
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final Span s;
+    final SqlIntervalQualifier unit;
+}
+{
+    <TIME_TRUNC> { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    <COMMA>
+    unit = TimeUnitOrName() { args.add(unit); }
+    <RPAREN> {
+        return SqlLibraryOperators.TIME_TRUNC.createCall(s.end(this), args);
+    }
+}
+
+/**
+ * Parses a call to a grouping function inside the GROUP BY clause,
+ * for example {@code TUMBLE(rowtime, INTERVAL '1' MINUTE)}.
+ */
+SqlCall GroupByWindowingCall() :
+{
+    final Span s;
+    final List<SqlNode> args;
+    final SqlOperator op;
+}
+{
+    (
+        <TUMBLE> { op = SqlStdOperatorTable.TUMBLE_OLD; }
+    |
+        <HOP> { op = SqlStdOperatorTable.HOP_OLD; }
+    |
+        <SESSION> { op = SqlStdOperatorTable.SESSION_OLD; }
+    )
+    { s = span(); }
+    args = UnquantifiedFunctionParameterList(ExprContext.ACCEPT_SUB_QUERY) {
+        return op.createCall(s.end(this), args);
+    }
+}
+
+SqlCall MatchRecognizeFunctionCall() :
+{
+    final SqlCall func;
+    final Span s;
+}
+{
+    (
+        <CLASSIFIER> { s = span(); } <LPAREN> <RPAREN> {
+            func = SqlStdOperatorTable.CLASSIFIER.createCall(s.end(this));
+        }
+    |
+        <MATCH_NUMBER> { s = span(); } <LPAREN> <RPAREN> {
+            func = SqlStdOperatorTable.MATCH_NUMBER.createCall(s.end(this));
+        }
+    |
+        LOOKAHEAD(3)
+        func = MatchRecognizeNavigationLogical()
+    |
+        LOOKAHEAD(2)
+        func = MatchRecognizeNavigationPhysical()
+    |
+        func = MatchRecognizeCallWithModifier()
+    )
+    { return func; }
+}
+
+SqlCall MatchRecognizeCallWithModifier() :
+{
+    final Span s;
+    final SqlOperator runningOp;
+    final SqlNode func;
+}
+{
+    (
+        <RUNNING> { runningOp = SqlStdOperatorTable.RUNNING; }
+    |
+        <FINAL> { runningOp = SqlStdOperatorTable.FINAL; }
+    )
+    { s = span(); }
+    func = NamedFunctionCall() {
+        return runningOp.createCall(s.end(func), func);
+    }
+}
+
+SqlCall MatchRecognizeNavigationLogical() :
+{
+    final Span s = Span.of();
+    SqlCall func;
+    final SqlOperator funcOp;
+    final SqlOperator runningOp;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+}
+{
+    (
+        <RUNNING> { runningOp = SqlStdOperatorTable.RUNNING; s.add(this); }
+    |
+        <FINAL> { runningOp = SqlStdOperatorTable.FINAL; s.add(this); }
+    |   { runningOp = null; }
+    )
+    (
+        <FIRST> { funcOp = SqlStdOperatorTable.FIRST; }
+    |
+        <LAST> { funcOp = SqlStdOperatorTable.LAST; }
+    )
+    { s.add(this); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <COMMA> e = NumericLiteral() { args.add(e); }
+    |
+        { args.add(LITERAL_ZERO); }
+    )
+    <RPAREN> {
+        func = funcOp.createCall(s.end(this), args);
+        if (runningOp != null) {
+            return runningOp.createCall(s.end(this), func);
+        } else {
+            return func;
+        }
+    }
+}
+
+SqlCall MatchRecognizeNavigationPhysical() :
+{
+    final Span s;
+    final SqlOperator funcOp;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+}
+{
+    (
+        <PREV> { funcOp = SqlStdOperatorTable.PREV; }
+    |
+        <NEXT> { funcOp = SqlStdOperatorTable.NEXT; }
+    )
+    { s = span(); }
+    <LPAREN>
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <COMMA> e = NumericLiteral() { args.add(e); }
+    |
+        { args.add(LITERAL_ONE); }
+    )
+    <RPAREN> {
+        return funcOp.createCall(s.end(this), args);
+    }
+}
+
+SqlCall withinDistinct(SqlNode arg) :
+{
+    final Span s;
+    final SqlNodeList distinctList;
+}
+{
+    <WITHIN> { s = span(); }
+    <DISTINCT>
+    <LPAREN>
+    distinctList = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY)
+    <RPAREN> {
+        return SqlStdOperatorTable.WITHIN_DISTINCT.createCall(
+            s.end(this), arg, distinctList);
+    }
+}
+
+SqlCall withinGroup(SqlNode arg) :
+{
+    final Span s;
+    final SqlNodeList orderList;
+}
+{
+    <WITHIN> { s = span(); }
+    <GROUP>
+    <LPAREN>
+    orderList = OrderBy(true)
+    <RPAREN> {
+        return SqlStdOperatorTable.WITHIN_GROUP.createCall(
+            s.end(this), arg, orderList);
+    }
+}
+
+Pair<SqlParserPos, SqlOperator> NullTreatment() :
+{
+    final Span span;
+}
+{
+    <IGNORE> { span = span(); } <NULLS> {
+        return Pair.of(span.end(this), SqlStdOperatorTable.IGNORE_NULLS);
+    }
+|
+    <RESPECT> { span = span(); } <NULLS> {
+        return Pair.of(span.end(this), SqlStdOperatorTable.RESPECT_NULLS);
+    }
+}
+
+SqlCall nullTreatment(SqlCall arg) :
+{
+    final Pair<SqlParserPos, SqlOperator> pair;
+}
+{
+    pair = NullTreatment() { return pair.right.createCall(pair.left, arg); }
+}
+
+/**
+ * Parses a call to a named function (could be a builtin with regular
+ * syntax, or else a UDF).
+ *
+ * <p>NOTE: every UDF has two names: an <em>invocation name</em> and a
+ * <em>specific name</em>.  Normally, function calls are resolved via overload
+ * resolution and invocation names.  The SPECIFIC prefix allows overload
+ * resolution to be bypassed.  Note that usage of the SPECIFIC prefix in
+ * queries is non-standard; it is used internally by Farrago, e.g. in stored
+ * view definitions to permanently bind references to a particular function
+ * after the overload resolution performed by view creation.
+ *
+ * <p>TODO jvs 25-Mar-2005:  Once we have SQL-Flagger support, flag SPECIFIC
+ * as non-standard.
+ */
+SqlNode NamedFunctionCall() :
+{
+    SqlCall call;
+    final Span filterSpan;
+    final SqlNode filter;
+    final Span overSpan;
+    final SqlNode over;
+}
+{
+    (
+        LOOKAHEAD(2)
+        call = StringAggFunctionCall()
+    |
+        call = NamedCall()
+    )
+    [
+        LOOKAHEAD(2) call = nullTreatment(call)
+    ]
+    [
+        LOOKAHEAD(2) // decide between WITHIN DISTINCT and WITHIN GROUP
+        call = withinDistinct(call)
+    ]
+    [
+        call = withinGroup(call)
+    ]
+    [
+        <FILTER> { filterSpan = span(); }
+        <LPAREN>
+        <WHERE>
+        filter = Expression(ExprContext.ACCEPT_SUB_QUERY)
+        <RPAREN> {
+            call = SqlStdOperatorTable.FILTER.createCall(
+                filterSpan.end(this), call, filter);
+        }
+    ]
+    [
+        <OVER> { overSpan = span(); }
+        (
+            over = SimpleIdentifier()
+        |
+            over = WindowSpecification()
+        )
+        {
+            call = SqlStdOperatorTable.OVER.createCall(overSpan.end(over), call, over);
+        }
+    ]
+    {
+        return call;
+    }
+}
+
+SqlCall NamedCall() :
+{
+    final SqlFunctionCategory funcType;
+    final SqlIdentifier qualifiedName;
+    final Span s;
+    final List<SqlNode> args;
+    SqlLiteral quantifier = null;
+}
+{
+    (
+        <SPECIFIC> {
+            funcType = SqlFunctionCategory.USER_DEFINED_SPECIFIC_FUNCTION;
+        }
+    |
+        { funcType = SqlFunctionCategory.USER_DEFINED_FUNCTION; }
+    )
+    qualifiedName = FunctionName() {
+        s = span();
+    }
+    (
+        LOOKAHEAD(2) <LPAREN> <STAR> {
+            args = ImmutableList.of(SqlIdentifier.star(getPos()));
+        }
+        <RPAREN>
+    |
+        LOOKAHEAD(2) <LPAREN> <RPAREN> {
+            args = ImmutableList.of();
+        }
+    |
+        args = FunctionParameterList(ExprContext.ACCEPT_SUB_QUERY) {
+            quantifier = (SqlLiteral) args.get(0);
+            args.remove(0);
+        }
+    )
+    {
+        return createCall(qualifiedName, s.end(this), funcType, quantifier, args);
+    }
+}
+
+/*
+* Parse Floor/Ceil function parameters
+*/
+SqlNode StandardFloorCeilOptions(Span s, boolean floorFlag) :
+{
+    SqlNode e;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    final SqlIntervalQualifier unit;
+    SqlCall function;
+    final Span s1;
+}
+{
+    <LPAREN> AddExpression(args, ExprContext.ACCEPT_SUB_QUERY)
+    (
+        <TO> unit = TimeUnitOrName() {
+            args.add(unit);
+        }
+    )?
+    <RPAREN> {
+        SqlOperator op = floorFlag
+            ? SqlStdOperatorTable.FLOOR
+            : SqlStdOperatorTable.CEIL;
+        function =  op.createCall(s.end(this), args);
+    }
+    (
+        <OVER> { s1 = span(); }
+        (
+            e = SimpleIdentifier()
+        |
+            e = WindowSpecification()
+        )
+        {
+            return SqlStdOperatorTable.OVER.createCall(s1.end(this), function, e);
+        }
+    |
+        { return function; }
+    )
+}
+
+/**
+ * Parses the name of a JDBC function that is a token but is not reserved.
+ */
+String NonReservedJdbcFunctionName() :
+{
+}
+{
+    (
+        <SUBSTRING>
+    )
+    {
+        return unquotedIdentifier();
+    }
+}
+
+/**
+ * Parses the name of a function (either a compound identifier or
+ * a reserved word which can be used as a function name).
+ */
+SqlIdentifier FunctionName() :
+{
+    SqlIdentifier qualifiedName;
+}
+{
+    (
+        qualifiedName = CompoundIdentifier()
+    |
+        qualifiedName = ReservedFunctionName()
+    )
+    {
+        return qualifiedName;
+    }
+}
+
+/**
+ * Parses a reserved word which is used as the name of a function.
+ */
+SqlIdentifier ReservedFunctionName() :
+{
+}
+{
+    (
+        <ABS>
+    |   <AVG>
+    |   <CARDINALITY>
+    |   <CEILING>
+    |   <CHAR>
+    |   <CHAR_LENGTH>
+    |   <CHARACTER_LENGTH>
+    |   <COALESCE>
+    |   <COLLECT>
+    |   <COVAR_POP>
+    |   <COVAR_SAMP>
+    |   <CUME_DIST>
+    |   <COUNT>
+    |   <CURRENT_DATE>
+    |   <CURRENT_TIME>
+    |   <CURRENT_TIMESTAMP>
+    |   <DENSE_RANK>
+    |   <ELEMENT>
+    |   <EVERY>
+    |   <EXP>
+    |   <FIRST_VALUE>
+    |   <FLOOR>
+    |   <FUSION>
+    |   <INTERSECTION>
+    |   <GROUPING>
+    |   <HOUR>
+    |   <LAG>
+    |   <LEAD>
+    |   <LEFT>
+    |   <LAST_VALUE>
+    |   <LN>
+    |   <LOCALTIME>
+    |   <LOCALTIMESTAMP>
+    |   <LOWER>
+    |   <MAX>
+    |   <MIN>
+    |   <MINUTE>
+    |   <MOD>
+    |   <MONTH>
+    |   <NTH_VALUE>
+    |   <NTILE>
+    |   <NULLIF>
+    |   <OCTET_LENGTH>
+    |   <PERCENT_RANK>
+    |   <PERCENTILE_CONT>
+    |   <PERCENTILE_DISC>
+    |   <POWER>
+    |   <RANK>
+    |   <REGR_COUNT>
+    |   <REGR_SXX>
+    |   <REGR_SYY>
+    |   <RIGHT>
+    |   <ROW_NUMBER>
+    |   <SECOND>
+    |   <SOME>
+    |   <SQRT>
+    |   <STDDEV_POP>
+    |   <STDDEV_SAMP>
+    |   <SUM>
+    |   <UPPER>
+    |   <TRUNCATE>
+    |   <USER>
+    |   <VAR_POP>
+    |   <VAR_SAMP>
+    |   <YEAR>
+    )
+    {
+        return new SqlIdentifier(unquotedIdentifier(), getPos());
+    }
+}
+
+SqlIdentifier ContextVariable() :
+{
+}
+{
+    (
+        <CURRENT_CATALOG>
+    |   <CURRENT_DATE>
+    |   <CURRENT_DEFAULT_TRANSFORM_GROUP>
+    |   <CURRENT_PATH>
+    |   <CURRENT_ROLE>
+    |   <CURRENT_SCHEMA>
+    |   <CURRENT_TIME>
+    |   <CURRENT_TIMESTAMP>
+    |   <CURRENT_USER>
+    |   <LOCALTIME>
+    |   <LOCALTIMESTAMP>
+    |   <SESSION_USER>
+    |   <SYSTEM_USER>
+    |   <USER>
+    )
+    {
+        return new SqlIdentifier(unquotedIdentifier(), getPos());
+    }
+}
+
+/**
+ * Parses a function call expression with JDBC syntax.
+ */
+SqlNode JdbcFunctionCall() :
+{
+    String name;
+    SqlIdentifier id;
+    SqlNode e;
+    SqlLiteral tl;
+    SqlNodeList args;
+    SqlCall call;
+    final Span s, s1;
+}
+{
+    <LBRACE_FN> {
+        s = span();
+    }
+    (
+        LOOKAHEAD(1)
+        call = TimestampAddFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(1)
+        call = DateTruncFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(1)
+        call = TimestampTruncFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(1)
+        call = TimeTruncFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(1)
+        call = TimestampDiff3FunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(1)
+        call = TimeDiffFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        LOOKAHEAD(3)
+        call = TimestampDiffFunctionCall() {
+            name = call.getOperator().getName();
+            args = new SqlNodeList(call.getOperandList(), getPos());
+        }
+    |
+        <CONVERT> { name = unquotedIdentifier(); }
+        <LPAREN>
+        e = Expression(ExprContext.ACCEPT_SUB_QUERY) {
+            args = new SqlNodeList(getPos());
+            args.add(e);
+        }
+        <COMMA>
+        tl = JdbcOdbcDataType() { args.add(tl); }
+        <RPAREN>
+    |
+        (
+            // INSERT is a reserved word, but we need to handle {fn insert}
+            // Similarly LEFT, RIGHT, TRUNCATE
+            LOOKAHEAD(1)
+            ( <INSERT> | <LEFT> | <RIGHT> | <TRUNCATE> ) { name = unquotedIdentifier(); }
+        |
+            // For cases like {fn power(1,2)} and {fn lower('a')}
+            id = ReservedFunctionName() { name = id.getSimple(); }
+        |
+            // For cases like {fn substring('foo', 1,2)}
+            name = NonReservedJdbcFunctionName()
+        |
+            name = Identifier()
+        )
+        (
+            LOOKAHEAD(2) <LPAREN> <STAR> { s1 = span(); } <RPAREN>
+            {
+                args = new SqlNodeList(s1.pos());
+                args.add(SqlIdentifier.star(s1.pos()));
+            }
+        |
+            LOOKAHEAD(2) <LPAREN> <RPAREN> { args = SqlNodeList.EMPTY; }
+        |
+            args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUB_QUERY)
+        )
+    )
+    <RBRACE> {
+        return new SqlJdbcFunctionCall(name).createCall(s.end(this),
+            args.getList());
+    }
+}
+
+/**
+ * Parses a binary query operator like UNION.
+ */
+SqlBinaryOperator BinaryQueryOperator() :
+{
+}
+{
+    // If both the ALL or DISTINCT keywords are missing, DISTINCT is implicit.
+    (
+        <UNION>
+        (
+            <ALL> { return SqlStdOperatorTable.UNION_ALL; }
+        |   <DISTINCT> { return SqlStdOperatorTable.UNION; }
+        |   { return SqlStdOperatorTable.UNION; }
+        )
+    |
+        <INTERSECT>
+        (
+            <ALL> { return SqlStdOperatorTable.INTERSECT_ALL; }
+        |   <DISTINCT> { return SqlStdOperatorTable.INTERSECT; }
+        |   { return SqlStdOperatorTable.INTERSECT; }
+        )
+    |
+        (
+            <EXCEPT>
+        |
+            <SET_MINUS> {
+                if (!this.conformance.isMinusAllowed()) {
+                    throw SqlUtil.newContextException(getPos(), RESOURCE.minusNotAllowed());
+                }
+            }
+        )
+        (
+            <ALL> { return SqlStdOperatorTable.EXCEPT_ALL; }
+        |   <DISTINCT> { return SqlStdOperatorTable.EXCEPT; }
+        |   { return SqlStdOperatorTable.EXCEPT; }
+        )
+    )
+}
+
+/**
+ * Parses a binary multiset operator.
+ */
+SqlBinaryOperator BinaryMultisetOperator() :
+{
+}
+{
+    // If both the ALL or DISTINCT keywords are missing, DISTINCT is implicit
+    <MULTISET>
+    (
+        <UNION>
+        [
+            <ALL>
+        |   <DISTINCT> { return SqlStdOperatorTable.MULTISET_UNION_DISTINCT; }
+        ]
+        { return SqlStdOperatorTable.MULTISET_UNION; }
+    |
+        <INTERSECT>
+        [
+            <ALL>
+        |   <DISTINCT> { return SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT; }
+        ]
+        { return SqlStdOperatorTable.MULTISET_INTERSECT; }
+    |
+        <EXCEPT>
+        [
+            <ALL>
+        |   <DISTINCT> { return SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT; }
+        ]
+        { return SqlStdOperatorTable.MULTISET_EXCEPT; }
+    )
+}
+
+/**
+ * Parses a binary row operator like AND.
+ */
+SqlBinaryOperator BinaryRowOperator() :
+{
+    SqlBinaryOperator op;
+}
+{
+    // <IN> is handled as a special case
+    <EQ> { return SqlStdOperatorTable.EQUALS; }
+|   <GT> { return SqlStdOperatorTable.GREATER_THAN; }
+|   <LT> { return SqlStdOperatorTable.LESS_THAN; }
+|   <LE> { return SqlStdOperatorTable.LESS_THAN_OR_EQUAL; }
+|   <GE> { return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL; }
+|   <NE> { return SqlStdOperatorTable.NOT_EQUALS; }
+|   <NE2> {
+        if (!this.conformance.isBangEqualAllowed()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.bangEqualNotAllowed());
+        }
+        return SqlStdOperatorTable.NOT_EQUALS;
+    }
+|   <PLUS> { return SqlStdOperatorTable.PLUS; }
+|   <MINUS> { return SqlStdOperatorTable.MINUS; }
+|   <STAR> { return SqlStdOperatorTable.MULTIPLY; }
+|   <SLASH> { return SqlStdOperatorTable.DIVIDE; }
+|   <PERCENT_REMAINDER> {
+        if (!this.conformance.isPercentRemainderAllowed()) {
+            throw SqlUtil.newContextException(getPos(), RESOURCE.percentRemainderNotAllowed());
+        }
+        return SqlStdOperatorTable.PERCENT_REMAINDER;
+    }
+|   <CONCAT> { return SqlStdOperatorTable.CONCAT; }
+|   <AND> { return SqlStdOperatorTable.AND; }
+|   <OR> { return SqlStdOperatorTable.OR; }
+|   LOOKAHEAD(2) <IS> <DISTINCT> <FROM> { return SqlStdOperatorTable.IS_DISTINCT_FROM; }
+|   <IS> <NOT> <DISTINCT> <FROM> { return SqlStdOperatorTable.IS_NOT_DISTINCT_FROM; }
+|   <MEMBER> <OF> { return SqlStdOperatorTable.MEMBER_OF; }
+|   LOOKAHEAD(2) <SUBMULTISET> <OF> { return SqlStdOperatorTable.SUBMULTISET_OF; }
+|   <NOT> <SUBMULTISET> <OF> { return SqlStdOperatorTable.NOT_SUBMULTISET_OF; }
+|   <CONTAINS> { return SqlStdOperatorTable.CONTAINS; }
+|   <OVERLAPS> { return SqlStdOperatorTable.OVERLAPS; }
+|   <EQUALS> { return SqlStdOperatorTable.PERIOD_EQUALS; }
+|   <PRECEDES> { return SqlStdOperatorTable.PRECEDES; }
+|   <SUCCEEDS> { return SqlStdOperatorTable.SUCCEEDS; }
+|   LOOKAHEAD(2) <IMMEDIATELY> <PRECEDES> { return SqlStdOperatorTable.IMMEDIATELY_PRECEDES; }
+|   <IMMEDIATELY> <SUCCEEDS> { return SqlStdOperatorTable.IMMEDIATELY_SUCCEEDS; }
+|   op = BinaryMultisetOperator() { return op; }
+}
+
+/**
+ * Parses a prefix row operator like NOT.
+ */
+SqlPrefixOperator PrefixRowOperator() :
+{}
+{
+    <PLUS> { return SqlStdOperatorTable.UNARY_PLUS; }
+|   <MINUS> { return SqlStdOperatorTable.UNARY_MINUS; }
+|   <NOT> { return SqlStdOperatorTable.NOT; }
+|   <EXISTS> { return SqlStdOperatorTable.EXISTS; }
+|   <UNIQUE> { return SqlStdOperatorTable.UNIQUE; }
+}
+
+/**
+ * Parses a postfix row operator like IS NOT NULL.
+ */
+SqlPostfixOperator PostfixRowOperator() :
+{}
+{
+    <IS>
+    (
+        <A> <SET> { return SqlStdOperatorTable.IS_A_SET; }
+    |
+        <NOT>
+        (
+            <NULL> { return SqlStdOperatorTable.IS_NOT_NULL; }
+        |   <TRUE> { return SqlStdOperatorTable.IS_NOT_TRUE; }
+        |   <FALSE> { return SqlStdOperatorTable.IS_NOT_FALSE; }
+        |   <UNKNOWN> { return SqlStdOperatorTable.IS_NOT_UNKNOWN; }
+        |   <A> <SET> { return SqlStdOperatorTable.IS_NOT_A_SET; }
+        |   <EMPTY> { return SqlStdOperatorTable.IS_NOT_EMPTY; }
+        |   LOOKAHEAD(2) <JSON> <VALUE> { return SqlStdOperatorTable.IS_NOT_JSON_VALUE; }
+        |   LOOKAHEAD(2) <JSON> <OBJECT> { return SqlStdOperatorTable.IS_NOT_JSON_OBJECT; }
+        |   LOOKAHEAD(2) <JSON> <ARRAY> { return SqlStdOperatorTable.IS_NOT_JSON_ARRAY; }
+        |   LOOKAHEAD(2) <JSON> <SCALAR> { return SqlStdOperatorTable.IS_NOT_JSON_SCALAR; }
+        |   <JSON> { return SqlStdOperatorTable.IS_NOT_JSON_VALUE; }
+        )
+    |
+        (
+            <NULL> { return SqlStdOperatorTable.IS_NULL; }
+        |   <TRUE> { return SqlStdOperatorTable.IS_TRUE; }
+        |   <FALSE> { return SqlStdOperatorTable.IS_FALSE; }
+        |   <UNKNOWN> { return SqlStdOperatorTable.IS_UNKNOWN; }
+        |   <EMPTY> { return SqlStdOperatorTable.IS_EMPTY; }
+        |   LOOKAHEAD(2) <JSON> <VALUE> { return SqlStdOperatorTable.IS_JSON_VALUE; }
+        |   LOOKAHEAD(2) <JSON> <OBJECT> { return SqlStdOperatorTable.IS_JSON_OBJECT; }
+        |   LOOKAHEAD(2) <JSON> <ARRAY> { return SqlStdOperatorTable.IS_JSON_ARRAY; }
+        |   LOOKAHEAD(2) <JSON> <SCALAR> { return SqlStdOperatorTable.IS_JSON_SCALAR; }
+        |   <JSON> { return SqlStdOperatorTable.IS_JSON_VALUE; }
+        )
+    )
+|
+    <FORMAT>
+    (
+        JsonRepresentation() {
+            return SqlStdOperatorTable.JSON_VALUE_EXPRESSION;
+        }
+    )
+}
+
+
+/* KEYWORDS:  anything in this list is a reserved word unless it appears
+   in the NonReservedKeyWord() production. */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < A: "A" >
+|   < ABS: "ABS" >
+|   < ABSENT: "ABSENT" >
+|   < ABSOLUTE: "ABSOLUTE" >
+|   < ACTION: "ACTION" >
+|   < ADA: "ADA" >
+|   < ADD: "ADD" >
+|   < ADMIN: "ADMIN" >
+|   < AFTER: "AFTER" >
+|   < ALL: "ALL" >
+|   < ALLOCATE: "ALLOCATE" >
+|   < ALLOW: "ALLOW" >
+|   < ALTER: "ALTER" >
+|   < ALWAYS: "ALWAYS" >
+|   < AND: "AND" >
+|   < ANY: "ANY" >
+|   < APPLY: "APPLY" >
+|   < ARE: "ARE" >
+|   < ARRAY: "ARRAY" >
+|   < ARRAY_AGG: "ARRAY_AGG" >
+|   < ARRAY_CONCAT_AGG: "ARRAY_CONCAT_AGG" >
+|   < ARRAY_MAX_CARDINALITY: "ARRAY_MAX_CARDINALITY" >
+|   < AS: "AS" >
+|   < ASC: "ASC" >
+|   < ASENSITIVE: "ASENSITIVE" >
+|   < ASSERTION: "ASSERTION" >
+|   < ASSIGNMENT: "ASSIGNMENT" >
+|   < ASYMMETRIC: "ASYMMETRIC" >
+|   < AT: "AT" >
+|   < ATOMIC: "ATOMIC" >
+|   < ATTRIBUTE: "ATTRIBUTE" >
+|   < ATTRIBUTES: "ATTRIBUTES" >
+|   < AUTHORIZATION: "AUTHORIZATION" >
+|   < AVG: "AVG" >
+|   < BEFORE: "BEFORE" >
+|   < BEGIN: "BEGIN" >
+|   < BEGIN_FRAME: "BEGIN_FRAME" >
+|   < BEGIN_PARTITION: "BEGIN_PARTITION" >
+|   < BERNOULLI: "BERNOULLI" >
+|   < BETWEEN: "BETWEEN" >
+|   < BIGINT: "BIGINT" >
+|   < BINARY: "BINARY" >
+|   < BIT: "BIT" >
+|   < BLOB: "BLOB" >
+|   < BOOLEAN: "BOOLEAN" >
+|   < BOTH: "BOTH" >
+|   < BREADTH: "BREADTH" >
+|   < BY: "BY" >
+|   < C: "C" >
+|   < CALL: "CALL" >
+|   < CALLED: "CALLED" >
+|   < CARDINALITY: "CARDINALITY" >
+|   < CASCADE: "CASCADE" >
+|   < CASCADED: "CASCADED" >
+|   < CASE: "CASE" >
+|   < CAST: "CAST" >
+|   < CATALOG: "CATALOG" >
+|   < CATALOG_NAME: "CATALOG_NAME" >
+|   < CEIL: "CEIL" >
+|   < CEILING: "CEILING" >
+|   < CENTURY: "CENTURY" >
+|   < CHAIN: "CHAIN" >
+|   < CHAR: "CHAR" >
+|   < CHAR_LENGTH: "CHAR_LENGTH" >
+|   < CHARACTER: "CHARACTER" >
+|   < CHARACTER_LENGTH: "CHARACTER_LENGTH" >
+|   < CHARACTER_SET_CATALOG: "CHARACTER_SET_CATALOG" >
+|   < CHARACTER_SET_NAME: "CHARACTER_SET_NAME" >
+|   < CHARACTER_SET_SCHEMA: "CHARACTER_SET_SCHEMA" >
+|   < CHARACTERISTICS: "CHARACTERISTICS" >
+|   < CHARACTERS: "CHARACTERS" >
+|   < CHECK: "CHECK" >
+|   < CLASSIFIER: "CLASSIFIER" >
+|   < CLASS_ORIGIN: "CLASS_ORIGIN" >
+|   < CLOB: "CLOB" >
+|   < CLOSE: "CLOSE" >
+|   < COALESCE: "COALESCE" >
+|   < COBOL: "COBOL" >
+|   < COLLATE: "COLLATE" >
+|   < COLLATION: "COLLATION" >
+|   < COLLATION_CATALOG: "COLLATION_CATALOG" >
+|   < COLLATION_NAME: "COLLATION_NAME" >
+|   < COLLATION_SCHEMA: "COLLATION_SCHEMA" >
+|   < COLLECT: "COLLECT" >
+|   < COLUMN: "COLUMN" >
+|   < COLUMN_NAME: "COLUMN_NAME" >
+|   < COMMAND_FUNCTION: "COMMAND_FUNCTION" >
+|   < COMMAND_FUNCTION_CODE: "COMMAND_FUNCTION_CODE" >
+|   < COMMIT: "COMMIT" >
+|   < COMMITTED: "COMMITTED" >
+|   < CONDITION: "CONDITION" >
+|   < CONDITIONAL: "CONDITIONAL" >
+|   < CONDITION_NUMBER: "CONDITION_NUMBER" >
+|   < CONNECT: "CONNECT" >
+|   < CONNECTION: "CONNECTION" >
+|   < CONNECTION_NAME: "CONNECTION_NAME" >
+|   < CONSTRAINT: "CONSTRAINT" >
+|   < CONSTRAINT_CATALOG: "CONSTRAINT_CATALOG" >
+|   < CONSTRAINT_NAME: "CONSTRAINT_NAME" >
+|   < CONSTRAINT_SCHEMA: "CONSTRAINT_SCHEMA" >
+|   < CONSTRAINTS: "CONSTRAINTS" >
+|   < CONSTRUCTOR: "CONSTRUCTOR" >
+|   < CONTAINS: "CONTAINS" >
+|   < CONTINUE: "CONTINUE" >
+|   < CONVERT: "CONVERT" >
+|   < CORR: "CORR" >
+|   < CORRESPONDING: "CORRESPONDING" >
+|   < COUNT: "COUNT" >
+|   < COVAR_POP: "COVAR_POP" >
+|   < COVAR_SAMP: "COVAR_SAMP" >
+|   < CREATE: "CREATE" >
+|   < CROSS: "CROSS" >
+|   < CUBE: "CUBE" >
+|   < CUME_DIST: "CUME_DIST" >
+|   < CURRENT: "CURRENT" >
+|   < CURRENT_CATALOG: "CURRENT_CATALOG" >
+|   < CURRENT_DATE: "CURRENT_DATE" >
+|   < CURRENT_DEFAULT_TRANSFORM_GROUP: "CURRENT_DEFAULT_TRANSFORM_GROUP" >
+|   < CURRENT_PATH: "CURRENT_PATH" >
+|   < CURRENT_ROLE: "CURRENT_ROLE" >
+|   < CURRENT_ROW: "CURRENT_ROW" >
+|   < CURRENT_SCHEMA: "CURRENT_SCHEMA" >
+|   < CURRENT_TIME: "CURRENT_TIME" >
+|   < CURRENT_TIMESTAMP: "CURRENT_TIMESTAMP" >
+|   < CURRENT_TRANSFORM_GROUP_FOR_TYPE: "CURRENT_TRANSFORM_GROUP_FOR_TYPE" >
+|   < CURRENT_USER: "CURRENT_USER" >
+|   < CURSOR: "CURSOR" >
+|   < CURSOR_NAME: "CURSOR_NAME" >
+|   < CYCLE: "CYCLE" >
+|   < DATA: "DATA" >
+|   < DATABASE: "DATABASE" >
+|   < DATE: "DATE" >
+|   < DATE_TRUNC: "DATE_TRUNC" >
+|   < DATETIME: "DATETIME" >
+|   < DATETIME_INTERVAL_CODE: "DATETIME_INTERVAL_CODE" >
+|   < DATETIME_INTERVAL_PRECISION: "DATETIME_INTERVAL_PRECISION" >
+|   < DAY: "DAY" >
+|   < DAYS: "DAYS" >
+|   < DEALLOCATE: "DEALLOCATE" >
+|   < DEC: "DEC" >
+|   < DECADE: "DECADE" >
+|   < DECIMAL: "DECIMAL" >
+|   < DECLARE: "DECLARE" >
+|   < DEFAULT_: "DEFAULT" >
+|   < DEFAULTS: "DEFAULTS" >
+|   < DEFERRABLE: "DEFERRABLE" >
+|   < DEFERRED: "DEFERRED" >
+|   < DEFINE: "DEFINE" >
+|   < DEFINED: "DEFINED" >
+|   < DEFINER: "DEFINER" >
+|   < DEGREE: "DEGREE" >
+|   < DELETE: "DELETE" > { beforeTableName(); }
+|   < DENSE_RANK: "DENSE_RANK" >
+|   < DEPTH: "DEPTH" >
+|   < DEREF: "DEREF" >
+|   < DERIVED: "DERIVED" >
+|   < DESC: "DESC" >
+|   < DESCRIBE: "DESCRIBE" > { beforeTableName(); }
+|   < DESCRIPTION: "DESCRIPTION" >
+|   < DESCRIPTOR: "DESCRIPTOR" >
+|   < DETERMINISTIC: "DETERMINISTIC" >
+|   < DIAGNOSTICS: "DIAGNOSTICS" >
+|   < DISALLOW: "DISALLOW" >
+|   < DISCONNECT: "DISCONNECT" >
+|   < DISPATCH: "DISPATCH" >
+|   < DISTINCT: "DISTINCT" >
+|   < DOMAIN: "DOMAIN" >
+|   < DOT_FORMAT: "DOT" >
+|   < DOUBLE: "DOUBLE" >
+|   < DOW: "DOW" >
+|   < DOY: "DOY" >
+|   < DROP: "DROP" >
+|   < DYNAMIC: "DYNAMIC" >
+|   < DYNAMIC_FUNCTION: "DYNAMIC_FUNCTION" >
+|   < DYNAMIC_FUNCTION_CODE: "DYNAMIC_FUNCTION_CODE" >
+|   < EACH: "EACH" >
+|   < ELEMENT: "ELEMENT" >
+|   < ELSE: "ELSE" >
+|   < EMPTY: "EMPTY" >
+|   < ENCODING: "ENCODING">
+|   < END: "END" >
+|   < END_EXEC: "END-EXEC" >
+|   < END_FRAME: "END_FRAME" >
+|   < END_PARTITION: "END_PARTITION" >
+|   < EPOCH: "EPOCH" >
+|   < EQUALS: "EQUALS" >
+|   < ERROR: "ERROR" >
+|   < ESCAPE: "ESCAPE" >
+|   < EVERY: "EVERY" >
+|   < EXCEPT: "EXCEPT" >
+|   < EXCEPTION: "EXCEPTION" >
+|   < EXCLUDE: "EXCLUDE" >
+|   < EXCLUDING: "EXCLUDING" >
+|   < EXEC: "EXEC" >
+|   < EXECUTE: "EXECUTE" >
+|   < EXISTS: "EXISTS" >
+|   < EXP: "EXP" >
+|   < EXPLAIN: "EXPLAIN" >
+|   < EXTEND: "EXTEND" >
+|   < EXTERNAL: "EXTERNAL" >
+|   < EXTRACT: "EXTRACT" >
+|   < FALSE: "FALSE" >
+|   < FETCH: "FETCH" >
+|   < FILTER: "FILTER" >
+|   < FINAL: "FINAL" >
+|   < FIRST: "FIRST" >
+|   < FIRST_VALUE: "FIRST_VALUE">
+|   < FLOAT: "FLOAT" >
+|   < FLOOR: "FLOOR" >
+|   < FOLLOWING: "FOLLOWING" >
+|   < FOR: "FOR" >
+|   < FORMAT: "FORMAT" >
+|   < FOREIGN: "FOREIGN" >
+|   < FORTRAN: "FORTRAN" >
+|   < FOUND: "FOUND" >
+|   < FRAC_SECOND: "FRAC_SECOND" >
+|   < FRAME_ROW: "FRAME_ROW" >
+|   < FREE: "FREE" >
+|   < FRIDAY: "FRIDAY" >
+|   < FROM: "FROM" > { beforeTableName(); }
+|   < FULL: "FULL" >
+|   < FUNCTION: "FUNCTION" >
+|   < FUSION: "FUSION" >
+|   < G: "G" >
+|   < GENERAL: "GENERAL" >
+|   < GENERATED: "GENERATED" >
+|   < GEOMETRY: "GEOMETRY" >
+|   < GET: "GET" >
+|   < GLOBAL: "GLOBAL" >
+|   < GO: "GO" >
+|   < GOTO: "GOTO" >
+|   < GRANT: "GRANT" >
+|   < GRANTED: "GRANTED" >
+|   < GROUP: "GROUP" >
+|   < GROUP_CONCAT: "GROUP_CONCAT" >
+|   < GROUPING: "GROUPING" >
+|   < GROUPS: "GROUPS" >
+|   < HAVING: "HAVING" >
+|   < HIERARCHY: "HIERARCHY" >
+|   < HOLD: "HOLD" >
+|   < HOP: "HOP" >
+|   < HOUR: "HOUR" >
+|   < HOURS: "HOURS" >
+|   < IDENTITY: "IDENTITY" >
+|   < IGNORE: "IGNORE" >
+|   < ILIKE: "ILIKE" >
+|   < IMMEDIATE: "IMMEDIATE" >
+|   < IMMEDIATELY: "IMMEDIATELY" >
+|   < IMPLEMENTATION: "IMPLEMENTATION" >
+|   < IMPORT: "IMPORT" >
+|   < IN: "IN" >
+|   < INCLUDE: "INCLUDE" >
+|   < INCLUDING: "INCLUDING" >
+|   < INCREMENT: "INCREMENT" >
+|   < INDICATOR: "INDICATOR" >
+|   < INITIAL: "INITIAL" >
+|   < INITIALLY: "INITIALLY" >
+|   < INNER: "INNER" >
+|   < INOUT: "INOUT" >
+|   < INPUT: "INPUT" >
+|   < INSENSITIVE: "INSENSITIVE" >
+|   < INSERT: "INSERT" > { beforeTableName(); }
+|   < INSTANCE: "INSTANCE" >
+|   < INSTANTIABLE: "INSTANTIABLE" >
+|   < INT: "INT" >
+|   < INTEGER: "INTEGER" >
+|   < INTERSECT: "INTERSECT" >
+|   < INTERSECTION: "INTERSECTION" >
+|   < INTERVAL: "INTERVAL" >
+|   < INTO: "INTO" >
+|   < INVOKER: "INVOKER" >
+|   < IS: "IS" >
+|   < ISODOW: "ISODOW" >
+|   < ISOYEAR: "ISOYEAR" >
+|   < ISOLATION: "ISOLATION" >
+|   < JAVA: "JAVA" >
+|   < JOIN: "JOIN" > { beforeTableName(); }
+|   < JSON: "JSON" >
+|   < JSON_ARRAY: "JSON_ARRAY">
+|   < JSON_ARRAYAGG: "JSON_ARRAYAGG">
+|   < JSON_EXISTS: "JSON_EXISTS" >
+|   < JSON_OBJECT: "JSON_OBJECT">
+|   < JSON_OBJECTAGG: "JSON_OBJECTAGG">
+|   < JSON_QUERY: "JSON_QUERY" >
+|   < JSON_VALUE: "JSON_VALUE" >
+|   < K: "K" >
+|   < KEY: "KEY" >
+|   < KEY_MEMBER: "KEY_MEMBER" >
+|   < KEY_TYPE: "KEY_TYPE" >
+|   < LABEL: "LABEL" >
+|   < LAG: "LAG" >
+|   < LANGUAGE: "LANGUAGE" >
+|   < LARGE: "LARGE" >
+|   < LAST: "LAST" >
+|   < LAST_VALUE: "LAST_VALUE" >
+|   < LATERAL: "LATERAL" >
+|   < LEAD: "LEAD" >
+|   < LEADING: "LEADING" >
+|   < LEFT: "LEFT" >
+|   < LENGTH: "LENGTH" >
+|   < LEVEL: "LEVEL" >
+|   < LIBRARY: "LIBRARY" >
+|   < LIKE: "LIKE" >
+|   < LIKE_REGEX: "LIKE_REGEX" >
+|   < LIMIT: "LIMIT" >
+|   < LN: "LN" >
+|   < LOCAL: "LOCAL" >
+|   < LOCALTIME: "LOCALTIME" >
+|   < LOCALTIMESTAMP: "LOCALTIMESTAMP" >
+|   < LOCATOR: "LOCATOR" >
+|   < LOWER: "LOWER" >
+|   < M: "M" >
+|   < MAP: "MAP" >
+|   < MATCH: "MATCH" >
+|   < MATCHED: "MATCHED" >
+|   < MATCHES: "MATCHES" >
+|   < MATCH_NUMBER: "MATCH_NUMBER">
+|   < MATCH_RECOGNIZE: "MATCH_RECOGNIZE">
+|   < MAX: "MAX" >
+|   < MAXVALUE: "MAXVALUE" >
+|   < MEASURES: "MEASURES" >
+|   < MEMBER: "MEMBER" >
+|   < MERGE: "MERGE" > { beforeTableName(); }
+|   < MESSAGE_LENGTH: "MESSAGE_LENGTH" >
+|   < MESSAGE_OCTET_LENGTH: "MESSAGE_OCTET_LENGTH" >
+|   < MESSAGE_TEXT: "MESSAGE_TEXT" >
+|   < METHOD: "METHOD" >
+|   < MICROSECOND: "MICROSECOND" >
+|   < MILLISECOND: "MILLISECOND" >
+|   < MILLENNIUM: "MILLENNIUM" >
+|   < MIN: "MIN" >
+|   < MINUTE: "MINUTE" >
+|   < MINUTES: "MINUTES" >
+|   < MINVALUE: "MINVALUE" >
+|   < MOD: "MOD" >
+|   < MODIFIES: "MODIFIES" >
+|   < MODULE: "MODULE" >
+|   < MONDAY: "MONDAY" >
+|   < MONTH: "MONTH" >
+|   < MONTHS: "MONTHS" >
+|   < MORE_: "MORE" >
+|   < MULTISET: "MULTISET" >
+|   < MUMPS: "MUMPS" >
+|   < NAME: "NAME" >
+|   < NAMES: "NAMES" >
+|   < NANOSECOND: "NANOSECOND" >
+|   < NATIONAL: "NATIONAL" >
+|   < NATURAL: "NATURAL" >
+|   < NCHAR: "NCHAR" >
+|   < NCLOB: "NCLOB" >
+|   < NESTING: "NESTING" >
+|   < NEW: "NEW" >
+|   < NEXT: "NEXT" >
+|   < NO: "NO" >
+|   < NONE: "NONE" >
+|   < NORMALIZE: "NORMALIZE" >
+|   < NORMALIZED: "NORMALIZED" >
+|   < NOT: "NOT" >
+|   < NTH_VALUE: "NTH_VALUE" >
+|   < NTILE: "NTILE" >
+|   < NULL: "NULL" >
+|   < NULLABLE: "NULLABLE" >
+|   < NULLIF: "NULLIF" >
+|   < NULLS: "NULLS" >
+|   < NUMBER: "NUMBER" >
+|   < NUMERIC: "NUMERIC" >
+|   < OBJECT: "OBJECT" >
+|   < OCCURRENCES_REGEX: "OCCURRENCES_REGEX" >
+|   < OCTET_LENGTH: "OCTET_LENGTH" >
+|   < OCTETS: "OCTETS" >
+|   < OF: "OF" >
+|   < OFFSET: "OFFSET" >
+|   < OLD: "OLD" >
+|   < OMIT: "OMIT" >
+|   < ON: "ON" >
+|   < ONE: "ONE" >
+|   < ONLY: "ONLY" >
+|   < OPEN: "OPEN" >
+|   < OPTION: "OPTION" >
+|   < OPTIONS: "OPTIONS" >
+|   < OR: "OR" >
+|   < ORDER: "ORDER" >
+|   < ORDERING: "ORDERING" >
+|   < ORDINALITY: "ORDINALITY" >
+|   < OTHERS: "OTHERS" >
+|   < OUT: "OUT" >
+|   < OUTER: "OUTER" >
+|   < OUTPUT: "OUTPUT" >
+|   < OVER: "OVER" >
+|   < OVERLAPS: "OVERLAPS" >
+|   < OVERLAY: "OVERLAY" >
+|   < OVERRIDING: "OVERRIDING" >
+|   < PAD: "PAD" >
+|   < PARAMETER: "PARAMETER" >
+|   < PARAMETER_MODE: "PARAMETER_MODE" >
+|   < PARAMETER_NAME: "PARAMETER_NAME" >
+|   < PARAMETER_ORDINAL_POSITION: "PARAMETER_ORDINAL_POSITION" >
+|   < PARAMETER_SPECIFIC_CATALOG: "PARAMETER_SPECIFIC_CATALOG" >
+|   < PARAMETER_SPECIFIC_NAME: "PARAMETER_SPECIFIC_NAME" >
+|   < PARAMETER_SPECIFIC_SCHEMA: "PARAMETER_SPECIFIC_SCHEMA" >
+|   < PARTIAL: "PARTIAL" >
+|   < PARTITION: "PARTITION" >
+|   < PASCAL: "PASCAL" >
+|   < PASSING: "PASSING" >
+|   < PASSTHROUGH: "PASSTHROUGH" >
+|   < PAST: "PAST" >
+|   < PATH: "PATH" >
+|   < PATTERN: "PATTERN" >
+|   < PER: "PER" >
+|   < PERCENT: "PERCENT" >
+|   < PERCENTILE_CONT: "PERCENTILE_CONT" >
+|   < PERCENTILE_DISC: "PERCENTILE_DISC" >
+|   < PERCENT_RANK: "PERCENT_RANK" >
+|   < PERIOD: "PERIOD" >
+|   < PERMUTE: "PERMUTE" >
+|   < PIVOT: "PIVOT" >
+|   < PLACING: "PLACING" >
+|   < PLAN: "PLAN" >
+|   < PLI: "PLI" >
+|   < PORTION: "PORTION" >
+|   < POSITION: "POSITION" >
+|   < POSITION_REGEX: "POSITION_REGEX" >
+|   < POWER: "POWER" >
+|   < PRECEDES: "PRECEDES" >
+|   < PRECEDING: "PRECEDING" >
+|   < PRECISION: "PRECISION" >
+|   < PREPARE: "PREPARE" >
+|   < PRESERVE: "PRESERVE" >
+|   < PREV: "PREV" >
+|   < PRIMARY: "PRIMARY" >
+|   < PRIOR: "PRIOR" >
+|   < PRIVILEGES: "PRIVILEGES" >
+|   < PROCEDURE: "PROCEDURE" >
+|   < PUBLIC: "PUBLIC" >
+|   < QUALIFY: "QUALIFY" >
+|   < QUARTER: "QUARTER" >
+|   < QUARTERS: "QUARTERS" >
+|   < RANGE: "RANGE" >
+|   < RANK: "RANK" >
+|   < READ: "READ" >
+|   < READS: "READS" >
+|   < REAL: "REAL" >
+|   < RECURSIVE: "RECURSIVE" >
+|   < REF: "REF" >
+|   < REFERENCES: "REFERENCES" >
+|   < REFERENCING: "REFERENCING" >
+|   < REGR_AVGX: "REGR_AVGX" >
+|   < REGR_AVGY: "REGR_AVGY" >
+|   < REGR_COUNT: "REGR_COUNT" >
+|   < REGR_INTERCEPT: "REGR_INTERCEPT" >
+|   < REGR_R2: "REGR_R2" >
+|   < REGR_SLOPE: "REGR_SLOPE" >
+|   < REGR_SXX: "REGR_SXX" >
+|   < REGR_SXY: "REGR_SXY" >
+|   < REGR_SYY: "REGR_SYY" >
+|   < RELATIVE: "RELATIVE" >
+|   < RELEASE: "RELEASE" >
+|   < REPEATABLE: "REPEATABLE" >
+|   < REPLACE: "REPLACE" >
+|   < RESET: "RESET" >
+|   < RESPECT: "RESPECT" >
+|   < RESTART: "RESTART" >
+|   < RESTRICT: "RESTRICT" >
+|   < RESULT: "RESULT" >
+|   < RETURN: "RETURN" >
+|   < RETURNED_CARDINALITY: "RETURNED_CARDINALITY" >
+|   < RETURNED_LENGTH: "RETURNED_LENGTH" >
+|   < RETURNED_OCTET_LENGTH: "RETURNED_OCTET_LENGTH" >
+|   < RETURNED_SQLSTATE: "RETURNED_SQLSTATE" >
+|   < RETURNING: "RETURNING" >
+|   < RETURNS: "RETURNS" >
+|   < REVOKE: "REVOKE" >
+|   < RIGHT: "RIGHT" >
+|   < RLIKE: "RLIKE" >
+|   < ROLE: "ROLE" >
+|   < ROLLBACK: "ROLLBACK" >
+|   < ROLLUP: "ROLLUP" >
+|   < ROUTINE: "ROUTINE" >
+|   < ROUTINE_CATALOG: "ROUTINE_CATALOG" >
+|   < ROUTINE_NAME: "ROUTINE_NAME" >
+|   < ROUTINE_SCHEMA: "ROUTINE_SCHEMA" >
+|   < ROW: "ROW" >
+|   < ROW_COUNT: "ROW_COUNT" >
+|   < ROW_NUMBER: "ROW_NUMBER" >
+|   < ROWS: "ROWS" >
+|   < RUNNING: "RUNNING" >
+|   < SATURDAY: "SATURDAY" >
+|   < SAVEPOINT: "SAVEPOINT" >
+|   < SCALAR: "SCALAR" >
+|   < SCALE: "SCALE" >
+|   < SCHEMA: "SCHEMA" >
+|   < SCHEMA_NAME: "SCHEMA_NAME" >
+|   < SCOPE: "SCOPE" >
+|   < SCOPE_CATALOGS: "SCOPE_CATALOGS" >
+|   < SCOPE_NAME: "SCOPE_NAME" >
+|   < SCOPE_SCHEMA: "SCOPE_SCHEMA" >
+|   < SCROLL: "SCROLL" >
+|   < SEARCH: "SEARCH" >
+|   < SECOND: "SECOND" >
+|   < SECONDS: "SECONDS" >
+|   < SECTION: "SECTION" >
+|   < SECURITY: "SECURITY" >
+|   < SEEK: "SEEK" >
+|   < SELECT: "SELECT" > { afterTableName(); }
+|   < SELF: "SELF" >
+|   < SENSITIVE: "SENSITIVE" >
+|   < SEPARATOR: "SEPARATOR" >
+|   < SEQUENCE: "SEQUENCE" >
+|   < SERIALIZABLE: "SERIALIZABLE" >
+|   < SERVER: "SERVER" >
+|   < SERVER_NAME: "SERVER_NAME" >
+|   < SESSION: "SESSION" >
+|   < SESSION_USER: "SESSION_USER" >
+|   < SET: "SET" > { afterTableName(); }
+|   < SETS: "SETS" >
+|   < SET_MINUS: "MINUS">
+|   < SHOW: "SHOW" >
+|   < SIMILAR: "SIMILAR" >
+|   < SIMPLE: "SIMPLE" >
+|   < SIZE: "SIZE" >
+|   < SKIP_: "SKIP" >
+|   < SMALLINT: "SMALLINT" >
+|   < SOME: "SOME" >
+|   < SOURCE: "SOURCE" >
+|   < SPACE: "SPACE" >
+|   < SPECIFIC: "SPECIFIC" >
+|   < SPECIFIC_NAME: "SPECIFIC_NAME" >
+|   < SPECIFICTYPE: "SPECIFICTYPE" >
+|   < SQL: "SQL" >
+|   < SQLEXCEPTION: "SQLEXCEPTION" >
+|   < SQLSTATE: "SQLSTATE" >
+|   < SQLWARNING: "SQLWARNING" >
+|   < SQL_BIGINT: "SQL_BIGINT" >
+|   < SQL_BINARY: "SQL_BINARY" >
+|   < SQL_BIT: "SQL_BIT" >
+|   < SQL_BLOB: "SQL_BLOB" >
+|   < SQL_BOOLEAN: "SQL_BOOLEAN" >
+|   < SQL_CHAR: "SQL_CHAR" >
+|   < SQL_CLOB: "SQL_CLOB" >
+|   < SQL_DATE: "SQL_DATE" >
+|   < SQL_DECIMAL: "SQL_DECIMAL" >
+|   < SQL_DOUBLE: "SQL_DOUBLE" >
+|   < SQL_FLOAT: "SQL_FLOAT" >
+|   < SQL_INTEGER: "SQL_INTEGER" >
+|   < SQL_INTERVAL_DAY: "SQL_INTERVAL_DAY" >
+|   < SQL_INTERVAL_DAY_TO_HOUR: "SQL_INTERVAL_DAY_TO_HOUR" >
+|   < SQL_INTERVAL_DAY_TO_MINUTE: "SQL_INTERVAL_DAY_TO_MINUTE" >
+|   < SQL_INTERVAL_DAY_TO_SECOND: "SQL_INTERVAL_DAY_TO_SECOND" >
+|   < SQL_INTERVAL_HOUR: "SQL_INTERVAL_HOUR" >
+|   < SQL_INTERVAL_HOUR_TO_MINUTE: "SQL_INTERVAL_HOUR_TO_MINUTE" >
+|   < SQL_INTERVAL_HOUR_TO_SECOND: "SQL_INTERVAL_HOUR_TO_SECOND" >
+|   < SQL_INTERVAL_MINUTE: "SQL_INTERVAL_MINUTE" >
+|   < SQL_INTERVAL_MINUTE_TO_SECOND: "SQL_INTERVAL_MINUTE_TO_SECOND" >
+|   < SQL_INTERVAL_MONTH: "SQL_INTERVAL_MONTH" >
+|   < SQL_INTERVAL_SECOND: "SQL_INTERVAL_SECOND" >
+|   < SQL_INTERVAL_YEAR: "SQL_INTERVAL_YEAR" >
+|   < SQL_INTERVAL_YEAR_TO_MONTH: "SQL_INTERVAL_YEAR_TO_MONTH" >
+|   < SQL_LONGVARBINARY: "SQL_LONGVARBINARY" >
+|   < SQL_LONGVARCHAR: "SQL_LONGVARCHAR" >
+|   < SQL_LONGVARNCHAR: "SQL_LONGVARNCHAR" >
+|   < SQL_NCHAR: "SQL_NCHAR" >
+|   < SQL_NCLOB: "SQL_NCLOB" >
+|   < SQL_NUMERIC: "SQL_NUMERIC" >
+|   < SQL_NVARCHAR: "SQL_NVARCHAR" >
+|   < SQL_REAL: "SQL_REAL" >
+|   < SQL_SMALLINT: "SQL_SMALLINT" >
+|   < SQL_TIME: "SQL_TIME" >
+|   < SQL_TIMESTAMP: "SQL_TIMESTAMP" >
+|   < SQL_TINYINT: "SQL_TINYINT" >
+|   < SQL_TSI_DAY: "SQL_TSI_DAY" >
+|   < SQL_TSI_FRAC_SECOND: "SQL_TSI_FRAC_SECOND" >
+|   < SQL_TSI_HOUR: "SQL_TSI_HOUR" >
+|   < SQL_TSI_MICROSECOND: "SQL_TSI_MICROSECOND" >
+|   < SQL_TSI_MINUTE: "SQL_TSI_MINUTE" >
+|   < SQL_TSI_MONTH: "SQL_TSI_MONTH" >
+|   < SQL_TSI_QUARTER: "SQL_TSI_QUARTER" >
+|   < SQL_TSI_SECOND: "SQL_TSI_SECOND" >
+|   < SQL_TSI_WEEK: "SQL_TSI_WEEK" >
+|   < SQL_TSI_YEAR: "SQL_TSI_YEAR" >
+|   < SQL_VARBINARY: "SQL_VARBINARY" >
+|   < SQL_VARCHAR: "SQL_VARCHAR" >
+|   < SQRT: "SQRT" >
+|   < START: "START" >
+|   < STATE: "STATE" >
+|   < STATEMENT: "STATEMENT" >
+|   < STATIC: "STATIC" >
+|   < STDDEV_POP: "STDDEV_POP" >
+|   < STDDEV_SAMP: "STDDEV_SAMP" >
+|   < STREAM: "STREAM" >
+|   < STRING_AGG: "STRING_AGG" >
+|   < STRUCTURE: "STRUCTURE" >
+|   < STYLE: "STYLE" >
+|   < SUBCLASS_ORIGIN: "SUBCLASS_ORIGIN" >
+|   < SUBMULTISET: "SUBMULTISET" >
+|   < SUBSET: "SUBSET" >
+|   < SUBSTITUTE: "SUBSTITUTE" >
+|   < SUBSTRING: "SUBSTRING" >
+|   < SUBSTRING_REGEX: "SUBSTRING_REGEX" >
+|   < SUCCEEDS: "SUCCEEDS" >
+|   < SUM: "SUM" >
+|   < SUNDAY: "SUNDAY" >
+|   < SYMMETRIC: "SYMMETRIC" >
+|   < SYSTEM: "SYSTEM" >
+|   < SYSTEM_TIME: "SYSTEM_TIME" >
+|   < SYSTEM_USER: "SYSTEM_USER" >
+|   < TABLE: "TABLE" > { beforeTableName(); }
+|   < TABLE_NAME: "TABLE_NAME" >
+|   < TABLESAMPLE: "TABLESAMPLE" >
+|   < TEMPORARY: "TEMPORARY" >
+|   < THEN: "THEN" >
+|   < THURSDAY: "THURSDAY" >
+|   < TIES: "TIES" >
+|   < TIME: "TIME" >
+|   < TIME_DIFF: "TIME_DIFF" >
+|   < TIME_TRUNC: "TIME_TRUNC" >
+|   < TIMESTAMP: "TIMESTAMP" >
+|   < TIMESTAMPADD: "TIMESTAMPADD" >
+|   < TIMESTAMPDIFF: "TIMESTAMPDIFF" >
+|   < TIMESTAMP_DIFF: "TIMESTAMP_DIFF" >
+|   < TIMESTAMP_TRUNC: "TIMESTAMP_TRUNC" >
+|   < TIMEZONE_HOUR: "TIMEZONE_HOUR" >
+|   < TIMEZONE_MINUTE: "TIMEZONE_MINUTE" >
+|   < TINYINT: "TINYINT" >
+|   < TO: "TO" >
+|   < TOP_LEVEL_COUNT: "TOP_LEVEL_COUNT" >
+|   < TRAILING: "TRAILING" >
+|   < TRANSACTION: "TRANSACTION" >
+|   < TRANSACTIONS_ACTIVE: "TRANSACTIONS_ACTIVE" >
+|   < TRANSACTIONS_COMMITTED: "TRANSACTIONS_COMMITTED" >
+|   < TRANSACTIONS_ROLLED_BACK: "TRANSACTIONS_ROLLED_BACK" >
+|   < TRANSFORM: "TRANSFORM" >
+|   < TRANSFORMS: "TRANSFORMS" >
+|   < TRANSLATE: "TRANSLATE" >
+|   < TRANSLATE_REGEX: "TRANSLATE_REGEX" >
+|   < TRANSLATION: "TRANSLATION" >
+|   < TREAT: "TREAT" >
+|   < TRIGGER: "TRIGGER" >
+|   < TRIGGER_CATALOG: "TRIGGER_CATALOG" >
+|   < TRIGGER_NAME: "TRIGGER_NAME" >
+|   < TRIGGER_SCHEMA: "TRIGGER_SCHEMA" >
+|   < TRIM: "TRIM" >
+|   < TRIM_ARRAY: "TRIM_ARRAY" >
+|   < TRUE: "TRUE" >
+|   < TRUNCATE: "TRUNCATE" >
+|   < TUESDAY: "TUESDAY" >
+|   < TUMBLE: "TUMBLE" >
+|   < TYPE: "TYPE" >
+|   < UESCAPE: "UESCAPE" >
+|   < UNBOUNDED: "UNBOUNDED" >
+|   < UNCOMMITTED: "UNCOMMITTED" >
+|   < UNCONDITIONAL: "UNCONDITIONAL" >
+|   < UNDER: "UNDER" >
+|   < UNION: "UNION" >
+|   < UNIQUE: "UNIQUE" >
+|   < UNKNOWN: "UNKNOWN" >
+|   < UNPIVOT: "UNPIVOT" >
+|   < UNNAMED: "UNNAMED" >
+|   < UNNEST: "UNNEST" >
+|   < UPDATE: "UPDATE" > { beforeTableName(); }
+|   < UPPER: "UPPER" >
+|   < UPSERT: "UPSERT" >
+|   < USAGE: "USAGE" >
+|   < USER: "USER" >
+|   < USER_DEFINED_TYPE_CATALOG: "USER_DEFINED_TYPE_CATALOG" >
+|   < USER_DEFINED_TYPE_CODE: "USER_DEFINED_TYPE_CODE" >
+|   < USER_DEFINED_TYPE_NAME: "USER_DEFINED_TYPE_NAME" >
+|   < USER_DEFINED_TYPE_SCHEMA: "USER_DEFINED_TYPE_SCHEMA" >
+|   < USING: "USING" >
+|   < UTF8: "UTF8" >
+|   < UTF16: "UTF16" >
+|   < UTF32: "UTF32" >
+|   < VALUE: "VALUE" >
+|   < VALUES: "VALUES" > { afterTableName(); }
+|   < VALUE_OF: "VALUE_OF" >
+|   < VAR_POP: "VAR_POP" >
+|   < VAR_SAMP: "VAR_SAMP" >
+|   < VARBINARY: "VARBINARY" >
+|   < VARCHAR: "VARCHAR" >
+|   < VARYING: "VARYING" >
+|   < VERSION: "VERSION" >
+|   < VERSIONING: "VERSIONING" >
+|   < VIEW: "VIEW" >
+|   < WEDNESDAY: "WEDNESDAY" >
+|   < WEEK: "WEEK" >
+|   < WEEKS: "WEEKS" >
+|   < WHEN: "WHEN" >
+|   < WHENEVER: "WHENEVER" >
+|   < WHERE: "WHERE" >
+|   < WIDTH_BUCKET: "WIDTH_BUCKET" >
+|   < WINDOW: "WINDOW" >
+|   < WITH: "WITH" >
+|   < WITHIN: "WITHIN" >
+|   < WITHOUT: "WITHOUT" >
+|   < WORK: "WORK" >
+|   < WRAPPER: "WRAPPER" >
+|   < WRITE: "WRITE" >
+|   < XML: "XML" >
+|   < YEAR: "YEAR" >
+|   < YEARS: "YEARS" >
+|   < ZONE: "ZONE" >
+<#-- additional parser keywords are included here -->
+<#list (parser.keywords!default.parser.keywords) as keyword>
+|   < ${keyword}: "${keyword}" >
+</#list>
+}
+
+/**
+ * Parses a non-reserved keyword for use as an identifier.
+ *
+ * <p>The method is broken up into several sub-methods; without this
+ * decomposition, parsers such as Babel with more than ~1,000 non-reserved
+ * keywords would generate such deeply nested 'if' statements that javac would
+ * fail with a {@link StackOverflowError}.
+ *
+ * <p>The list is generated from the FMPP config data. To add or remove
+ * keywords, modify config.fmpp. For parsers except Babel, make sure that
+ * keywords are not reserved by the SQL standard.
+ *
+ * @see Glossary#SQL2003 SQL:2003 Part 2 Section 5.2
+ */
+String NonReservedKeyWord() :
+{
+}
+{
+    (
+        NonReservedKeyWord0of3()
+    |   NonReservedKeyWord1of3()
+    |   NonReservedKeyWord2of3()
+    )
+    {
+        return unquotedIdentifier();
+    }
+}
+
+/** @see #NonReservedKeyWord */
+void NonReservedKeyWord0of3() :
+{
+}
+{
+    (
+<#list (parser.nonReservedKeywords!default.parser.nonReservedKeywords) + (parser.nonReservedKeywordsToAdd!default.parser.nonReservedKeywordsToAdd) as keyword>
+<#if keyword?index == 0>
+        <${keyword}>
+<#elseif keyword?index % 3 == 0>
+    |   <${keyword}>
+</#if>
+</#list>
+    )
+}
+
+/** @see #NonReservedKeyWord */
+void NonReservedKeyWord1of3() :
+{
+}
+{
+    (
+<#list (parser.nonReservedKeywords!default.parser.nonReservedKeywords) + (parser.nonReservedKeywordsToAdd!default.parser.nonReservedKeywordsToAdd) as keyword>
+<#if keyword?index == 1>
+        <${keyword}>
+<#elseif keyword?index % 3 == 1>
+    |   <${keyword}>
+</#if>
+</#list>
+    )
+}
+
+/** @see #NonReservedKeyWord */
+void NonReservedKeyWord2of3() :
+{
+}
+{
+    (
+<#list (parser.nonReservedKeywords!default.parser.nonReservedKeywords) + (parser.nonReservedKeywordsToAdd!default.parser.nonReservedKeywordsToAdd) as keyword>
+<#if keyword?index == 2>
+        <${keyword}>
+<#elseif keyword?index % 3 == 2>
+    |   <${keyword}>
+</#if>
+</#list>
+    )
+}
+
+/* LITERALS */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < UNSIGNED_INTEGER_LITERAL: (["0"-"9"])+ >
+|
+    < APPROX_NUMERIC_LITERAL:
+    (<UNSIGNED_INTEGER_LITERAL> | <DECIMAL_NUMERIC_LITERAL>) <EXPONENT> >
+|
+    < DECIMAL_NUMERIC_LITERAL:
+    (["0"-"9"])+(".")?(["0"-"9"])*
+    | "."(["0"-"9"])+
+    >
+|
+    < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
+|
+    < #HEXDIGIT: ["0"-"9","a"-"f","A"-"F"] >
+|
+    < #WHITESPACE:
+    [ " ","\t","\n","\r","\f" ]
+    >
+|
+    /* To improve error reporting, we allow all kinds of characters,
+     * not just hexits, in a binary string literal. */
+    < BINARY_STRING_LITERAL: ["x","X"] <QUOTE> ( (~["'"]) | ("''"))* <QUOTE> >
+}
+
+// All databases except BigQuery support standard single-quoted literals,
+// which use single-quote as the escape character.
+<DEFAULT, DQID, BTID> TOKEN :
+{
+    < QUOTED_STRING: <QUOTE> ( (~["'"]) | ("''"))* <QUOTE> >
+|
+    < PREFIXED_STRING_LITERAL: ("_" <CHARSETNAME> | "N") <QUOTED_STRING> >
+|
+    < UNICODE_STRING_LITERAL: "U" "&" <QUOTED_STRING> >
+|
+    < C_STYLE_ESCAPED_STRING_LITERAL: "E" <QUOTE> ( (~["'", "\\"]) | ("\\" ~[]) | "''")* <QUOTE> >
+|
+    < #CHARSETNAME: (["a"-"z","A"-"Z","0"-"9"])
+    (["a"-"z","A"-"Z","0"-"9",":",".","-","_"])*
+    >
+}
+
+// BigQuery supports single- and double-quoted literals with back-slash
+// as the escape character.
+<BQID, BQHID> TOKEN :
+{
+    // BigQuery-style double-quoted string, escaped using backslash
+    < BIG_QUERY_DOUBLE_QUOTED_STRING:
+      <DOUBLE_QUOTE> ( (~["\\", "\""]) | ("\\" ~[]) )* <DOUBLE_QUOTE>
+    >
+|
+    // BigQuery-style single-quoted string, escaped using backslash
+    < BIG_QUERY_QUOTED_STRING:
+      <QUOTE> ( (~["\\", "'"]) | ("\\" ~[]) )* <QUOTE>
+    >
+}
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < UNICODE_QUOTED_ESCAPE_CHAR:
+    <QUOTE>
+    (~["0"-"9","a"-"f","A"-"F","+","\""," ","\t","\n","\r","\f"])
+    <QUOTE>
+    >
+}
+
+/* SEPARATORS */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < LPAREN: "(">
+|   < RPAREN: ")">
+<#if (parser.includeBraces!default.parser.includeBraces) >
+|   < LBRACE_D: "{" (" ")* ["d","D"] >
+|   < LBRACE_T: "{" (" ")* ["t","T"] >
+|   < LBRACE_TS: "{" (" ")* ["t","T"] ["s","S"] >
+|   < LBRACE_FN: "{" (" ")* ["f","F"] ["n","N"] >
+|   < LBRACE: "{" >
+|   < RBRACE: "}" >
+<#else>
+<#include "/@includes/braces.ftl" />
+</#if>
+|   < LBRACKET: "[" >
+|   < RBRACKET: "]" >
+|   < SEMICOLON: ";" >
+|   < DOT: "." >
+|   < COMMA: "," >
+}
+
+/* OPERATORS */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < EQ: "=" >
+|   < GT: ">" >
+|   < LT: "<" >
+|   < HOOK: "?" >
+|   < COLON: ":" >
+|   < LE: "<=" >
+|   < GE: ">=" >
+|   < NE: "<>" >
+|   < NE2: "!=" >
+|   < PLUS: "+" >
+|   < MINUS: "-" >
+|   < STAR: "*" >
+|   < SLASH: "/" >
+|   < PERCENT_REMAINDER: "%" >
+|   < CONCAT: "||" >
+|   < NAMED_ARGUMENT_ASSIGNMENT: "=>" >
+|   < DOUBLE_PERIOD: ".." >
+|   < QUOTE: "'" >
+|   < DOUBLE_QUOTE: "\"" >
+|   < VERTICAL_BAR: "|" >
+|   < CARET: "^" >
+|   < DOLLAR: "$" >
+<#list (parser.binaryOperatorsTokens!default.parser.binaryOperatorsTokens) as operator>
+|   ${operator}
+</#list>
+}
+
+
+/*****************************************
+ * Lexical Descriptions                  *
+ *****************************************/
+
+TOKEN_MGR_DECLS : {
+    final List<Integer> lexicalStateStack = new ArrayList<Integer>();
+
+    void pushState() {
+      lexicalStateStack.add(curLexState);
+    }
+
+    void popState() {
+      SwitchTo(lexicalStateStack.remove(lexicalStateStack.size() - 1));
+    }
+
+    void beforeTableName() {
+      if (curLexState == BQID) {
+        pushState();
+        SwitchTo(BQHID);
+      }
+    }
+
+    void afterTableName() {
+      if (curLexState == BQHID) {
+        popState();
+      }
+    }
+
+<#if (parser.includeAdditionalDeclarations!default.parser.includeAdditionalDeclarations)>
+  <#include "/@includes/tokenManagerDeclarations.ftl" />
+</#if>
+}
+
+/*
+Lexical states:
+
+DEFAULT: Identifiers are quoted in brackets, e.g. [My Identifier]
+DQID:    Identifiers are double-quoted, e.g. "My Identifier"
+BTID:    Identifiers are enclosed in back-ticks, escaped using back-ticks,
+         e.g. `My ``Quoted`` Identifier`
+BQID:    Identifiers are enclosed in back-ticks, escaped using backslash,
+         e.g. `My \`Quoted\` Identifier`,
+         and with the potential to shift into BQHID in contexts where table
+         names are expected, and thus allow hyphen-separated identifiers as
+         part of table names
+BQHID:   Identifiers are enclosed in back-ticks, escaped using backslash,
+         e.g. `My \`Quoted\` Identifier`
+         and unquoted identifiers may contain hyphens, e.g. foo-bar
+IN_SINGLE_LINE_COMMENT:
+IN_FORMAL_COMMENT:
+IN_MULTI_LINE_COMMENT:
+
+DEFAULT, DQID, BTID, BQID are the 4 'normal states'. Behavior is identical
+except for how quoted identifiers are recognized.
+
+The BQHID state exists only at the start of a table name (e.g. immediately after
+FROM or INSERT INTO). As soon as an identifier is seen, the state shifts back
+to BTID.
+
+After a comment has completed, the lexer returns to the previous state, one
+of the 'normal states'.
+*/
+
+/* WHITE SPACE */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> SKIP :
+{
+    " "
+|   "\t"
+|   "\n"
+|   "\r"
+|   "\f"
+}
+
+/* COMMENTS */
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < HINT_BEG: "/*+">
+|   < COMMENT_END: "*/" >
+}
+
+<DEFAULT, DQID, BTID, BQID, BQHID> MORE :
+{
+    <"/**" ~["/"]> { pushState(); } : IN_FORMAL_COMMENT
+}
+
+<DEFAULT, DQID, BTID, BQID, BQHID> MORE :
+{
+    "/*" { pushState(); } : IN_MULTI_LINE_COMMENT
+}
+
+<DEFAULT, DQID, BTID, BQID, BQHID> SKIP :
+{
+    <SINGLE_LINE_COMMENT: ("//"|"--")(~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
+}
+
+<IN_FORMAL_COMMENT>
+SPECIAL_TOKEN :
+{
+    <FORMAL_COMMENT: <COMMENT_END> > { popState(); }
+}
+
+<IN_MULTI_LINE_COMMENT>
+SPECIAL_TOKEN :
+{
+    <MULTI_LINE_COMMENT: <COMMENT_END> > { popState(); }
+}
+
+<IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
+MORE :
+{
+    < ~[] >
+}
+
+
+/* IDENTIFIERS */
+
+<DEFAULT> TOKEN :
+{
+    < BRACKET_QUOTED_IDENTIFIER:
+    "["
+    (
+        (~["]","\n","\r"])
+    |
+        ("]]")
+    )+
+    "]"
+    >
+}
+
+<DQID> TOKEN :
+{
+    < QUOTED_IDENTIFIER:
+    "\""
+    (
+        (~["\"","\n","\r"])
+    |
+        ("\"\"")
+    )+
+    "\""
+    >
+}
+
+<BTID> TOKEN :
+{
+    < BACK_QUOTED_IDENTIFIER:
+    "`"
+    (
+        (~["`","\n","\r"])
+    |
+        ("``")
+    )+
+    "`"
+    >
+}
+
+<BQID, BQHID> TOKEN :
+{
+    // BigQuery-style backtick-quoted identifier, escaped using backslash
+    < BIG_QUERY_BACK_QUOTED_IDENTIFIER:
+    "`"
+    (
+        (~["\\", "`"])
+    |
+        ("\\" ~[])
+    )*
+    "`"
+    >
+}
+
+<BQHID> TOKEN :
+{
+    // Per BigQuery: "Project IDs must contain 6-63 lowercase letters, digits,
+    // or dashes. IDs must start with a letter and may not end with a dash."
+    // We do not restrict length, or prevent identifiers from ending in a dash.
+    < HYPHENATED_IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|"-")* > { popState(); }
+}
+
+<DEFAULT, DQID, BTID, BQID> TOKEN :
+{
+    < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
+}
+
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < COLLATION_ID:
+    (<LETTER>|<DIGIT>)+ (<LETTER>|<DIGIT>|":"|"."|"-"|"_")*
+    "$"
+    (<LETTER>|"_")+
+    ("$" (<LETTER>|<DIGIT>|"_")+)?
+    >
+|
+    < UNICODE_QUOTED_IDENTIFIER: "U" "&" <QUOTED_IDENTIFIER> >
+|
+    < #LETTER:
+    [
+        "\u0024",
+        "\u0041"-"\u005a",
+        "\u005f",
+        "\u0061"-"\u007a",
+        "\u00c0"-"\u00d6",
+        "\u00d8"-"\u00f6",
+        "\u00f8"-"\u00ff",
+        "\u0100"-"\u1fff",
+        "\u3040"-"\u318f",
+        "\u3300"-"\u337f",
+        "\u3400"-"\u3d2d",
+        "\u4e00"-"\u9fff",
+        "\uf900"-"\ufaff"
+    ]
+    >
+|
+    < #DIGIT:
+    [
+        "\u0030"-"\u0039",
+        "\u0660"-"\u0669",
+        "\u06f0"-"\u06f9",
+        "\u0966"-"\u096f",
+        "\u09e6"-"\u09ef",
+        "\u0a66"-"\u0a6f",
+        "\u0ae6"-"\u0aef",
+        "\u0b66"-"\u0b6f",
+        "\u0be7"-"\u0bef",
+        "\u0c66"-"\u0c6f",
+        "\u0ce6"-"\u0cef",
+        "\u0d66"-"\u0d6f",
+        "\u0e50"-"\u0e59",
+        "\u0ed0"-"\u0ed9",
+        "\u1040"-"\u1049"
+    ]
+    >
+}
+
+/* Special token to throw a wrench in the works. It is never valid in SQL,
+   and so when it occurs, it causes the parser to print which tokens would
+   have been valid at that point. Used by SqlAdvisor. */
+<DEFAULT, DQID, BTID, BQID, BQHID> TOKEN :
+{
+    < BEL:
+    [
+        "\u0007"
+    ]
+    >
+}
+
+/**
+ * Defines a production which can never be accepted by the parser.
+ * In effect, it tells the parser, "If you got here, you've gone too far."
+ * It is used as the default production for parser extension points;
+ * derived parsers replace it with a real production when they want to
+ * implement a particular extension point.
+ */
+void UnusedExtension() :
+{
+}
+{
+    (
+        LOOKAHEAD({false}) <ZONE>
+    )
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlSelectBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlSelectBuilder.java
index a665390..07dcf01 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlSelectBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlSelectBuilder.java
@@ -31,6 +31,7 @@
   private SqlNodeList groupBy;
   private SqlNode having;
   private SqlNodeList windowDecls;
+  private SqlNode qualify;
   private SqlNodeList orderBy;
   private SqlNode offset;
   private SqlNode fetch;
@@ -76,6 +77,11 @@
     return this;
   }
 
+  public SqlSelectBuilder qualify(SqlNode qualify) {
+    this.qualify = qualify;
+    return this;
+  }
+
   public SqlSelectBuilder orderBy(SqlNodeList orderBy) {
     this.orderBy = orderBy;
     return this;
@@ -98,7 +104,7 @@
 
   public SqlSelect build() {
     return new SqlSelect(parserPosition, keywordList, selectList, from,
-      where, groupBy, having, windowDecls, orderBy, offset, fetch, hints);
+      where, groupBy, having, windowDecls, qualify, orderBy, offset, fetch, hints);
   }
 
 }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java
index 6aca6ba..2d006d3 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java
@@ -66,7 +66,7 @@
         .put(SqlAnalyzeTable.class, arrayOf(D, D, E, D))
         .put(SqlMetastoreAnalyzeTable.class, arrayOf(D, E, D, D, D))
         .put(SqlDropTableMetadata.class, arrayOf(D, D, D))
-        .put(SqlSelect.class, arrayOf(D, E, D, E, E, E, E, E, D, D, D))
+        .put(SqlSelect.class, arrayOf(D, E, D, E, E, E, E, E, E, D, D, D))
         .put(SqlCreateTable.class, arrayOf(D, D, D, E, D, D))
         .put(SqlCreateView.class, arrayOf(D, E, E, D))
         .put(DrillSqlDescribeTable.class, arrayOf(D, D, E))
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
index 19303cb..bcc504e 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
@@ -19,9 +19,14 @@
 
 import org.apache.drill.test.ClusterFixture;
 import org.apache.drill.test.ClusterTest;
+import org.apache.drill.test.rowSet.RowSetComparison;
 import org.apache.drill.categories.UnlikelyTest;
 import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.common.types.TypeProtos.MinorType;
+import org.apache.drill.exec.physical.rowSet.RowSet;
 import org.apache.drill.exec.proto.UserBitShared;
+import org.apache.drill.exec.record.metadata.SchemaBuilder;
+import org.apache.drill.exec.record.metadata.TupleMetadata;
 import org.apache.drill.exec.work.foreman.SqlUnsupportedException;
 import org.apache.drill.exec.work.foreman.UnsupportedFunctionException;
 
@@ -1128,4 +1133,40 @@
         .build()
         .run();
   }
+
+  @Test
+  public void testWindowFunctionWithQualifyClause() throws Exception {
+    String query = "select employee_id, full_name, birth_date " +
+        "from cp.`employee.json` " +
+        "qualify row_number() over (order by employee_id) between 5 and 7";
+
+    String[] expectedPlan = {
+      "Filter\\(condition=\\[SEARCH\\(\\$\\d, Sarg\\[\\[5..7\\]\\]\\)\\]\\)",
+      "Window\\(.*?\\[window\\(order by \\[\\d\\] rows between UNBOUNDED PRECEDING and CURRENT ROW aggs \\[ROW_NUMBER\\(\\)\\]\\)\\]\\)"
+    };
+
+    client.queryBuilder()
+      .sql(query)
+      .planMatcher()
+      .include(expectedPlan)
+      .exclude(new String[]{})
+      .match();
+
+    RowSet results = queryBuilder().sql(query).rowSet();
+
+    TupleMetadata expectedSchema = new SchemaBuilder()
+      .addNullable("employee_id", MinorType.BIGINT)
+      .addNullable("full_name", MinorType.VARCHAR)
+      .addNullable("birth_date", MinorType.VARCHAR)
+      .buildSchema();
+
+    RowSet expected = client.rowSetBuilder(expectedSchema)
+       .addRow(6, "Roberta Damstra", "1942-10-08")
+       .addRow(7, "Rebecca Kanagaki", "1949-03-27")
+       .addRow(8, "Kim Brunner", "1922-08-10")
+       .build();
+
+    new RowSetComparison(expected).verifyAndClearAll(results);
+
+  }
 }
diff --git a/pom.xml b/pom.xml
index c9d852d..bc8f927 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
   <parent>
     <groupId>org.apache</groupId>
     <artifactId>apache</artifactId>
-    <version>24</version>
+    <version>29</version>
     <relativePath />
   </parent>
 
@@ -54,7 +54,7 @@
     <parquet.version>1.12.2</parquet.version>
     <parquet.format.version>2.8.0</parquet.format.version>
     <calcite.groupId>org.apache.calcite</calcite.groupId>
-    <calcite.version>1.33.0</calcite.version>
+    <calcite.version>1.34.0</calcite.version>
     <avatica.version>1.23.0</avatica.version>
     <janino.version>3.1.8</janino.version>
     <sqlline.version>1.12.0</sqlline.version>
@@ -1063,10 +1063,6 @@
             <doclint>none</doclint>
           </configuration>
         </plugin>
-
-        <!--Note: apache-21.pom has the latest versions of apache-rat-plugin, maven-dependency-plugin and
-        maven-clean-plugin. Once the newer versions are needed and present in maven repo, the plugins versions can be
-        overridden here-->
       </plugins>
     </pluginManagement>
   </build>
