/*
 * #%L
 * JSQLParser library
 * %%
 * Copyright (C) 2004 - 2014 JSQLParser
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
 * #L%
 */

options{
    IGNORE_CASE=true ;
    STATIC=false;
	DEBUG_PARSER=false;
    DEBUG_LOOKAHEAD=false;
    DEBUG_TOKEN_MANAGER=false;
//  FORCE_LA_CHECK=true;
    UNICODE_INPUT=true;
}

PARSER_BEGIN(CCJSqlParser)
/*
 * #%L
 * JSQLParser library
 * %%
 * Copyright (C) 2004 - 2014 JSQLParser
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
 * #L%
 */

package net.sf.jsqlparser.parser;

import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.arithmetic.*;
import net.sf.jsqlparser.expression.operators.conditional.*;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.*;
import net.sf.jsqlparser.statement.*;
import net.sf.jsqlparser.statement.alter.*;
import net.sf.jsqlparser.statement.create.index.*;
import net.sf.jsqlparser.statement.create.table.*;
import net.sf.jsqlparser.statement.create.view.*;
import net.sf.jsqlparser.statement.delete.*;
import net.sf.jsqlparser.statement.drop.*;
import net.sf.jsqlparser.statement.insert.*;
import net.sf.jsqlparser.statement.replace.*;
import net.sf.jsqlparser.statement.execute.*;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.truncate.*;
import net.sf.jsqlparser.statement.update.*;

import java.util.*;

/**
 * The parser generated by JavaCC
 */
public class CCJSqlParser {
	private void linkAST(ASTNodeAccess access, SimpleNode node) {
        access.setASTNode(node);
        node.jjtSetValue(access);
    }

    public Node getASTRoot() {
        return jjtree.rootNode();
    }
}

PARSER_END(CCJSqlParser)

SKIP:
{
    " "
|   "\t"
|   "\r"
|   "\n"
}

TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
{
    <K_AS: "AS">
|   <K_BY:"BY">
|   <K_DO:"DO">
|   <K_IS:"IS">
|   <K_IN:"IN">
|   <K_OR:"OR">
|   <K_ON:"ON">
|   <K_ALL:"ALL">
|   <K_AND:"AND">
|   <K_ANY:"ANY">
|   <K_KEY:"KEY">
|   <K_NOT:"NOT">
|   <K_SET:"SET">
|   <K_ASC:"ASC">
|   <K_TOP:"TOP">
|   <K_PERCENT:"PERCENT">
|   <K_END:"END">
|   <K_DESC:"DESC">
|   <K_INTO:"INTO">
|   <K_NULL:"NULL">
|   <K_LIKE:"LIKE">
|   <K_ILIKE:"ILIKE">
|   <K_DROP:"DROP">
|   <K_JOIN:"JOIN">
|   <K_LEFT:"LEFT">
|   <K_CROSS:"CROSS">
|   <K_FROM:"FROM">
|   <K_OPEN:"OPEN">
|   <K_CASE:"CASE">
|   <K_WHEN:"WHEN">
|   <K_THEN:"THEN">
|   <K_ELSE:"ELSE">
|   <K_SOME:"SOME">
|   <K_FULL:"FULL">
|   <K_WITH:"WITH">
|   <K_TABLE:"TABLE">
|   <K_VIEW:"VIEW">
|   <K_WHERE:"WHERE">
|   <K_FOR:"FOR">
|   <K_PIVOT:"PIVOT">
|   <K_XML:"XML">
|   <K_USING:"USING">
|   <K_UNION:"UNION">
|   <K_GROUP:"GROUP">
|   <K_BEGIN:"BEGIN">
|   <K_INDEX: "INDEX">
|   <K_INNER:"INNER">
|   <K_LIMIT:"LIMIT">
|   <K_OUTER:"OUTER">
|   <K_ORDER:"ORDER">
|   <K_RIGHT:"RIGHT">
|   <K_VALUE:"VALUE">
|   <K_DELETE:"DELETE">
|   <K_CREATE:"CREATE">
|   <K_SELECT:"SELECT">
|   <K_OFFSET:"OFFSET">
|   <K_EXISTS:"EXISTS">
|   <K_HAVING:"HAVING">
|   <K_INSERT:"INSERT">
|   <K_UPDATE:"UPDATE">
|   <K_VALUES:"VALUES">
|   <K_ESCAPE:"ESCAPE">
|   <K_PRIMARY:"PRIMARY">
|   <K_NATURAL:"NATURAL">
|   <K_REPLACE:"REPLACE">
|   <K_BETWEEN:"BETWEEN">
|   <K_TRUNCATE:"TRUNCATE">
|   <K_DISTINCT:"DISTINCT">
|   <K_INTERSECT:"INTERSECT">
|   <K_CAST:"CAST">
|   <K_EXCEPT:"EXCEPT">
|   <K_MINUS:"MINUS">
|   <K_OVER:"OVER">
|   <K_PARTITION:"PARTITION">
|   <K_EXTRACT:"EXTRACT">
|	<K_LATERAL:"LATERAL">
|	<K_MATERIALIZED:"MATERIALIZED">
|   <K_INTERVAL:"INTERVAL">
|	<K_FOREIGN:"FOREIGN">
|	<K_CONSTRAINT:"CONSTRAINT">
|	<K_REFERENCES:"REFERENCES">
|	<K_CHARACTER:"CHARACTER">
|	<K_VARYING:"VARYING">
|	<K_START:"START">
|	<K_CONNECT:"CONNECT">
|	<K_PRIOR:"PRIOR">
|   <K_NOCYCLE:"NOCYCLE">
|	<K_SIBLINGS:"SIBLINGS">
|	<K_ALTER:"ALTER">
|	<K_ADD:"ADD">
|	<K_COLUMN:"COLUMN">
|   <K_NULLS: "NULLS">
|   <K_FIRST: "FIRST">
|   <K_LAST: "LAST">
|   <K_ROWS: "ROWS">
|   <K_RANGE: "RANGE">
|   <K_UNBOUNDED: "UNBOUNDED"> 
|   <K_PRECEDING: "PRECEDING">
|   <K_FOLLOWING: "FOLLOWING">
|   <K_CURRENT: "CURRENT">
|   <K_ROW: "ROW"> 
|   <K_RETURNING: "RETURNING"> 
|   <K_BINARY: "BINARY">  
|   <K_REGEXP: "REGEXP">
|   <K_UNLOGGED: "UNLOGGED">
|   <K_EXEC: "EXEC">
|   <K_EXECUTE: "EXECUTE">
|   <K_FETCH:"FETCH">
|   <K_NEXT:"NEXT">
|   <K_ONLY:"ONLY">
|   <K_COMMIT:"COMMIT">
|   <K_UNIQUE:"UNIQUE">
|   <K_WITHIN:"WITHIN">
|   <K_IF:"IF">
|   <K_RECURSIVE:"RECURSIVE">
|   <K_OF:"OF">
|   <K_KEEP:"KEEP">
|   <K_GROUP_CONCAT:"GROUP_CONCAT">
|   <K_SEPARATOR:"SEPARATOR">
|   <K_SKIP: "SKIP">
}

TOKEN : /* Numeric Constants */
{
   < S_DOUBLE: ((<S_LONG>)? "." <S_LONG> ( ["e","E"] (["+", "-"])? <S_LONG>)?
			|
			<S_LONG> "." (["e","E"] (["+", "-"])? <S_LONG>)?
			|
			<S_LONG> ["e","E"] (["+", "-"])? <S_LONG>
			)>
  | 	< S_LONG: ( <DIGIT> )+ >
  | 	< #DIGIT: ["0" - "9"] >
  |     < S_HEX: ("x'" ( <HEX_VALUE> )+ "'" | "0x" ( <HEX_VALUE> )+ ) >
  |     < #HEX_VALUE: ["0"-"9","A"-"F"]  >
}

SPECIAL_TOKEN:
{
   < LINE_COMMENT: "--"(~["\r","\n"])*>
|  < MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
}

TOKEN:
{
<S_IDENTIFIER: <LETTER> (<PART_LETTER>)*>
|   <#LETTER: ["$","A"-"Z","_","a"-"z","\u00a2"-"\u00a5","\u00aa","\u00b5","\u00ba","\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u021f","\u0222"-"\u0233","\u0250"-"\u02ad","\u02b0"-"\u02b8","\u02bb"-"\u02c1","\u02d0"-"\u02d1","\u02e0"-"\u02e4","\u02ee","\u037a","\u0386","\u0388"-"\u038a","\u038c","\u038e"-"\u03a1","\u03a3"-"\u03ce","\u03d0"-"\u03d7","\u03da"-"\u03f3","\u0400"-"\u0481","\u048c"-"\u04c4","\u04c7"-"\u04c8","\u04cb"-"\u04cc","\u04d0"-"\u04f5","\u04f8"-"\u04f9","\u0531"-"\u0556","\u0559","\u0561"-"\u0587","\u05d0"-"\u05ea","\u05f0"-"\u05f2","\u0621"-"\u063a","\u0640"-"\u064a","\u0671"-"\u06d3","\u06d5","\u06e5"-"\u06e6","\u06fa"-"\u06fc","\u0710","\u0712"-"\u072c","\u0780"-"\u07a5","\u0905"-"\u0939","\u093d","\u0950","\u0958"-"\u0961","\u0985"-"\u098c","\u098f"-"\u0990","\u0993"-"\u09a8","\u09aa"-"\u09b0","\u09b2","\u09b6"-"\u09b9","\u09dc"-"\u09dd","\u09df"-"\u09e1","\u09f0"-"\u09f3","\u0a05"-"\u0a0a","\u0a0f"-"\u0a10","\u0a13"-"\u0a28","\u0a2a"-"\u0a30","\u0a32"-"\u0a33","\u0a35"-"\u0a36","\u0a38"-"\u0a39","\u0a59"-"\u0a5c","\u0a5e","\u0a72"-"\u0a74","\u0a85"-"\u0a8b","\u0a8d","\u0a8f"-"\u0a91","\u0a93"-"\u0aa8","\u0aaa"-"\u0ab0","\u0ab2"-"\u0ab3","\u0ab5"-"\u0ab9","\u0abd","\u0ad0","\u0ae0","\u0b05"-"\u0b0c","\u0b0f"-"\u0b10","\u0b13"-"\u0b28","\u0b2a"-"\u0b30","\u0b32"-"\u0b33","\u0b36"-"\u0b39","\u0b3d","\u0b5c"-"\u0b5d","\u0b5f"-"\u0b61","\u0b85"-"\u0b8a","\u0b8e"-"\u0b90","\u0b92"-"\u0b95","\u0b99"-"\u0b9a","\u0b9c","\u0b9e"-"\u0b9f","\u0ba3"-"\u0ba4","\u0ba8"-"\u0baa","\u0bae"-"\u0bb5","\u0bb7"-"\u0bb9","\u0c05"-"\u0c0c","\u0c0e"-"\u0c10","\u0c12"-"\u0c28","\u0c2a"-"\u0c33","\u0c35"-"\u0c39","\u0c60"-"\u0c61","\u0c85"-"\u0c8c","\u0c8e"-"\u0c90","\u0c92"-"\u0ca8","\u0caa"-"\u0cb3","\u0cb5"-"\u0cb9","\u0cde","\u0ce0"-"\u0ce1","\u0d05"-"\u0d0c","\u0d0e"-"\u0d10","\u0d12"-"\u0d28","\u0d2a"-"\u0d39","\u0d60"-"\u0d61","\u0d85"-"\u0d96","\u0d9a"-"\u0db1","\u0db3"-"\u0dbb","\u0dbd","\u0dc0"-"\u0dc6","\u0e01"-"\u0e30","\u0e32"-"\u0e33","\u0e3f"-"\u0e46","\u0e81"-"\u0e82","\u0e84","\u0e87"-"\u0e88","\u0e8a","\u0e8d","\u0e94"-"\u0e97","\u0e99"-"\u0e9f","\u0ea1"-"\u0ea3","\u0ea5","\u0ea7","\u0eaa"-"\u0eab","\u0ead"-"\u0eb0","\u0eb2"-"\u0eb3","\u0ebd","\u0ec0"-"\u0ec4","\u0ec6","\u0edc"-"\u0edd","\u0f00","\u0f40"-"\u0f47","\u0f49"-"\u0f6a","\u0f88"-"\u0f8b","\u1000"-"\u1021","\u1023"-"\u1027","\u1029"-"\u102a","\u1050"-"\u1055","\u10a0"-"\u10c5","\u10d0"-"\u10f6","\u1100"-"\u1159","\u115f"-"\u11a2","\u11a8"-"\u11f9","\u1200"-"\u1206","\u1208"-"\u1246","\u1248","\u124a"-"\u124d","\u1250"-"\u1256","\u1258","\u125a"-"\u125d","\u1260"-"\u1286","\u1288","\u128a"-"\u128d","\u1290"-"\u12ae","\u12b0","\u12b2"-"\u12b5","\u12b8"-"\u12be","\u12c0","\u12c2"-"\u12c5","\u12c8"-"\u12ce","\u12d0"-"\u12d6","\u12d8"-"\u12ee","\u12f0"-"\u130e","\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346","\u1348"-"\u135a","\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676","\u1681"-"\u169a","\u16a0"-"\u16ea","\u1780"-"\u17b3","\u17db","\u1820"-"\u1877","\u1880"-"\u18a8","\u1e00"-"\u1e9b","\u1ea0"-"\u1ef9","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d","\u1f50"-"\u1f57","\u1f59","\u1f5b","\u1f5d","\u1f5f"-"\u1f7d","\u1f80"-"\u1fb4","\u1fb6"-"\u1fbc","\u1fbe","\u1fc2"-"\u1fc4","\u1fc6"-"\u1fcc","\u1fd0"-"\u1fd3","\u1fd6"-"\u1fdb","\u1fe0"-"\u1fec","\u1ff2"-"\u1ff4","\u1ff6"-"\u1ffc","\u203f"-"\u2040","\u207f","\u20a0"-"\u20af","\u2102","\u2107","\u210a"-"\u2113","\u2115","\u2119"-"\u211d","\u2124","\u2126","\u2128","\u212a"-"\u212d","\u212f"-"\u2131","\u2133"-"\u2139","\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u3029","\u3031"-"\u3035","\u3038"-"\u303a","\u3041"-"\u3094","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c","\u3131"-"\u318e","\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c","\uac00"-"\ud7a3","\uf900"-"\ufa2d","\ufb00"-"\ufb06","\ufb13"-"\ufb17","\ufb1d","\ufb1f"-"\ufb28","\ufb2a"-"\ufb36","\ufb38"-"\ufb3c","\ufb3e","\ufb40"-"\ufb41","\ufb43"-"\ufb44","\ufb46"-"\ufbb1","\ufbd3"-"\ufd3d","\ufd50"-"\ufd8f","\ufd92"-"\ufdc7","\ufdf0"-"\ufdfb","\ufe33"-"\ufe34","\ufe4d"-"\ufe4f","\ufe69","\ufe70"-"\ufe72","\ufe74","\ufe76"-"\ufefc","\uff04","\uff21"-"\uff3a","\uff3f","\uff41"-"\uff5a","\uff65"-"\uffbe","\uffc2"-"\uffc7","\uffca"-"\uffcf","\uffd2"-"\uffd7","\uffda"-"\uffdc","\uffe0"-"\uffe1","\uffe5"-"\uffe6"]>
|   <#PART_LETTER: ["\u0000"-"\b","\u000e"-"\u001b","$","#","@","0"-"9","A"-"Z","_","a"-"z","\u007f"-"\u009f","\u00a2"-"\u00a5","\u00aa","\u00b5","\u00ba","\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u021f","\u0222"-"\u0233","\u0250"-"\u02ad","\u02b0"-"\u02b8","\u02bb"-"\u02c1","\u02d0"-"\u02d1","\u02e0"-"\u02e4","\u02ee","\u0300"-"\u034e","\u0360"-"\u0362","\u037a","\u0386","\u0388"-"\u038a","\u038c","\u038e"-"\u03a1","\u03a3"-"\u03ce","\u03d0"-"\u03d7","\u03da"-"\u03f3","\u0400"-"\u0481","\u0483"-"\u0486","\u048c"-"\u04c4","\u04c7"-"\u04c8","\u04cb"-"\u04cc","\u04d0"-"\u04f5","\u04f8"-"\u04f9","\u0531"-"\u0556","\u0559","\u0561"-"\u0587","\u0591"-"\u05a1","\u05a3"-"\u05b9","\u05bb"-"\u05bd","\u05bf","\u05c1"-"\u05c2","\u05c4","\u05d0"-"\u05ea","\u05f0"-"\u05f2","\u0621"-"\u063a","\u0640"-"\u0655","\u0660"-"\u0669","\u0670"-"\u06d3","\u06d5"-"\u06dc","\u06df"-"\u06e8","\u06ea"-"\u06ed","\u06f0"-"\u06fc","\u070f"-"\u072c","\u0730"-"\u074a","\u0780"-"\u07b0","\u0901"-"\u0903","\u0905"-"\u0939","\u093c"-"\u094d","\u0950"-"\u0954","\u0958"-"\u0963","\u0966"-"\u096f","\u0981"-"\u0983","\u0985"-"\u098c","\u098f"-"\u0990","\u0993"-"\u09a8","\u09aa"-"\u09b0","\u09b2","\u09b6"-"\u09b9","\u09bc","\u09be"-"\u09c4","\u09c7"-"\u09c8","\u09cb"-"\u09cd","\u09d7","\u09dc"-"\u09dd","\u09df"-"\u09e3","\u09e6"-"\u09f3","\u0a02","\u0a05"-"\u0a0a","\u0a0f"-"\u0a10","\u0a13"-"\u0a28","\u0a2a"-"\u0a30","\u0a32"-"\u0a33","\u0a35"-"\u0a36","\u0a38"-"\u0a39","\u0a3c","\u0a3e"-"\u0a42","\u0a47"-"\u0a48","\u0a4b"-"\u0a4d","\u0a59"-"\u0a5c","\u0a5e","\u0a66"-"\u0a74","\u0a81"-"\u0a83","\u0a85"-"\u0a8b","\u0a8d","\u0a8f"-"\u0a91","\u0a93"-"\u0aa8","\u0aaa"-"\u0ab0","\u0ab2"-"\u0ab3","\u0ab5"-"\u0ab9","\u0abc"-"\u0ac5","\u0ac7"-"\u0ac9","\u0acb"-"\u0acd","\u0ad0","\u0ae0","\u0ae6"-"\u0aef","\u0b01"-"\u0b03","\u0b05"-"\u0b0c","\u0b0f"-"\u0b10","\u0b13"-"\u0b28","\u0b2a"-"\u0b30","\u0b32"-"\u0b33","\u0b36"-"\u0b39","\u0b3c"-"\u0b43","\u0b47"-"\u0b48","\u0b4b"-"\u0b4d","\u0b56"-"\u0b57","\u0b5c"-"\u0b5d","\u0b5f"-"\u0b61","\u0b66"-"\u0b6f","\u0b82"-"\u0b83","\u0b85"-"\u0b8a","\u0b8e"-"\u0b90","\u0b92"-"\u0b95","\u0b99"-"\u0b9a","\u0b9c","\u0b9e"-"\u0b9f","\u0ba3"-"\u0ba4","\u0ba8"-"\u0baa","\u0bae"-"\u0bb5","\u0bb7"-"\u0bb9","\u0bbe"-"\u0bc2","\u0bc6"-"\u0bc8","\u0bca"-"\u0bcd","\u0bd7","\u0be7"-"\u0bef","\u0c01"-"\u0c03","\u0c05"-"\u0c0c","\u0c0e"-"\u0c10","\u0c12"-"\u0c28","\u0c2a"-"\u0c33","\u0c35"-"\u0c39","\u0c3e"-"\u0c44","\u0c46"-"\u0c48","\u0c4a"-"\u0c4d","\u0c55"-"\u0c56","\u0c60"-"\u0c61","\u0c66"-"\u0c6f","\u0c82"-"\u0c83","\u0c85"-"\u0c8c","\u0c8e"-"\u0c90","\u0c92"-"\u0ca8","\u0caa"-"\u0cb3","\u0cb5"-"\u0cb9","\u0cbe"-"\u0cc4","\u0cc6"-"\u0cc8","\u0cca"-"\u0ccd","\u0cd5"-"\u0cd6","\u0cde","\u0ce0"-"\u0ce1","\u0ce6"-"\u0cef","\u0d02"-"\u0d03","\u0d05"-"\u0d0c","\u0d0e"-"\u0d10","\u0d12"-"\u0d28","\u0d2a"-"\u0d39","\u0d3e"-"\u0d43","\u0d46"-"\u0d48","\u0d4a"-"\u0d4d","\u0d57","\u0d60"-"\u0d61","\u0d66"-"\u0d6f","\u0d82"-"\u0d83","\u0d85"-"\u0d96","\u0d9a"-"\u0db1","\u0db3"-"\u0dbb","\u0dbd","\u0dc0"-"\u0dc6","\u0dca","\u0dcf"-"\u0dd4","\u0dd6","\u0dd8"-"\u0ddf","\u0df2"-"\u0df3","\u0e01"-"\u0e3a","\u0e3f"-"\u0e4e","\u0e50"-"\u0e59","\u0e81"-"\u0e82","\u0e84","\u0e87"-"\u0e88","\u0e8a","\u0e8d","\u0e94"-"\u0e97","\u0e99"-"\u0e9f","\u0ea1"-"\u0ea3","\u0ea5","\u0ea7","\u0eaa"-"\u0eab","\u0ead"-"\u0eb9","\u0ebb"-"\u0ebd","\u0ec0"-"\u0ec4","\u0ec6","\u0ec8"-"\u0ecd","\u0ed0"-"\u0ed9","\u0edc"-"\u0edd","\u0f00","\u0f18"-"\u0f19","\u0f20"-"\u0f29","\u0f35","\u0f37","\u0f39","\u0f3e"-"\u0f47","\u0f49"-"\u0f6a","\u0f71"-"\u0f84","\u0f86"-"\u0f8b","\u0f90"-"\u0f97","\u0f99"-"\u0fbc","\u0fc6","\u1000"-"\u1021","\u1023"-"\u1027","\u1029"-"\u102a","\u102c"-"\u1032","\u1036"-"\u1039","\u1040"-"\u1049","\u1050"-"\u1059","\u10a0"-"\u10c5","\u10d0"-"\u10f6","\u1100"-"\u1159","\u115f"-"\u11a2","\u11a8"-"\u11f9","\u1200"-"\u1206","\u1208"-"\u1246","\u1248","\u124a"-"\u124d","\u1250"-"\u1256","\u1258","\u125a"-"\u125d","\u1260"-"\u1286","\u1288","\u128a"-"\u128d","\u1290"-"\u12ae","\u12b0","\u12b2"-"\u12b5","\u12b8"-"\u12be","\u12c0","\u12c2"-"\u12c5","\u12c8"-"\u12ce","\u12d0"-"\u12d6","\u12d8"-"\u12ee","\u12f0"-"\u130e","\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346","\u1348"-"\u135a","\u1369"-"\u1371","\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676","\u1681"-"\u169a","\u16a0"-"\u16ea","\u1780"-"\u17d3","\u17db","\u17e0"-"\u17e9","\u180b"-"\u180e","\u1810"-"\u1819","\u1820"-"\u1877","\u1880"-"\u18a9","\u1e00"-"\u1e9b","\u1ea0"-"\u1ef9","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d","\u1f50"-"\u1f57","\u1f59","\u1f5b","\u1f5d","\u1f5f"-"\u1f7d","\u1f80"-"\u1fb4","\u1fb6"-"\u1fbc","\u1fbe","\u1fc2"-"\u1fc4","\u1fc6"-"\u1fcc","\u1fd0"-"\u1fd3","\u1fd6"-"\u1fdb","\u1fe0"-"\u1fec","\u1ff2"-"\u1ff4","\u1ff6"-"\u1ffc","\u200c"-"\u200f","\u202a"-"\u202e","\u203f"-"\u2040","\u206a"-"\u206f","\u207f","\u20a0"-"\u20af","\u20d0"-"\u20dc","\u20e1","\u2102","\u2107","\u210a"-"\u2113","\u2115","\u2119"-"\u211d","\u2124","\u2126","\u2128","\u212a"-"\u212d","\u212f"-"\u2131","\u2133"-"\u2139","\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u302f","\u3031"-"\u3035","\u3038"-"\u303a","\u3041"-"\u3094","\u3099"-"\u309a","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c","\u3131"-"\u318e","\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c","\uac00"-"\ud7a3","\uf900"-"\ufa2d","\ufb00"-"\ufb06","\ufb13"-"\ufb17","\ufb1d"-"\ufb28","\ufb2a"-"\ufb36","\ufb38"-"\ufb3c","\ufb3e","\ufb40"-"\ufb41","\ufb43"-"\ufb44","\ufb46"-"\ufbb1","\ufbd3"-"\ufd3d","\ufd50"-"\ufd8f","\ufd92"-"\ufdc7","\ufdf0"-"\ufdfb","\ufe20"-"\ufe23","\ufe33"-"\ufe34","\ufe4d"-"\ufe4f","\ufe69","\ufe70"-"\ufe72","\ufe74","\ufe76"-"\ufefc","\ufeff","\uff04","\uff10"-"\uff19","\uff21"-"\uff3a","\uff3f","\uff41"-"\uff5a","\uff65"-"\uffbe","\uffc2"-"\uffc7","\uffca"-"\uffcf","\uffd2"-"\uffd7","\uffda"-"\uffdc","\uffe0"-"\uffe1","\uffe5"-"\uffe6","\ufff9"-"\ufffb"]>
|   < S_CHAR_LITERAL: "'" (~["'"])* "'" ("'" (~["'"])* "'")*>
|   < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])+ "\"" | ("`" (~["\n","\r","`"])+ "`") | ( "[" ~["0"-"9","]"] (~["\n","\r","]"])* "]" ) >
}

Statement Statement() #Statement: 
{ Statement stm; } 
{
    stm = SingleStatement()
    [";"]
    <EOF>
    { 
        return stm; 
    }
}

Statement SingleStatement() :
{ Statement stm;}
{
	(
    stm = Select()
    |
    stm =  Update()
    |
    stm = Insert()
    |
    stm = Delete()
    |
    stm = Replace()
    |
	stm = Alter()
	|
    LOOKAHEAD(3)
    stm = CreateIndex()
    |
	LOOKAHEAD(2)
    stm = CreateTable()
    |
	LOOKAHEAD(2)
	stm = CreateView()
	|
    stm = Drop()
    |
    stm = Truncate()
    |
    stm = Execute()
    |
    stm = Set()
    )
    { return stm; }
}

Statements Statements() #Statements : 
{ Statements stmts = new Statements();
  List<Statement> list = new ArrayList<Statement>();
  Statement stm; }
{
    stm = SingleStatement() { list.add(stm); }
     (LOOKAHEAD(2) ";" stm = SingleStatement() { list.add(stm); } )*

    [";"]
    <EOF>

    {
        stmts.setStatements(list);
        return stmts;
    }
}

SetStatement Set(): {
    String name;
    Expression value;
}
{
    <K_SET> name = RelObjectNameExt() "=" value=SimpleExpression()
    {
        return new SetStatement(name,value);
    }
}

Update Update():
{
	Update update = new Update();
    Table table = null;
	List<Table> tables = new ArrayList<Table>();
	Expression where = null;
	Column tableColumn = null;
	List<Expression> expList = new ArrayList<Expression>();
	List<Column> columns = new ArrayList<Column>();
	Expression value = null;
	FromItem fromItem = null;
	List<Join> joins = null;
	Select select = null;
	boolean useColumnsBrackets = false;
}
{
    <K_UPDATE> table=TableWithAlias() { tables.add(table); } 
          ("," table=TableWithAlias() { tables.add(table); } )*
    <K_SET> 
    (
	LOOKAHEAD(3) tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); }
		("," tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); } )*

	|

	["(" { useColumnsBrackets = true; }] tableColumn=Column() { columns.add(tableColumn); } ("," tableColumn=Column() { columns.add(tableColumn); } )* [ ")" ] "="
		"("
		(
			{ update.setUseSelect(true); }
			select = Select()
		)
		")"
   )

   [ <K_FROM>
      fromItem=FromItem()
      joins=JoinsList() ]

   [ where=WhereClause() { update.setWhere(where); } ]
   {
   		update.setColumns(columns);
   		update.setExpressions(expList);
   		update.setTables(tables);
		update.setFromItem(fromItem);
		update.setJoins(joins);
		update.setSelect(select);
		update.setUseColumnsBrackets(useColumnsBrackets);
		return update;
   }
}

Replace Replace():
{
	Replace replace = new Replace();
	Table table = null;
	Column tableColumn = null;
	Expression value = null;

	List<Column> columns = new ArrayList<Column>();
	List<Expression> expList = new ArrayList<Expression>();
	ItemsList itemsList = null;
	Expression exp = null;
}
{
    <K_REPLACE> [<K_INTO>] table=Table()

    (
		(
		    <K_SET> tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); }
			  ("," tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); } )*
			 {
		   		replace.setExpressions(expList);
			 }
		)
		|

		(
		     [LOOKAHEAD(2) "(" tableColumn=Column() { columns.add(tableColumn); } ("," tableColumn=Column() { columns.add(tableColumn); } )* ")"  ]
			(
				LOOKAHEAD(2) [<K_VALUES> | <K_VALUE>] "(" exp=PrimaryExpression() { expList.add(exp); }
						("," exp=PrimaryExpression()  { expList.add(exp); } )* ")" { itemsList = new ExpressionList(expList); }
				|
					{ replace.setUseValues(false); }
				    itemsList=SubSelect()
                    { ((SubSelect)itemsList).setUseBrackets(false); }
			)
		    {
				replace.setItemsList(itemsList);
		    }
		)
	)
   {
   		if (columns.size() > 0)
	   		replace.setColumns(columns);
   		replace.setTable(table);
		return replace;
   }
}

List<SelectExpressionItem> ListExpressionItem():
{
   List<SelectExpressionItem> retval = new ArrayList<SelectExpressionItem>();
   SelectExpressionItem item;
}
{
   item = SelectExpressionItem() {retval.add(item);}
   ("," item = SelectExpressionItem() {retval.add(item);} )*
   { return retval; }
}

Insert Insert():
{
	Insert insert = new Insert();
	Table table = null;
	Column tableColumn = null;
 	List<Column> columns = new ArrayList<Column>();
	List<Expression> primaryExpList = new ArrayList<Expression>();
	ItemsList itemsList = null;
	Expression exp = null;
	MultiExpressionList multiExpr = null;
    List<SelectExpressionItem> returning = null;
    Select select = null;
    boolean useSelectBrackets = false;
}
{
    <K_INSERT> [<K_INTO>] table=Table()


     [LOOKAHEAD(2) "(" tableColumn=Column() { columns.add(tableColumn); } ("," tableColumn=Column() { columns.add(tableColumn); } )* ")"  ]
	(
		LOOKAHEAD(2) [<K_VALUES> | <K_VALUE>]  "(" exp=SimpleExpression() { primaryExpList.add(exp); }
				("," exp=SimpleExpression()  { primaryExpList.add(exp); } )* ")" { itemsList = new ExpressionList(primaryExpList); }
			("," "(" exp=SimpleExpression() {
					if (multiExpr==null) {
						multiExpr=new MultiExpressionList();
						multiExpr.addExpressionList((ExpressionList)itemsList);
						itemsList = multiExpr;
					}
					primaryExpList = new ArrayList<Expression>();
					primaryExpList.add(exp); }
				("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { multiExpr.addExpressionList(primaryExpList); } )*

		|

		(
            LOOKAHEAD(2) "(" { useSelectBrackets = true; }
                { insert.setUseValues(false); }
                select = Select()
            ")"
            |
            { insert.setUseValues(false); }
            select = Select()
        )
	)

    [ <K_RETURNING> (
           "*" { insert.setReturningAllColumns(true); }
           | returning=ListExpressionItem()
           )
    ]

    {
		insert.setItemsList(itemsList);
        insert.setUseSelectBrackets(useSelectBrackets);
        insert.setSelect(select);
	    insert.setTable(table);
	    if (columns.size() > 0)
	    	insert.setColumns(columns);
        insert.setReturningExpressionList(returning);
    	return insert;
    }
}

Delete Delete():
{
	Delete delete = new Delete();
	Table table = null;
	Expression where = null;
}
{
    <K_DELETE> [<K_FROM>] table=TableWithAlias()
    [where=WhereClause() { delete.setWhere(where); } ]
    {
    	delete.setTable(table);
    	return delete;
    }
}

// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx

Column Column() #Column :
{
	String databaseName = null, schemaName = null, tableName = null, columnName = null;
}
{
    (
          LOOKAHEAD(7) databaseName=RelObjectName() "." [schemaName=RelObjectName()] "." tableName=RelObjectName() "." columnName=RelObjectName()
        | LOOKAHEAD(5) schemaName=RelObjectName() "." tableName=RelObjectName() "." columnName=RelObjectName()
        | LOOKAHEAD(3) tableName=RelObjectName() "." columnName=RelObjectName()
        | columnName=RelObjectName()
    )
	{
        final Database database = new Database(databaseName);
        final Table table = new Table(database, schemaName, tableName);
        Column col = new Column(table, columnName);
        linkAST(col,jjtThis);
        return col;
	}
}

String RelObjectName() :
{	Token tk = null; }
{
	(tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>
      | tk=<K_CAST> | tk=<K_DO> | tk=<K_EXTRACT> | tk=<K_FIRST> | tk=<K_FOLLOWING> 
      | tk=<K_LAST> | tk=<K_MATERIALIZED> | tk=<K_NULLS> | tk=<K_PARTITION> | tk=<K_RANGE> 
      | tk=<K_ROW> | tk=<K_ROWS> | tk=<K_SIBLINGS> | tk=<K_VALUE> | tk=<K_XML>
      | tk=<K_COLUMN> | tk=<K_REPLACE> | tk=<K_TRUNCATE> | tk=<K_KEY> | tk=<K_ANY>
      | tk=<K_OPEN> | tk=<K_OVER> | tk=<K_VALUES> | tk=<K_PERCENT>
      )

    { return tk.image; }
}

/*
Extended usage of object names.
*/
String RelObjectNameExt():
{ Token tk = null;
  String result=null;
} 
{
    ( result=RelObjectName() | tk=<K_LEFT> | tk=<K_RIGHT> | tk=<K_SET> )
    {
        if (tk!=null) result=tk.image;
        return result;
    }
}

Table Table() #Table :
{
	String serverName = null, databaseName = null, schemaName = null, tableName = null;
}
{
    (
          LOOKAHEAD(7) serverName=RelObjectName() "." [databaseName=RelObjectName()] "." [schemaName=RelObjectName()] "." tableName=RelObjectName()
        | LOOKAHEAD(5) databaseName=RelObjectName() "." [schemaName=RelObjectName()] "." tableName=RelObjectName()
        | LOOKAHEAD(3) schemaName=RelObjectName() "." tableName=RelObjectName()
        | tableName=RelObjectName()
    )
	{
        final Server server = new Server(serverName);
        final Database database = new Database(server, databaseName);
        Table table = new Table(database, schemaName, tableName);
        linkAST(table,jjtThis);
    	return table;
	}
}

Table TableWithAlias():
{
	Table table = null;
	Alias alias = null;
}
{
	table=Table() [alias=Alias() { table.setAlias(alias); }]
	{ return table; }
}

Select Select():
{
	Select select = new Select();
	SelectBody selectBody = null;
	List<WithItem> with = null;
}
{
    [ with=WithList() {  } ] selectBody = SelectBody()
	{
        select.setWithItemsList(with);
		select.setSelectBody(selectBody);
		return select;
	}
}

SelectBody SelectBody():
{ SelectBody selectBody = null; }
{
	(
		LOOKAHEAD(SetOperationList())
		    selectBody = SetOperationList()
    	|
	    selectBody = PlainSelect()
        |
        ( "(" selectBody = PlainSelect() { ((PlainSelect)selectBody).setUseBrackets(true); } ")" )
	)
	{ return selectBody; }
}

PlainSelect PlainSelect():
{
	PlainSelect plainSelect = new PlainSelect();
	List<SelectItem> selectItems = null;
	FromItem fromItem = null;
	List<Join> joins = null;
	List<SelectItem> distinctOn = null;
	Expression where = null;
	List<OrderByElement> orderByElements;
	List<Expression> groupByColumnReferences = null;
	Expression having = null;
	Limit limit = null;
	Offset offset = null;
	Fetch fetch = null;
	Top top = null;
        Skip skip = null;
        First first = null;
	OracleHierarchicalExpression oracleHierarchicalQueryClause = null;
    List<Table> intoTables = null;
    Table updateTable = null;
}
{
    <K_SELECT>

    [skip = Skip() { plainSelect.setSkip(skip);	} ]

    [LOOKAHEAD(2) first = First() { plainSelect.setFirst(first); } ]

    [
    	<K_ALL>
    	|
    		(
    			<K_DISTINCT> { Distinct distinct = new Distinct(); plainSelect.setDistinct(distinct); }
    				[ "ON" "(" distinctOn=SelectItemsList()  { plainSelect.getDistinct().setOnSelectItems(distinctOn); } ")" ]
    		)
    ]

    [top = Top() { plainSelect.setTop(top);	} ]

    selectItems=SelectItemsList()

    [intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ]
    [ <K_FROM>
      fromItem=FromItem()
      joins=JoinsList() ]

    [ where=WhereClause() { plainSelect.setWhere(where); }]
	[ oracleHierarchicalQueryClause=OracleHierarchicalQueryClause() { plainSelect.setOracleHierarchical(oracleHierarchicalQueryClause); } ]
    [ groupByColumnReferences=GroupByColumnReferences() { plainSelect.setGroupByColumnReferences(groupByColumnReferences); }]
    [ having=Having() { plainSelect.setHaving(having); }]
	[LOOKAHEAD(<K_ORDER> <K_SIBLINGS> <K_BY>) orderByElements = OrderByElements() { plainSelect.setOracleSiblings(true); plainSelect.setOrderByElements(orderByElements);	}   ]
	[LOOKAHEAD(<K_ORDER> <K_BY>) orderByElements = OrderByElements() { plainSelect.setOrderByElements(orderByElements);	}   ]
    [LOOKAHEAD(<K_LIMIT>) limit = Limit() { plainSelect.setLimit(limit);	} ]
	[LOOKAHEAD(<K_OFFSET>) offset = Offset() { plainSelect.setOffset(offset);	} ]
	[LOOKAHEAD(<K_FETCH>) fetch = Fetch() { plainSelect.setFetch(fetch);	} ]

    [ <K_FOR> <K_UPDATE> { plainSelect.setForUpdate(true); } 
        [ <K_OF> updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ] ]

	{
		plainSelect.setSelectItems(selectItems);
		plainSelect.setFromItem(fromItem);
		if (joins != null && joins.size() > 0)
			plainSelect.setJoins(joins);
		return plainSelect;
	}
}

SetOperationList SetOperationList():
{
	SetOperationList list = new SetOperationList();
	List<OrderByElement> orderByElements = null;
	Limit limit = null;
	Offset offset = null;
	Fetch fetch = null;
	SelectBody select = null;
	List<SelectBody> selects = new ArrayList<SelectBody>();
	List<SetOperation> operations = new ArrayList<SetOperation>();
}
{
	(

		(
			(("(" select=SelectBody() ")") | select=PlainSelect() ) {selects.add(select);}
			(
				((<K_UNION> { UnionOp union = new UnionOp();operations.add(union); } [ <K_ALL> { union.setAll(true); } | <K_DISTINCT> { union.setDistinct(true); } ])
				| <K_INTERSECT> { operations.add(new IntersectOp()); }
				| <K_MINUS> { operations.add(new MinusOp()); }
				| <K_EXCEPT> { operations.add(new ExceptOp()); }
				)

				(("(" select=SelectBody() ")") | select=PlainSelect() ) {selects.add(select);}
			)+
		)

		[orderByElements=OrderByElements() {list.setOrderByElements(orderByElements);} ]
		[LOOKAHEAD(<K_LIMIT>) limit=Limit() {list.setLimit(limit);} ]
		[LOOKAHEAD(<K_OFFSET>) offset = Offset() { list.setOffset(offset);} ]
		[LOOKAHEAD(<K_FETCH>) fetch = Fetch() { list.setFetch(fetch);} ]
	)

	{
		list.setOpsAndSelects(selects,operations);
		return list;
	}
}

List<WithItem> WithList():
{
	List<WithItem> withItemsList = new ArrayList<WithItem>();
	WithItem with = null;
}
{
	<K_WITH> with=WithItem() { withItemsList.add(with); } ("," with=WithItem() { withItemsList.add(with); } )*

 	{ return withItemsList; }
}

WithItem WithItem():
{
	WithItem with = new WithItem();
	String name = null;
	List<SelectItem> selectItems = null;
	SelectBody selectBody = null;
}
{
	 [ <K_RECURSIVE> { with.setRecursive(true); } ] name=RelObjectName() { with.setName(name); }
	 [ "(" selectItems=SelectItemsList() ")" { with.setWithItemList(selectItems); } ]
	 <K_AS>
	 "(" selectBody = SelectBody() { with.setSelectBody(selectBody); } ")"
	 { return with; }
}

List<SelectItem> SelectItemsList():
{
	List<SelectItem> selectItemsList = new ArrayList<SelectItem>();
	SelectItem selectItem = null;
}
{
    selectItem=SelectItem() { selectItemsList.add(selectItem); } ("," selectItem=SelectItem() { selectItemsList.add(selectItem); } )*

    { return selectItemsList; }
}

SelectExpressionItem SelectExpressionItem():
{
	SelectExpressionItem selectExpressionItem = null;
	Expression expression = null;
	Alias alias = null;
}
{
	 expression=SimpleExpression() { selectExpressionItem = new SelectExpressionItem(); selectExpressionItem.setExpression(expression); }
			 [alias=Alias() { selectExpressionItem.setAlias(alias); }] { return selectExpressionItem; }
}

SelectItem SelectItem():
{
	SelectItem selectItem = null;
}
{   ("*" { selectItem = new AllColumns(); }
    |
	LOOKAHEAD(AllTableColumns()) selectItem=AllTableColumns()
	|
	LOOKAHEAD(SelectExpressionItem()) selectItem=SelectExpressionItem() 
	)
	{
		return selectItem;
	}
}

AllTableColumns AllTableColumns():
{
	Table table = null;
}
{
     table=Table() "." "*"
	{
		return new AllTableColumns(table);
	}

}

Alias Alias():
{ String name = null;
  boolean useAs = false; }
{
	[<K_AS> { useAs = true; } ] name=RelObjectName()
   { return new Alias(name,useAs); }
}

FunctionItem FunctionItem():
{
    Alias alias = null;
    Function function;
    FunctionItem functionItem;
}
{
    function=Function() { functionItem = new FunctionItem(); functionItem.setFunction(function); }
			 [alias=Alias() { functionItem.setAlias(alias); }]
    { return functionItem; }
}

List<Column> PivotForColumns():
{
    List<Column> columns = new ArrayList<Column>();
    Column column;
}
{
    (
		("(" column = Column() { columns.add(column); }
         ("," column = Column() { columns.add(column); } )*
		 ")")
	| column = Column() { columns.add(column); }
	)
    { return columns; }
}

List<FunctionItem> PivotFunctionItems():
{
    List<FunctionItem> functionItems = new ArrayList<FunctionItem>();
    FunctionItem item;
}
{
    item = FunctionItem() {functionItems.add(item);}
    ( "," item = FunctionItem() {functionItems.add(item);} )*
    { return functionItems; }
}

List<SelectExpressionItem> PivotSingleInItems():
{
   List<SelectExpressionItem> retval = new ArrayList<SelectExpressionItem>();
   SelectExpressionItem item;
}
{
   item = SelectExpressionItem() {retval.add(item);}
   ("," item = SelectExpressionItem() {retval.add(item);} )*
   { return retval; }
}

ExpressionListItem ExpressionListItem():
{
	ExpressionListItem expressionListItem = null;
	ExpressionList expressionList = null;
	Alias alias = null;
}
{
    "("
    expressionList=SimpleExpressionList() { expressionListItem = new ExpressionListItem(); expressionListItem.setExpressionList(expressionList); }
    ")"
	[alias=Alias() { expressionListItem.setAlias(alias); }]
    { return expressionListItem; }
}

List<ExpressionListItem> PivotMultiInItems():
{
   List<ExpressionListItem> retval = new ArrayList<ExpressionListItem>();
   ExpressionListItem item;
}
{
   item = ExpressionListItem() {retval.add(item);}
   ("," item = ExpressionListItem() {retval.add(item);} )*
   { return retval; }
}

Pivot Pivot():
{
    Pivot retval = new Pivot();
    List<FunctionItem> functionItems;
    List<Column> forColumns;
    List<SelectExpressionItem> singleInItems = null;
    List<ExpressionListItem> multiInItems = null;
}
{
	<K_PIVOT> "(" functionItems = PivotFunctionItems() <K_FOR>
	forColumns = PivotForColumns()
	<K_IN> "("
	(LOOKAHEAD(3) singleInItems = PivotSingleInItems()
	| multiInItems = PivotMultiInItems() )
	")"
	")"
    {
        retval.setFunctionItems(functionItems);
        retval.setForColumns(forColumns);
        retval.setSingleInItems(singleInItems);
        retval.setMultiInItems(multiInItems);
        return retval;
    }
}

PivotXml PivotXml():
{
    PivotXml retval = new PivotXml();
    List<FunctionItem> functionItems;
    List<Column> forColumns;
    List<SelectExpressionItem> singleInItems = null;
    List<ExpressionListItem> multiInItems = null;
    SelectBody inSelect = null;
}
{
	<K_PIVOT> <K_XML> "(" functionItems = PivotFunctionItems() <K_FOR>
	forColumns = PivotForColumns()
	<K_IN> "("
	(
	    LOOKAHEAD(2) <K_ANY> { retval.setInAny(true); } |
	    LOOKAHEAD(1) inSelect = SelectBody() |
	    LOOKAHEAD(2) singleInItems = PivotSingleInItems() |
	    multiInItems = PivotMultiInItems()
    )
	")"
	")"
    {
        retval.setFunctionItems(functionItems);
        retval.setForColumns(forColumns);
        retval.setSingleInItems(singleInItems);
        retval.setMultiInItems(multiInItems);
        retval.setInSelect(inSelect);
        return retval;
    }
}

List<Table> IntoClause():
{
    List<Table> tables = new ArrayList<Table>();
    Table table;
}
{
    <K_INTO> table=Table() { tables.add(table); } ("," table=Table() { tables.add(table); } )*
    {
        return tables;
    }
}

FromItem FromItem():
{
	FromItem fromItem = null;
	Pivot pivot = null;
	Alias alias = null;
}
{
	(
		LOOKAHEAD(ValuesList()) fromItem=ValuesList()
		|
		(
			(
				(
					"("
						(
						LOOKAHEAD(SubJoin())
						fromItem=SubJoin()
						|
						fromItem=SubSelect()
						)
					")"
				)
				|
				fromItem=Table()
                |
				fromItem=LateralSubSelect()
			)
			[(LOOKAHEAD(2) pivot=PivotXml()|pivot=Pivot()) { fromItem.setPivot(pivot); } ]
			[ alias=Alias() { fromItem.setAlias(alias); } ]
		)
	)
	{
		return fromItem;
	}
}

FromItem ValuesList():
{
	MultiExpressionList exprList = new MultiExpressionList();
	List<Expression> primaryExpList = new ArrayList<Expression>();
	ValuesList valuesList = new ValuesList();
	Expression exp = null;
	List<String> colNames = null;
	String colName;
	Alias alias;
}
{
	"("
	<K_VALUES>
	(LOOKAHEAD(3) ("(" exp=SimpleExpression() { primaryExpList.add(exp); }
			("," exp=SimpleExpression()  { primaryExpList.add(exp); } )* ")" { exprList.addExpressionList(primaryExpList); }

			("," "(" exp=SimpleExpression() {
					primaryExpList = new ArrayList<Expression>();
					primaryExpList.add(exp); }
				("," exp=SimpleExpression() { primaryExpList.add(exp); } )* ")" { exprList.addExpressionList(primaryExpList); } )*)
	|
	( exp=SimpleExpression() { exprList.addExpressionList(exp); valuesList.setNoBrackets(true); }
		("," exp=SimpleExpression()  { exprList.addExpressionList(exp);} )*
	))
	")"

	[ alias=Alias() { valuesList.setAlias(alias); }

		[ "("
			colName = RelObjectName() { colNames = new ArrayList<String>(); colNames.add(colName); }
			( "," colName = RelObjectName() { colNames.add(colName); } )*
			")" { valuesList.setColumnNames(colNames); } ]

	]

	{
		valuesList.setMultiExpressionList(exprList);
		return valuesList;
	}
}

LateralSubSelect LateralSubSelect():
{
	LateralSubSelect lateralSubSelect = new LateralSubSelect();
	SubSelect subSelect = null;
}
{
	<K_LATERAL>
	 "(" subSelect=SubSelect() ")"
	{
		lateralSubSelect.setSubSelect(subSelect);
		return lateralSubSelect;
	}
}

FromItem SubJoin():
{
	FromItem fromItem = null;
	Join join = null;
	SubJoin subJoin = new SubJoin();
}
{
	fromItem=FromItem() { subJoin.setLeft(fromItem); }
	join=JoinerExpression() { subJoin.setJoin(join); }

	{
		return subJoin;
	}
}

List JoinsList():
{
	List<Join> joinsList = new ArrayList<Join>();
	Join join = null;
}
{

    (join=JoinerExpression() { joinsList.add(join); })*

    { return joinsList; }
}

Join JoinerExpression():
{
	Join join = new Join();
	FromItem right = null;
	Expression onExpression = null;
	Column tableColumn;
	List<Column> columns = null;
}
{
    [   
           ( <K_LEFT> { join.setLeft(true); }
  		   | <K_RIGHT> { join.setRight(true); }
  		   | <K_FULL> { join.setFull(true); } 
           ) [ <K_OUTER> { join.setOuter(true); } ]
        | <K_INNER> { join.setInner(true); }
        | <K_NATURAL> { join.setNatural(true); }
		| <K_CROSS> { join.setCross(true); } 
    ]

  	    ( <K_JOIN> | "," { join.setSimple(true); } ) 

        right=FromItem()


	[
		( <K_ON> onExpression=Expression()  { join.setOnExpression(onExpression); } )
		|
		( <K_USING> "(" tableColumn=Column() { columns = new ArrayList(); columns.add(tableColumn); }
				("," tableColumn=Column() { columns.add(tableColumn); } )* ")"
		  { join.setUsingColumns(columns); }   )
  	]
  {
  	join.setRightItem(right);
    return join; 
  }
}

Expression WhereClause():
{
	Expression retval = null;
}
{
    <K_WHERE> retval=Expression()
    { return retval; }
}

OracleHierarchicalExpression OracleHierarchicalQueryClause():
{
	OracleHierarchicalExpression result = new OracleHierarchicalExpression();
	Expression expr;
}
{
	(
				<K_START> <K_WITH>  expr=AndExpression() {result.setStartExpression(expr);}
				<K_CONNECT> <K_BY> [ <K_NOCYCLE> { result.setNoCycle(true); } ] expr=AndExpression()
                { result.setConnectExpression(expr); }
			|
				<K_CONNECT> <K_BY> [ <K_NOCYCLE> { result.setNoCycle(true); } ] expr=AndExpression()
                { 
                    result.setConnectExpression(expr); 
                    result.setConnectFirst(true);
                }
				[ <K_START> <K_WITH>  expr=AndExpression() {result.setStartExpression(expr);} ]
	)
	{
		return result;
	}
}

List<Expression> GroupByColumnReferences():
{
	Expression columnReference = null;
	List<Expression> columnReferences = new ArrayList<Expression>();
}
{
    <K_GROUP> <K_BY> columnReference=SimpleExpression() {columnReferences.add(columnReference); }
    ("," columnReference=SimpleExpression()  {columnReferences.add(columnReference); } )*
	{
		return columnReferences;
	}
}

Expression Having():
{
	Expression having = null;
}
{
    <K_HAVING> having=Expression()
	{
		return having;
	}
}

List<OrderByElement> OrderByElements():
{
	List<OrderByElement> orderByList = new ArrayList<OrderByElement>();
	OrderByElement orderByElement = null;
}
{
    <K_ORDER> [ <K_SIBLINGS> ] <K_BY> orderByElement=OrderByElement() { orderByList.add(orderByElement); }
        ("," orderByElement=OrderByElement() { orderByList.add(orderByElement); } )*
    {
    	return orderByList;
    }
}

OrderByElement OrderByElement():
{
	OrderByElement orderByElement = new OrderByElement();
	Expression columnReference = null;
}
{
	columnReference = SimpleExpression()
    [ ( <K_ASC> | (<K_DESC> { orderByElement.setAsc(false); } )) { orderByElement.setAscDescPresent(true); }  ]
    [<K_NULLS> ( 
        <K_FIRST> { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_FIRST);  }  | 
        <K_LAST> { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_LAST);  }  
        )?
    ]
	{
    	orderByElement.setExpression(columnReference);
		return orderByElement;
	}
}

Limit Limit():
{
	Limit limit = new Limit();
	limit.setRowCount(-1l);
	Token token = null;
}
{
	(
			LOOKAHEAD(3)
				// mysql-> LIMIT offset,row_count
				<K_LIMIT>
					 (
					 	token=<S_LONG> { limit.setOffset(Long.parseLong(token.image)); }
					 	|
					 	"?" { limit.setOffsetJdbcParameter(true);}

					 )
					 ","

				(
				token=<S_LONG> { limit.setRowCount(Long.parseLong(token.image)); } | "?" { limit.setRowCountJdbcParameter(true);}
				)
			|
				// mysql-postgresql-> LIMIT (row_count | ALL | NULL)
				<K_LIMIT>
				 (
				 	token=<S_LONG> { limit.setRowCount(Long.parseLong(token.image)); }
				 	|
				 	"?" { limit.setRowCountJdbcParameter(true);}
				 	|
				 	<K_ALL> { limit.setLimitAll(true);}
				 	|
				 	<K_NULL> { limit.setLimitNull(true); }
				 )

		)
	{
		return limit;
	}
}

Offset Offset():
{
	Offset offset = new Offset();
	Token token = null;
}
{
	(
			// postgresql-> OFFSET offset
			// sqlserver-oracle-> OFFSET offset (ROW | ROWS)
			 <K_OFFSET>
				 (token=<S_LONG> { offset.setOffset(Long.parseLong(token.image)); }
				 | "?" { offset.setOffsetJdbcParameter(true); } )
				 [(<K_ROWS> { offset.setOffsetParam("ROWS"); } | <K_ROW> { offset.setOffsetParam("ROW"); })]

		)
	{
		return offset;
	}
}

Fetch Fetch():
{
	Fetch fetch = new Fetch();
	Token token = null;
}
{
	(
			// sqlserver-oracle-> FETCH (FIRST | NEXT) row_count (ROW | ROWS) ONLY
			 <K_FETCH>
			 	 (<K_FIRST> { fetch.setFetchParamFirst(true); } | <K_NEXT>)
				 (token=<S_LONG> { fetch.setRowCount(Long.parseLong(token.image)); }
				 | "?" { fetch.setFetchJdbcParameter(true); } )
				 (<K_ROWS> { fetch.setFetchParam("ROWS"); } | <K_ROW>) 
				 <K_ONLY>

		)
	{
		return fetch;
	}
}

// according to http://technet.microsoft.com/en-us/library/ms189463.aspx
Top Top():
{
	Top top = new Top();
	Token token = null;
}
{
	<K_TOP>
	(
	 	token=<S_LONG>                      { top.setRowCount(Long.parseLong(token.image)); }
	   |
	 	"?"                                 { top.setRowCountJdbcParameter(true);}
	   |
	   "("
            ( token=<S_LONG>                { top.setRowCount(Long.parseLong(token.image)); }
              | "?"                         { top.setRowCountJdbcParameter(true);} )
            { top.setParenthesis(true);}
       ")"
	) [ LOOKAHEAD(2) <K_PERCENT>            { top.setPercentage(true); } ] 
	{
		return top;
	}
}

// according to http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0156.htm
Skip Skip():
{
	Skip skip = new Skip();
	Token token = null;
}
{
	<K_SKIP>
	(
	 	token=<S_LONG>                      { skip.setRowCount(Long.parseLong(token.image)); }
                | token=<S_IDENTIFIER>              { skip.setVariable(token.image); }
                | "?" { skip.setJdbcParameter(new JdbcParameter()); } [ LOOKAHEAD(2) token = <S_LONG> { skip.getJdbcParameter().setIndex(Integer.valueOf(token.image)); } ]
	)
	{
		return skip;
	}
}

First First():
{
	First first = new First();
	Token token = null;
}
{
	( <K_FIRST>                                 { first.setKeyword(First.Keyword.FIRST); }
            |  <K_LIMIT>                            { first.setKeyword(First.Keyword.LIMIT); }
        )
	(
	 	token=<S_LONG>                      { first.setRowCount(Long.parseLong(token.image)); }
                | token=<S_IDENTIFIER>              { first.setVariable(token.image); }
                |  "?" { first.setJdbcParameter(new JdbcParameter()); } [ LOOKAHEAD(2) token = <S_LONG> { first.getJdbcParameter().setIndex(Integer.valueOf(token.image)); } ]
	)
	{
		return first;
	}
}

Expression Expression() #Expression :
{
	Expression retval = null;
}
{
	(
	LOOKAHEAD(OrExpression())
		retval=OrExpression()
		|
		"(" retval=Expression() ")" {retval = new Parenthesis(retval); }

	)

    { return retval; }
}

Expression OrExpression():
{
	Expression left, right, result;
}
{
	left=AndExpression() { result = left; }
	(
		LOOKAHEAD(<K_OR>)
			<K_OR>
			right=AndExpression()
			{
				result = new OrExpression(left, right);
				left = result;
	   		}
	 )*
	 {
	 	return result;
	 }

}

Expression AndExpression() :
{
	Expression left, right, result;
	boolean not = false;
}
{
	(
	LOOKAHEAD(Condition())
	    left=Condition()
	    |
	    [ <K_NOT> { not = true; } ]
	    "(" left=OrExpression() ")" {left = new Parenthesis(left); if (not) { ((Parenthesis)left).setNot(); not = false; } }
	)
	{ result = left; }

	(
		LOOKAHEAD(<K_AND>)
 		<K_AND>
		(
		LOOKAHEAD(Condition())
		    right=Condition()
		    |
		    [ <K_NOT> { not = true; } ]
		    "(" right=OrExpression() ")" {right = new Parenthesis(right); if (not) { ((Parenthesis)right).setNot(); not = false; } }
		)
		{
			result = new AndExpression(left, right);
			left = result;
		}
	)*
	{
		return result;
	}
}

Expression Condition():
{
	Expression result;
}
{
	(LOOKAHEAD(SQLCondition()) result=SQLCondition()
	| LOOKAHEAD(RegularCondition()) result=RegularCondition()
	| result=Function()
	)

	{ return result; }
}

Expression RegularCondition():
{
	Expression result = null;
	Expression leftExpression;
	Expression rightExpression;
	boolean not = false;
	int oracleJoin=EqualsTo.NO_ORACLE_JOIN;
	int oraclePrior=EqualsTo.NO_ORACLE_PRIOR;
    boolean binary = false;
}
{
	[ <K_PRIOR> { oraclePrior = EqualsTo.ORACLE_PRIOR_START; }]
	[ <K_NOT> { not = true; } ]
	leftExpression=ComparisonItem() { result = leftExpression; }

	[ "(" "+" ")" { oracleJoin=EqualsTo.ORACLE_JOIN_RIGHT; } ]

	(
	">" { result = new GreaterThan(); }
	| "<" { result = new MinorThan(); }
	| "=" { result = new EqualsTo(); }
	| ">=" { result = new GreaterThanEquals(); }
	| "<=" { result = new MinorThanEquals(); }
	| "<>" { result = new NotEqualsTo(); }
    | "!=" { result = new NotEqualsTo("!="); }
	| "@@" { result = new Matches(); }
	| "~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); }
	| <K_REGEXP> [ <K_BINARY> { binary=true; } ] { result = new RegExpMySQLOperator(binary?RegExpMatchOperatorType.MATCH_CASESENSITIVE:RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); }
	| "~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); }
	| "!~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE); }
	| "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); }
	)
	rightExpression=ComparisonItem()

	[ <K_PRIOR> { oraclePrior = EqualsTo.ORACLE_PRIOR_END; } ]
	[ "(" "+" ")" { oracleJoin=EqualsTo.ORACLE_JOIN_LEFT; } ]

	{
		BinaryExpression regCond = (BinaryExpression) result;
		regCond.setLeftExpression(leftExpression);
		regCond.setRightExpression(rightExpression);
		if (not)
			regCond.setNot();

		if (oracleJoin>0)
			((SupportsOldOracleJoinSyntax)result).setOldOracleJoinSyntax(oracleJoin);

		if (oraclePrior!=EqualsTo.NO_ORACLE_PRIOR)
			((SupportsOldOracleJoinSyntax)result).setOraclePriorPosition(oraclePrior);
	}

	{ return result; }
}

Expression SQLCondition():
{
	Expression result;
}
{
	(
	LOOKAHEAD(InExpression()) result=InExpression()
	| LOOKAHEAD(Between()) result=Between()
	| LOOKAHEAD(IsNullExpression()) result=IsNullExpression()
	| LOOKAHEAD(ExistsExpression()) result=ExistsExpression()
	|  result=LikeExpression()
	)
	{ return result; }
}

Expression InExpression() :
{
	InExpression result = new InExpression();
	ItemsList leftItemsList = null;
	ItemsList rightItemsList = null;
	Expression leftExpression = null;
}
{
	( LOOKAHEAD(1) "(" (
			LOOKAHEAD(SimpleExpressionList()) leftItemsList = SimpleExpressionList() { result.setLeftItemsList(leftItemsList); }
			|
			leftExpression=SimpleExpression()
	        [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ]
		  )
	  ")"
	|
		leftExpression=SimpleExpression() { result.setLeftExpression(leftExpression); }
        [ "(" "+" ")" { result.setOldOracleJoinSyntax(EqualsTo.ORACLE_JOIN_RIGHT); } ]
	)
    [<K_NOT> { result.setNot(true); } ] <K_IN> "(" (LOOKAHEAD(SubSelect()) rightItemsList=SubSelect() | rightItemsList=SimpleExpressionList() ) ")"
	{
		result.setRightItemsList(rightItemsList);
		return result;
	}
}

Expression Between() :
{
	Between result = new Between();
	Expression leftExpression = null;
	Expression betweenExpressionStart = null;
	Expression betweenExpressionEnd = null;
}
{
	leftExpression=SimpleExpression()
	    [<K_NOT> { result.setNot(true); }]
	    <K_BETWEEN> betweenExpressionStart=SimpleExpression() <K_AND> betweenExpressionEnd=SimpleExpression()

	{
		result.setLeftExpression(leftExpression);
		result.setBetweenExpressionStart(betweenExpressionStart);
		result.setBetweenExpressionEnd(betweenExpressionEnd);
		return result;
	}
}

Expression LikeExpression() :
{
	LikeExpression result = new LikeExpression();
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
	leftExpression=SimpleExpression()
    [<K_NOT> { result.setNot(true); } ] ( <K_LIKE> | <K_ILIKE> { result.setCaseInsensitive(true); } ) rightExpression=SimpleExpression()
    [<K_ESCAPE> token=<S_CHAR_LITERAL> { result.setEscape((new StringValue(token.image)).getValue()); }]
	{
		result.setLeftExpression(leftExpression);
		result.setRightExpression(rightExpression);
		return result;
	}
}

Expression IsNullExpression():
{
	IsNullExpression result = new IsNullExpression();
	Expression leftExpression = null;
}
{
	(
	<K_NOT> { result.setNot(true); } leftExpression=SimpleExpression() <K_IS> <K_NULL>
	|
	leftExpression=SimpleExpression() <K_IS> [<K_NOT> { result.setNot(true); } ] <K_NULL>
	)

	{
		result.setLeftExpression(leftExpression);
		return result;
	}
}

Expression ExistsExpression():
{
	ExistsExpression result = new ExistsExpression();
	Expression rightExpression = null;
}
{
    [<K_NOT> { result.setNot(true); } ] <K_EXISTS> rightExpression=SimpleExpression()
	{
		result.setRightExpression(rightExpression);
		return result;
	}
}

ExpressionList SQLExpressionList():
{
	ExpressionList retval = new ExpressionList();
	List<Expression> expressions = new ArrayList<Expression>();
	Expression expr = null;
}
{
    expr=Expression() { expressions.add(expr); } ("," expr=Expression() { expressions.add(expr); })*
	{
		retval.setExpressions(expressions);
		return retval;
	}
}

ExpressionList SimpleExpressionList():
{
	ExpressionList retval = new ExpressionList();
	List<Expression> expressions = new ArrayList<Expression>();
	Expression expr = null;
}
{
    expr=SimpleExpression() { expressions.add(expr); } ("," expr=SimpleExpression() { expressions.add(expr); })*
	{
		retval.setExpressions(expressions);
		return retval;
	}
}

ExpressionList SimpleExpressionListAtLeastTwoItems():
{
	ExpressionList retval = new ExpressionList();
	List<Expression> expressions = new ArrayList<Expression>();
	Expression expr = null;
}
{
    expr=SimpleExpression() { expressions.add(expr); } ("," expr=SimpleExpression() { expressions.add(expr); })+
	{
		retval.setExpressions(expressions);
		return retval;
	}
}

Expression ComparisonItem() :
{
	Expression retval = null;
}
{
  (
    retval=AllComparisonExpression()
    | LOOKAHEAD(AnyComparisonExpression()) retval=AnyComparisonExpression()
    | LOOKAHEAD(3) retval=SimpleExpression()
    | retval=RowConstructor()
  )

   {
      return retval;
   }
}

Expression AllComparisonExpression() :
{
	AllComparisonExpression retval = null;
	SubSelect subselect = null;
}
{
 <K_ALL> "(" subselect=SubSelect() ")" { retval = new AllComparisonExpression(subselect); }
   {
      return retval;
   }
}

Expression AnyComparisonExpression() :
{
	AnyComparisonExpression retval = null;
    AnyType anyType;
	SubSelect subselect = null;
}
{
 (<K_ANY> { anyType = AnyType.ANY; } | <K_SOME> { anyType = AnyType.SOME; } ) 
 "(" subselect=SubSelect() ")" { retval = new AnyComparisonExpression(anyType, subselect); }
   {
      return retval;
   }
}

Expression SimpleExpression():
{
	Expression retval = null;
}
{
  (
		LOOKAHEAD(BitwiseAndOr())
		retval=BitwiseAndOr()
		|
		"(" retval=BitwiseAndOr() ")" {retval = new Parenthesis(retval); }

  )

   {
      return retval;
   }
}

Expression ConcatExpression():
{
	Expression result = null;
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
    leftExpression=AdditiveExpression()  { result = leftExpression; }
    (
    	"||"
    	rightExpression=AdditiveExpression()
		{
			Concat binExp = new Concat();
			binExp.setLeftExpression(leftExpression);
			binExp.setRightExpression(rightExpression);
			result = binExp;
			leftExpression = result;
		}
    )*

    { return result; }
}

Expression BitwiseAndOr():
{
	Expression result = null;
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
    leftExpression=ConcatExpression()  { result = leftExpression; }
    (
    	LOOKAHEAD(2) (
    					"|" { result = new BitwiseOr(); }
    				  	|
    				  	"&" { result = new BitwiseAnd(); }
    				  )

    						rightExpression=ConcatExpression()

		{
			BinaryExpression binExp = (BinaryExpression) result;
			binExp.setLeftExpression(leftExpression);
			binExp.setRightExpression(rightExpression);
			leftExpression = result;
		}
    )*

    { return result; }
}

Expression AdditiveExpression():
{
	Expression result = null;
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
    leftExpression=MultiplicativeExpression()  { result = leftExpression; }
    (
    	LOOKAHEAD(2) ("+" { result = new Addition(); }
    								| "-" { result = new Subtraction(); } )

        rightExpression=MultiplicativeExpression()
		{
			BinaryExpression binExp = (BinaryExpression) result;
			binExp.setLeftExpression(leftExpression);
			binExp.setRightExpression(rightExpression);
			leftExpression = result;
		}
    )*

    { return result; }
}

Expression MultiplicativeExpression():
{
	Expression result = null;
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
	(
	LOOKAHEAD(BitwiseXor())
	    leftExpression=BitwiseXor()
	    |
	    "(" leftExpression=ConcatExpression() ")" {leftExpression = new Parenthesis(leftExpression); }
	)
      { result = leftExpression; }
    (
    	LOOKAHEAD(2) ("*" { result = new Multiplication(); }
    								| "/" { result = new Division(); }
    								| "%" { result = new Modulo(); }
    				)

				(
				LOOKAHEAD(BitwiseXor())
    						rightExpression=BitwiseXor()
						    |
						    "(" rightExpression=ConcatExpression() ")" {rightExpression = new Parenthesis(rightExpression); }
				)

		{
			BinaryExpression binExp = (BinaryExpression) result;
			binExp.setLeftExpression(leftExpression);
			binExp.setRightExpression(rightExpression);
			leftExpression = result;
		}
    )*
    { return result; }
}

Expression BitwiseXor():
{
	Expression result = null;
	Expression leftExpression = null;
	Expression rightExpression = null;
}
{
    leftExpression=PrimaryExpression()  { result = leftExpression; }
    (
    	"^"
    	rightExpression=PrimaryExpression()
		{
			BitwiseXor binExp = new BitwiseXor();
			binExp.setLeftExpression(leftExpression);
			binExp.setRightExpression(rightExpression);
			result = binExp;
			leftExpression = result;
		}
    )*

    { return result; }
}

Expression PrimaryExpression():
{
	Expression retval = null;
    CastExpression castExpr = null;
	Token token = null;
	Token sign = null;
	String tmp = "";
	ColDataType type = null;
}
{
(
	<K_NULL> { retval = new NullValue(); }

	| retval=CaseWhenExpression()

	| LOOKAHEAD(3) [sign="+" | sign="-"] "?" { retval = new JdbcParameter(); } [ LOOKAHEAD(2) token = <S_LONG> { ((JdbcParameter)retval).setIndex(Integer.valueOf(token.image)); } ]

    | LOOKAHEAD(3) [sign="+" | sign="-"] retval=JdbcNamedParameter()

    | LOOKAHEAD(3) [sign="+" | sign="-"] retval=UserVariable()

    | LOOKAHEAD(3) [sign="+" | sign="-"] retval=NumericBind()

	| LOOKAHEAD(AnalyticExpression()) retval=AnalyticExpression()

    | LOOKAHEAD(WithinGroupExpression()) retval=WithinGroupExpression()

	| LOOKAHEAD(ExtractExpression()) retval=ExtractExpression()

    | retval=MySQLGroupConcat()

    | LOOKAHEAD([sign="+" | sign="-"] JsonExpression()) [sign="+" | sign="-"] retval=JsonExpression()

	| LOOKAHEAD(["+" | "-"] Function())       [sign="+" | sign="-"] retval=Function()

	| LOOKAHEAD(["+" | "-"] <S_DOUBLE>)       [sign="+" | sign="-"] token=<S_DOUBLE>  { retval = new DoubleValue(token.image); }

	| LOOKAHEAD(["+" | "-"] <S_LONG>)         [sign="+" | sign="-"] token=<S_LONG> { retval = new LongValue(token.image); }

    | LOOKAHEAD(["+" | "-"] <S_HEX>)          [sign="+" | sign="-"] token=<S_HEX>  { retval = new HexValue(token.image); }

	| LOOKAHEAD(["+" | "-"] CastExpression()) [sign="+" | sign="-"] retval=CastExpression()

	| LOOKAHEAD(["+" | "-"] Column())         [sign="+" | sign="-"] retval=Column()

    | LOOKAHEAD([sign="+" | sign="-"] "(" SubSelect() ")")     [sign="+" | sign="-"] "(" retval=SubSelect() ")"

	| LOOKAHEAD(3)   [sign="+" | sign="-"] "(" retval=BitwiseAndOr() ")" {retval = new Parenthesis(retval); }

	| token=<S_CHAR_LITERAL> { retval = new StringValue(token.image); }


	| "{d" token=<S_CHAR_LITERAL> "}"  { retval = new DateValue(token.image); }

	| "{t" token=<S_CHAR_LITERAL> "}"  { retval = new TimeValue(token.image); }

	| "{ts" token=<S_CHAR_LITERAL> "}" { retval = new TimestampValue(token.image); }

	| retval = IntervalExpression()
)

[ "::" type=ColDataType() {
		castExpr = new CastExpression();
		castExpr.setUseCastKeyword(false);
		castExpr.setLeftExpression(retval);
		castExpr.setType(type);
		retval=castExpr;
} ]

    {
		if (sign != null) {
			retval = new SignedExpression(sign.image.charAt(0), retval);
		}
    	return retval;
    }
}

JdbcNamedParameter JdbcNamedParameter() : {
	JdbcNamedParameter parameter = new JdbcNamedParameter();
	Token token;
}
{
    ":" token=<S_IDENTIFIER> { parameter.setName(token.image); }
	{
		return parameter;
	}
}

UserVariable UserVariable() : {
    UserVariable var = new UserVariable();
	Token token;
}
{
    ("@" | "@@" { var.setDoubleAdd(true);} )
    token=<S_IDENTIFIER> 
    { 
        var.setName(token.image); 
        return var; 
    }
}

NumericBind NumericBind() : {
    NumericBind var = new NumericBind();
	Token token;
}
{
    ":" token=<S_LONG> 
    { 
        var.setBindId(Integer.valueOf(token.image)); 
        return var; 
    }
}

JsonExpression JsonExpression() : {
  JsonExpression result = new JsonExpression();
  Column column;
  Token token;
}
{
    column=Column() ("->" token=<S_CHAR_LITERAL> {result.addIdent(token.image);} )+
    { 
        result.setColumn(column);
        return result; 
    }
}

IntervalExpression IntervalExpression() : {
	IntervalExpression interval = new IntervalExpression();
	Token token;
}
{
	<K_INTERVAL> (token=<S_LONG> | token=<S_DOUBLE> | token=<S_CHAR_LITERAL>) 
    { interval.setParameter(token.image); }
    [ LOOKAHEAD(2) token = <S_IDENTIFIER> { interval.setIntervalType(token.image); } ]
	{
		return interval;
	}
}

WithinGroupExpression WithinGroupExpression() :
{
    Token token = null;
    List<OrderByElement> orderByElements = null;
    WithinGroupExpression result = new WithinGroupExpression();
    ExpressionList exprList;
}
{
    token = <S_IDENTIFIER> "(" exprList = SimpleExpressionList() ")" 
      <K_WITHIN> <K_GROUP>
    "(" orderByElements = OrderByElements() ")"

    { 
        result.setName(token.image);
        result.setExprList(exprList);
        result.setOrderByElements(orderByElements);
        return result; 
    }
}

KeepExpression KeepExpression() : {
    KeepExpression keep = new KeepExpression();
    Token token;
    List<OrderByElement> list;
}
{
    <K_KEEP> "(" token = <S_IDENTIFIER> (<K_FIRST> { keep.setFirst(true); } | <K_LAST> { keep.setFirst(false); })
      list = OrderByElements() ")"

    {
        keep.setName(token.image);
        keep.setOrderByElements(list);
        return keep;
    }
}

AnalyticExpression AnalyticExpression() :
{
	AnalyticExpression retval = new AnalyticExpression();
	ExpressionList expressionList = null;
	List<OrderByElement> olist = null;
	Token token = null;
	Expression expr = null;
	Expression offset = null;
	Expression defaultValue = null;
    WindowElement windowElement = null;
    KeepExpression keep = null;
}
{
	token=<S_IDENTIFIER> { retval.setName(token.image); }
	    "(" [ expr=SimpleExpression() ["," offset=SimpleExpression() ["," defaultValue=SimpleExpression() ]] | "*" { retval.setAllColumns(true); } ] ")" 

    [ keep=KeepExpression() ]

    <K_OVER> "("
        [<K_PARTITION> <K_BY> expressionList=SimpleExpressionList() ]
        [olist=OrderByElements() [windowElement = WindowElement() ] ]
        
	{
		retval.setExpression(expr);
		retval.setOffset(offset);
		retval.setDefaultValue(defaultValue);
        retval.setKeep(keep);
		retval.setPartitionExpressionList(expressionList);
		retval.setOrderByElements(olist);
        retval.setWindowElement(windowElement);
	}
	")"
	{
		return retval;
	}
}

WindowElement WindowElement():
{
    WindowElement windowElement = new WindowElement();
    WindowRange range = new WindowRange();
    WindowOffset offset = null;
}
{
    (<K_ROWS> { windowElement.setType(WindowElement.Type.ROWS); }  |  <K_RANGE> { windowElement.setType(WindowElement.Type.RANGE); } )
    ( (
      <K_BETWEEN> { windowElement.setRange(range); } 
      offset = WindowOffset() { range.setStart(offset); } 
      <K_AND> offset = WindowOffset() { range.setEnd(offset); }
      )
    | 
      offset = WindowOffset() { windowElement.setOffset(offset); } 
    )
 
    {
        return windowElement;
    }
}

WindowOffset WindowOffset():
{
    WindowOffset offset = new WindowOffset();
    Expression expr = null;
}
{
    (
  
        <K_UNBOUNDED> (<K_PRECEDING> { offset.setType(WindowOffset.Type.PRECEDING); return offset; } |
   									 <K_FOLLOWING> { offset.setType(WindowOffset.Type.FOLLOWING); return offset; } )
    ) 
    |
    ( <K_CURRENT> <K_ROW> { offset.setType(WindowOffset.Type.CURRENT); return offset;} ) 
    |
    ( expr = SimpleExpression() {
        offset.setType(WindowOffset.Type.EXPR); 
        offset.setExpression(expr); 
        } 
        (<K_PRECEDING> { offset.setType(WindowOffset.Type.PRECEDING); } | <K_FOLLOWING> { offset.setType(WindowOffset.Type.FOLLOWING);  } )
    )
  
    {
        return offset;
    }
} 

ExtractExpression ExtractExpression() :
{
	ExtractExpression retval = new ExtractExpression();
	Token token = null;
	Expression expr = null;
}
{
	<K_EXTRACT>
	"("
		token=<S_IDENTIFIER> { retval.setName(token.image); }
		<K_FROM>
		expr=SimpleExpression() { retval.setExpression(expr); }
	")"
	{
		return retval;
	}
}

CastExpression CastExpression():
{
	CastExpression retval = new CastExpression();
	ColDataType type = null;
	Expression expression = null;
	boolean	useCastKeyword;
}
{
	<K_CAST> "(" expression=SimpleExpression() <K_AS> type=ColDataType() ")" { retval.setUseCastKeyword(true); }

    {
	    retval.setLeftExpression(expression);
	    retval.setType(type);
    	return retval;
    }
}

Expression CaseWhenExpression():
{
	CaseExpression caseExp = new CaseExpression();
	Expression switchExp = null;
	WhenClause clause;
	List whenClauses = new ArrayList();
	Expression elseExp = null;
}
{
	<K_CASE>
	(
    	    ( clause=WhenThenSearchCondition() { whenClauses.add(clause); } )+
             [<K_ELSE> elseExp=SimpleExpression()]
		|
		    switchExp=PrimaryExpression()
             ( clause=WhenThenValue() { whenClauses.add(clause); } )*
             [<K_ELSE> elseExp=SimpleExpression()]
	)
    <K_END>
    {
    	caseExp.setSwitchExpression(switchExp);
        caseExp.setWhenClauses(whenClauses);
		caseExp.setElseExpression(elseExp);
    	return caseExp;
    }
}

WhenClause WhenThenSearchCondition():
{
	WhenClause whenThen = new WhenClause();
	Expression whenExp = null;
	Expression thenExp = null;
}
{
	<K_WHEN> whenExp=Expression() <K_THEN> thenExp=SimpleExpression()
	{
	   whenThen.setWhenExpression(whenExp);
	   whenThen.setThenExpression(thenExp);
	   return whenThen;
	}
}

WhenClause WhenThenValue():
{
	WhenClause whenThen = new WhenClause();
	Expression whenExp = null;
	Expression thenExp = null;
}
{
	<K_WHEN> whenExp=PrimaryExpression() <K_THEN> thenExp=SimpleExpression()
	{
	   whenThen.setWhenExpression(whenExp);
	   whenThen.setThenExpression(thenExp);
	   return whenThen;
	}
}

RowConstructor RowConstructor(): {
    ExpressionList list = null;
    RowConstructor rowConstructor = new RowConstructor();
} {
    //("(" list =SimpleExpressionListAtLeastTwoItems() ")"
    //|
    [ <K_ROW> { rowConstructor.setName("ROW");} ]
    "("
        list = SimpleExpressionList()
    ")"

    {
        rowConstructor.setExprList(list);
        return rowConstructor;
    }
}

Execute Execute(): {
	String funcName = null;
    ExpressionList expressionList = null;
    Execute execute = new Execute();
}
{
    (<K_EXEC> | <K_EXECUTE>)

    funcName=RelObjectName() { execute.setName(funcName); }

    [ expressionList=SimpleExpressionList() ]

    { 
        execute.setExprList(expressionList);
        return execute; 
    }
}

Function Function():
{
	Function retval = new Function();
	String funcName = null;
	String tmp = null;
	ExpressionList expressionList = null;
    KeepExpression keep = null;
}
{
	["{fn" { retval.setEscaped(true); } ]

	funcName=RelObjectNameExt()

    [ "." tmp=RelObjectNameExt() { funcName+= "." + tmp; } ["." tmp=RelObjectNameExt() { funcName+= "." + tmp; }]]
    "(" [ [<K_DISTINCT> { retval.setDistinct(true); } | <K_ALL> { retval.setAllColumns(true); }] (expressionList=SimpleExpressionList() | "*" { retval.setAllColumns(true); }) ] ")"

    [ "." tmp=RelObjectName() { retval.setAttribute(tmp); }]

    [ keep = KeepExpression() ]

    ["}"]
    {
	    retval.setParameters(expressionList);
	    retval.setName(funcName);
        retval.setKeep(keep);
    	return retval;
    }
}

MySQLGroupConcat MySQLGroupConcat():{
    MySQLGroupConcat retval = new MySQLGroupConcat();
    ExpressionList expressionList = null;
    List<OrderByElement> orderByList = null;
    Token t;
}
{
    <K_GROUP_CONCAT> "(" 
       [<K_DISTINCT>  { retval.setDistinct(true); } ] 
       expressionList = SimpleExpressionList() 
       [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ]
       [ <K_SEPARATOR> t=<S_CHAR_LITERAL> { retval.setSeparator(t.image); } ]
    ")"
    { 
        retval.setExpressionList(expressionList);
        return retval; 
    }
}


SubSelect SubSelect():
{
	SelectBody selectBody = null;
    SubSelect subSelect = new SubSelect();
    List<WithItem> with = null;
}
{
    [ with=WithList() { subSelect.setWithItemsList(with); } ]
    selectBody=SelectBody()
    {
    	subSelect.setSelectBody(selectBody);
    	return subSelect;
    }
}

CreateIndex CreateIndex():
{
	CreateIndex createIndex = new CreateIndex();
	Table table = null;
	List<String> colNames = new ArrayList<String>();
	Token columnName;
	Index index = null;
	String name = null;
	String parameter = null;
}
{
	<K_CREATE>
	( parameter=CreateParameter() )*

	<K_INDEX> name=RelObjectName()
	{
		index = new Index();
		index.setName(name);
		index.setType(parameter);
	}

	<K_ON> table=Table()

	"("
	(columnName=<S_IDENTIFIER>
	|
	columnName=<S_QUOTED_IDENTIFIER>)

	(CreateParameter() | <K_ASC> | <K_DESC>)*
	{
		colNames.add(columnName.image);
	}

	(
		","
		(columnName=<S_IDENTIFIER>
		|
		columnName=<S_QUOTED_IDENTIFIER>)

		(CreateParameter() | <K_ASC> | <K_DESC>)*
		{
			colNames.add(columnName.image);
		}
	)*

	")"
	(CreateParameter() {})*

	{
		index.setColumnsNames(colNames);
		createIndex.setIndex(index);
		createIndex.setTable(table);
		return createIndex;
	}
}

CreateTable CreateTable():
{
	CreateTable createTable = new CreateTable();
	Table table = null;
	List columnDefinitions = new ArrayList();
	List columnSpecs = null;
	List<String> tableOptions = new ArrayList<String>();
    List<String> createOptions = new ArrayList<String>();
	String columnName;
	Token tk = null;
	Token tk2 = null;
	Token tk3 = null;
    String sk3 = null;
	ColDataType colDataType = null;
	String stringList = null;
	ColumnDefinition coldef = null;
	List indexes = new ArrayList();
	List colNames = null;
	Index index = null;
	ForeignKeyIndex fkIndex = null;
	String parameter = null;
	Table fkTable = null;
    Select select = null;
}
{
	<K_CREATE>
	// TODO:
//	[ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ]
    [ <K_UNLOGGED> { createTable.setUnlogged(true); } ]
	(parameter = CreateParameter() { createOptions.add(parameter); })*

	<K_TABLE> 
    [ <K_IF> <K_NOT> <K_EXISTS> { createTable.setIfNotExists(true); }]
    table=Table()
	[
		("("
		columnName=RelObjectName()

		colDataType = ColDataType()
		{
			columnSpecs = new ArrayList();
		}

		( parameter=CreateParameter() { columnSpecs.add(parameter); } )*

		{
			coldef = new ColumnDefinition();
			coldef.setColumnName(columnName);
			coldef.setColDataType(colDataType);
			if (columnSpecs.size() > 0)
				coldef.setColumnSpecStrings(columnSpecs);
			columnDefinitions.add(coldef);
		}

		(
			","

			(
				(
					tk=<K_INDEX>
						sk3=RelObjectName()
						colNames=ColumnsNamesList()
						{
							index = new Index();
							index.setType(tk.image);
							index.setName(sk3);
							index.setColumnsNames(colNames);
							indexes.add(index);
						}
				)
				|
				LOOKAHEAD(3) (
                    {
                        index = new NamedConstraint();
                    }
                    [<K_CONSTRAINT> sk3=RelObjectName() {index.setName(sk3);} ]
					
                    (tk=<K_PRIMARY> tk2=<K_KEY> {index.setType(tk.image + " " + tk2.image);}
                     | tk=<K_UNIQUE> [ tk2=<K_KEY> ] {index.setType(tk.image + (tk2!=null?" " + tk2.image:""));}
                     )
						colNames=ColumnsNamesList()
						{
							
							index.setColumnsNames(colNames);
							indexes.add(index);
						}
				)
				|
				LOOKAHEAD(3) ( {tk=null;}
					 [ tk=<K_UNIQUE> ] tk2=<K_KEY>
						sk3=RelObjectName()
						colNames=ColumnsNamesList()
						{
							index = new Index();
							index.setType((tk!=null?tk.image + " ":"") + tk2.image);
							index.setName(sk3);
							index.setColumnsNames(colNames);
							indexes.add(index);
						}
				)
				|
				(
					{
						fkIndex = new ForeignKeyIndex();
					}
					[<K_CONSTRAINT> sk3=RelObjectName() {fkIndex.setName(sk3);} ]
					tk=<K_FOREIGN> tk2=<K_KEY>
						colNames=ColumnsNamesList()
						{
							fkIndex.setType(tk.image + " " + tk2.image);
							fkIndex.setColumnsNames(colNames);
						}
						<K_REFERENCES> fkTable=Table() colNames=ColumnsNamesList()
						{
							fkIndex.setTable(fkTable);
							fkIndex.setReferencedColumnNames(colNames);
							indexes.add(fkIndex);
						}
				)
				|
				(
					columnName=RelObjectName()

					colDataType = ColDataType()
					{
						columnSpecs = new ArrayList();
					}

					( 	parameter=CreateParameter() { columnSpecs.add(parameter); } 	)*

					{
						coldef = new ColumnDefinition();
						coldef.setColumnName(columnName);
						coldef.setColDataType(colDataType);
						if (columnSpecs.size() > 0)
							coldef.setColumnSpecStrings(columnSpecs);
						columnDefinitions.add(coldef);
					}
				)
			)
		)*

		")"
		( 	parameter=CreateParameter() { tableOptions.add(parameter); } )*
        )
        |
        (
        <K_AS> select = Select() { createTable.setSelect(select); }
        )
	]

	{
		createTable.setTable(table);
		if (indexes.size() > 0)
			createTable.setIndexes(indexes);
        if (createOptions.size() > 0)
            createTable.setCreateOptionsStrings(createOptions);
		if (tableOptions.size() > 0)
			createTable.setTableOptionsStrings(tableOptions);
		if (columnDefinitions.size() > 0)
			createTable.setColumnDefinitions(columnDefinitions);
		return createTable;
	}
}

ColDataType ColDataType():
{
	ColDataType colDataType = new ColDataType();
	Token tk = null;
	Token tk2 = null;
	ArrayList argumentsStringList = new ArrayList();
    List<Integer> array = new ArrayList<Integer>();
}
{
	( tk=<K_CHARACTER> tk2=<K_VARYING> { colDataType.setDataType(tk.image + " " + tk2.image); }
	| tk=<S_IDENTIFIER> { colDataType.setDataType(tk.image); } )

	[LOOKAHEAD(2) "(" ( (tk=<S_LONG> | tk=<S_CHAR_LITERAL>) { argumentsStringList.add(tk.image); } ["," {/*argumentsStringList.add(",");*/}] )*    ")"]
    [( "[" {tk=null;} [ tk=<S_LONG> ] { array.add(tk!=null?Integer.valueOf(tk.image):null); } "]" )+ { colDataType.setArrayData(array); } ]
    [<K_CHARACTER> <K_SET> tk=<S_IDENTIFIER> { colDataType.setCharacterSet(tk.image); } ]

	{
		if (argumentsStringList.size() > 0)
			colDataType.setArgumentsStringList(argumentsStringList);
		return colDataType;
	}
}

CreateView CreateView():
{
	CreateView createView = new CreateView();
	Table view = null;
	SelectBody select = null;
	List<String> columnNames = null;
}
{
	<K_CREATE>
	[ <K_OR> <K_REPLACE> { createView.setOrReplace(true);} ]
	[ <K_MATERIALIZED> { createView.setMaterialized(true);} ]
	<K_VIEW> view=Table() { createView.setView(view); }
	[ columnNames = ColumnsNamesList() { createView.setColumnNames(columnNames); } ]
	<K_AS>
	(
      LOOKAHEAD(SelectBody()) select=SelectBody() { createView.setSelectBody(select); }
	  |
	  "(" select=SelectBody() ")" { createView.setSelectBody(select); }
    )
	{ return createView; }
}

String CreateParameter():
{
	String retval = "";
	Token tk = null;
    Token sign = null;
}
{
		(
			tk=<S_IDENTIFIER> { retval = tk.image; }
			|
			tk=<K_NULL> { retval = tk.image; }
			|
			tk=<K_NOT> { retval = tk.image; }
			|
			tk=<K_PRIMARY> { retval = tk.image; }
			|
			tk=<K_FOREIGN> { retval=tk.image; }
            |
            tk=<K_REFERENCES> { retval=tk.image; }
            |
			tk=<K_KEY> { retval = tk.image; }
			|
			tk=<S_CHAR_LITERAL> { retval = tk.image; }
			|
              ("+" {retval = "+";} | "-" {retval = "-";})?
              (
			   tk=<S_LONG> { retval += tk.image; }
			   |
			   tk=<S_DOUBLE> { retval += tk.image; }
              )
			|
			tk=<K_ON> { retval = tk.image; } 
            |
			tk=<K_COMMIT> { retval = tk.image; } 
            |
			tk=<K_ROWS> { retval = tk.image; } 
            |
            tk=<K_UNIQUE> { retval = tk.image; } 
            |
			"=" { retval = "="; }
			|
			retval=AList()
		)
	{return retval;}
}

String AList():
{
	StringBuilder retval = new StringBuilder("(");
	Token tk = null;
}
{
	 "("

	 ( (tk=<S_LONG> | tk=<S_DOUBLE> | tk=<S_CHAR_LITERAL> | tk=<S_IDENTIFIER>) { retval.append(tk.image); } ["," {retval.append(",");}] )*

	")"
	{
		retval.append(")");
		return retval.toString();
	}
}

List<String> ColumnsNamesList():
{
	List<String> retval = new ArrayList<String>();
	Token tk = null;
}
{
	"("

	 	(tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>) { retval.add(tk.image); }
	 	( "," (tk=<S_IDENTIFIER> | tk=<S_QUOTED_IDENTIFIER>) { retval.add(tk.image); } )*

	")"
	{
		return retval;
	}
}

Drop Drop():
{
	Drop drop = new Drop();
	Token tk = null;
    Table name;
	List<String> dropArgs = new ArrayList<String>();
}
{
	<K_DROP>
	(
		tk=<S_IDENTIFIER>
		|
		tk=<K_TABLE>
		|
		tk=<K_INDEX>
	)
    { drop.setType(tk.image); }
	name = Table() { drop.setName(name); }
	(tk=<S_IDENTIFIER> { dropArgs.add(tk.image); })*

	{
		if (dropArgs.size() > 0)
			drop.setParameters(dropArgs);
		return drop;
	}
}

Truncate Truncate():
{
	Truncate truncate = new Truncate();
	Table table;
}
{
	<K_TRUNCATE> <K_TABLE>
	table=Table() { truncate.setTable(table); }
	{
		return truncate;
	}
}

Alter Alter():
{
	Alter alter = new Alter();
	Table table;
	Token tk;
	ColDataType dataType;
    List<String> pkColumnNames = null;
    List<String> ukColumnNames = null;
}
{
	<K_ALTER> <K_TABLE> table=Table() { alter.setTable(table); } 

    <K_ADD> 
    
    (  
        (  <K_COLUMN>
	       (tk=<S_IDENTIFIER>	| tk=<S_QUOTED_IDENTIFIER>) dataType=ColDataType()
            {
               alter.setColumnName(tk.image);
               alter.setDataType(dataType);
            }
        )
        |
        ( <K_PRIMARY> <K_KEY> pkColumnNames=ColumnsNamesList() { alter.setPkColumns(pkColumnNames); } )
        |
        ( <K_UNIQUE> <K_KEY> (tk=<S_IDENTIFIER>	| tk=<S_QUOTED_IDENTIFIER>) ukColumnNames=ColumnsNamesList() { alter.setUkName(tk.image); alter.setUkColumns(ukColumnNames); } )
    )

    {
		return alter;
	}
}
