blob: 1944f0e04f2842e6c92e366cf58b0868689f2477 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 Ingres Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Ingres Corporation - initial API and implementation
*******************************************************************************/
options{
STATIC=false;
MULTI=true;
NODE_DEFAULT_VOID=true;
NODE_SCOPE_HOOK=true;
VISITOR=true;
IGNORE_CASE=true;
}
PARSER_BEGIN(IngresSQLParser)
package org.eclipse.datatools.enablement.ingres.internal.ui.parser;
import java.util.ArrayList;
import java.io.StringReader;
import org.eclipse.datatools.sqltools.sql.parser.SQLParser;
import org.eclipse.datatools.sqltools.sql.parser.ast.Node;
import org.eclipse.datatools.sqltools.sql.parser.ast.SimpleNode;
import org.eclipse.datatools.sqltools.sql.parser.ParseException;
import org.eclipse.datatools.sqltools.sql.parser.SQLParserConstants;
import org.eclipse.datatools.sqltools.sql.parser.JavaCharStream;
import org.eclipse.datatools.sqltools.sql.parser.Token;
import org.eclipse.datatools.sqltools.sql.parser.TokenMgrError;
import org.eclipse.datatools.sqltools.sql.parser.ParsingResult;
import org.eclipse.datatools.sqltools.sql.parser.util.ParserUtil;
import org.eclipse.datatools.sqltools.sql.parser.ParserParameters;
/**
* Ingres SQL parser.
*
* @author stefan.reddig@ingres.com
*/
public class IngresSQLParser extends SQLParser implements SQLParserConstants
{
private static IngresSQLParser _instance = new IngresSQLParser(new StringReader(""));
private boolean _debug = false;
private ParsingResult result = null;
private ArrayList exceptions = new ArrayList();
private ArrayList knownExceptions = new ArrayList();
private static final int[] STMT_START = new int[]{ALTER, //BEGIN,
CLOSE, COMMIT, //CONTINUE,
CREATE,
DECLARE, DELETE,
DROP, //DUMP,
EXECUTE, EXEC,
FETCH, //GOTO, GRANT,
IF, INSERT, //KILL, LOAD,
OPEN, PREPARE, //MOUNT, PRINT,
REMOVE,RETURN, REVOKE, ROLLBACK, SAVE, SELECT, SET,
UPDATE, //UNMOUNT,
WHILE
};
public static final String[] STMT_START_STRING = new String[]{"ALTER",//"BEGIN",
"CLOSE","COMMIT", //"CONTINUE",
"CREATE",
"DECLARE","DELETE",
"DROP",//"DUMP",
"EXECUTE","EXEC",
"FETCH",//"GOTO","GRANT",
"IF","INSERT",//"KILL","LOAD",
"OPEN","PREPARE",//"PRINT",
"REMOVE","RETURN","REVOKE","ROLLBACK","SAVE","SELECT","SET",
"UPDATE",
"WHILE"
};
private static final int[] DEFINED_STMT_START = new int[]{ALTER, //BEGIN,
CREATE, DECLARE, DELETE, EXECUTE, EXEC,
FETCH, IF, INSERT, //PRINT,
RETURN, SELECT, UPDATE
};
private static final int[] TERMINATORS = new int[]{GO, SEMICOLON};
private static final String[] TERMINATORS_STRING = new String[]{"\\g", ";"};
private static int[] STMT_START_TERMINATORS = new int[STMT_START.length + TERMINATORS.length];
static
{
System.arraycopy(STMT_START, 0, STMT_START_TERMINATORS, 0, STMT_START.length);
System.arraycopy(TERMINATORS, 0, STMT_START_TERMINATORS, STMT_START.length, TERMINATORS.length);
}
//FIXME do we need this field?
private boolean isContentAssist = true;
/*
* Singleton
*/
public static IngresSQLParser getInstance(){
return _instance;
}
public IngresSQLParser()
{
}
//Implements JavaCC methods
void jjtreeOpenNodeScope(Node n)
{
((SimpleNode)n).setFirstToken ( getToken(1));
}
void jjtreeCloseNodeScope(Node n)
{
((SimpleNode)n).setLastToken( getToken(0));
}
//Implements SQLParser abstract methods
/**
* Returns the statement terminator array. Different vendors will have their
* own terminators defined, so we just leave this method as abstract here.
*
* @return statement terminator array
*/
public String[] getStatementTerminators()
{
return TERMINATORS_STRING;
}
/**
* Returns the token strings that can be used to begin a SQL statement.
*
* @return statement start token array
*/
public String[] getStatementStartTokens()
{
return STMT_START_STRING;
}
/**
* Concrete parsers must imlement this method to do the real parsing.
* @param text sql text to be parsed.
* @return <code>ParsingResult</code> containing root AST node and <code>ParseException</code>s.
*/
protected synchronized ParsingResult doParse(String text)
{
java.io.StringReader sr = new java.io.StringReader( text );
java.io.Reader r = new java.io.BufferedReader( sr );
//ReInit will be generated by JavaCC
ReInit(r);
initParsing();
return startIgnoreException();
}
//Other methods
private ParsingResult startIgnoreException()
{
Node node = new ASTStart(JJTSTART);
try
{
node = startRootIgnoreException();
}catch (ParseException e) {
exceptions.add(e);
}
catch (TokenMgrError t)
{
ParseException e = new ParseException(t.getMessage());
if (token == null){
//when the error token occurs at the beginning
e.currentToken = new Token();
}else{
e.currentToken = token;
}
if (t.getToken() != null){
e.currentToken.next = t.getToken();
}else{
Token errtoken = new Token();
errtoken.beginLine = token.endLine;
errtoken.beginColumn = token.endColumn + 1;
errtoken.endLine = token.endLine;
errtoken.endColumn = token.endColumn + 1;
e.currentToken.next = errtoken;
}
exceptions.add(e);
}
catch (Throwable t)
{
// Activator.getDefault().log(t);
}
Boolean consumeException = (Boolean)getParameters().getProperty(ParserParameters.PARAM_CONSUME_EXCEPTION);
result.setRootNode(node);
if ( consumeException == null || consumeException.booleanValue())
{
result.setExceptions(knownExceptions);
}
else
{
result.setExceptions(exceptions);
}
return result;
}
private void initParsing(){
result = new IngresParsingResult();
exceptions = new ArrayList();
knownExceptions = new ArrayList();
}
private boolean isSupportedStatementStartToken(int kind)
{
for (int i=0; i<DEFINED_STMT_START.length; i++)
{
if (kind == DEFINED_STMT_START[i])
{
return true;
}
}
return false;
}
private boolean isStatementStartToken(int kind)
{
for (int i=0; i<STMT_START.length; i++)
{
if (kind == STMT_START[i])
{
return true;
}
}
return false;
}
private boolean isStatementToken(int kind)
{
if (kind == 0 || isStatementStartToken(kind))
{
return false;
}
for (int i=0; i<TERMINATORS.length; i++)
{
if (kind == TERMINATORS[i])
{
return false;
}
}
return true;
}
private boolean check(String unReservedKeyword)
{
Token currentToken = getToken(1);
int currentTokenKind = currentToken.kind;
String currentTokenImage = currentToken.image;
if (currentTokenKind == ID && currentTokenImage.equalsIgnoreCase(unReservedKeyword))
{
return true;
}
if (currentTokenKind == INVALID_TOKEN)
{
result.addExpectedUnreservedKeywords(unReservedKeyword);
}
return false;
}
private boolean check(int type, String multiKeyword)
{
return check(type, new String[]{multiKeyword});
}
/**
*multiKeywords will show as content assist proposal
*/
private boolean check(int type, String[] multiKeywords)
{
Token currentToken = getToken(1);
int currentTokenKind = currentToken.kind;
String currentTokenImage = currentToken.image;
if (currentTokenKind == type)
{
return true;
}
if (currentTokenKind == INVALID_TOKEN)
{
for (int i=0; i< multiKeywords.length; i++)
{
result.addExpectedUnreservedKeywords(multiKeywords[i]);
}
}
return false;
}
final private void logDebug(String message)
{
if (_debug)
{
//Activator.getDefault().log(message);
}
}
}
PARSER_END(IngresSQLParser)
SKIP:
{
" "
| "\n"
| "\r"
| "\t"
| "\f"
}
/* COMMENTS */
MORE :
{
"--" : IN_SINGLE_LINE_COMMENT
}
<IN_SINGLE_LINE_COMMENT>
SPECIAL_TOKEN :
{
<SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT
}
<IN_SINGLE_LINE_COMMENT>
MORE :
{
< ~[] >
}
/*
SPECIAL_TOKEN :
{
< SINGLE_LINE_COMMENT: "--"(~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
}
*/
TOKEN_MGR_DECLS : {
int commentNestingDepth = 0 ;
}
MORE : { "/*" { commentNestingDepth = 1 ; } : IN_MULTI_LINE_COMMENT }
< IN_MULTI_LINE_COMMENT > MORE : { "/*" { commentNestingDepth += 1 ; } }
< IN_MULTI_LINE_COMMENT > SPECIAL_TOKEN : { "*/" {
commentNestingDepth -= 1;
SwitchTo( commentNestingDepth==0 ? DEFAULT : IN_MULTI_LINE_COMMENT ); } }
< IN_MULTI_LINE_COMMENT > MORE : { <COMMENT_CONTENT: ~[]> {} }
TOKEN:
{
< INVALID_TOKEN: "!%^&" > //Using token will always causes exception
| < ADD: "add" >
| < ALTER: "alter" >
| < AND: "and" >
| < ANY: "any" >
| < AS: "as" >
| < ASC: "asc" >
| < AT: "at" >
| < AUTHORIZATION: "authorization" >
| < AVG: "avg" >
| < BEGIN: "begin" >
| < BETWEEN: "between" >
| < BY: "by" >
| < CASCADE: "cascade" >
| < CASE: "case" >
| < CHECK: "check" >
| < CHECKPOINT: "checkpoint" >
| < CLOSE: "close" >
| < COALESCE: "coalesce" >
| < COMMIT: "commit" >
| < CONSTRAINT: "constraint" >
| < CONTINUE: "continue" >
| < COUNT: "count" >
| < CREATE: "create" >
| < CURRENT: "current" >
| < CURSOR: "cursor" >
| < DATABASE: "database" >
| < DBEVENT: "dbevent" >
| < DECLARE: "declare" >
| < DEFAULT_VAL: "default" >
| < DELETE: "delete" >
| < DESC: "desc" >
| < DISTINCT: "distinct" >
| < DOMAIN: "domain" >
| < DROP: "drop" >
| < DUMP: "dump" >
| < ELSE: "else" >
| < END: "end" >
| < ESCAPE: "escape" >
| < EXCEPT: "except" >
| < EXCLUSIVE: "exclusive" >
| < EXEC: "exec" >
| < EXECUTE: "execute" >
| < EXISTS: "exists" >
| < FETCH: "fetch" >
| < FILLFACTOR: "fillfactor" >
| < FOR: "for" >
| < FOREIGN: "foreign" >
| < FROM: "from" >
| < FUNC: "func" >
| < FUNCTION: "function" >
| < GO: "\\g" > //terminator
| < GOTO: "goto" >
| < GRANT: "grant" >
| < GROUP: "group" >
| < HAVING: "having" >
| < IF: "if" >
| < IN: "in" >
| < INDEX: "index" >
| < INSERT: "insert" >
| < INTERSECT: "intersect" >
| < INTEGRITY: "integrity" >
| < INTO: "into" >
| < IS: "is" >
| < ISOLATION: "isolation" >
| < JOIN: "join" >
| < KEY: "key" >
| < KILL: "kill" >
| < LEVEL: "level" >
| < LIKE: "like" >
| < LOAD: "load" >
| < LOCATION: "location" >
| < MAX: "max" >
| < MIN: "min" >
| < MODIFY: "modify" >
| < NO: "no" >
| < NOT: "not" >
| < NULL: "null" >
| < NULLIF: "nullif" >
| < OF: "of" >
| < OFF: "off" >
| < ON: "on" >
| < ONLY: "only" >
| < OPEN: "open" >
| < OPTION: "option" >
| < OR: "or" >
| < ORDER: "order" >
| < OUT: "out" >
| < OUTPUT: "output" >
| < PARTITION: "partition" >
| < PERM: "perm" >
| < PERMANENT: "permanent" >
| < PREPARE: "prepare" >
| < PRIMARY: "primary" >
| < PRIVILEGES: "privileges" >
| < PRINT: "print" >
| < PROCEDURE: "procedure" >
| < PROFILE: "profile" >
| < PUBLIC: "public" >
| < READ: "read" >
| < REFERENCES: "references" >
| < REMOVE: "remove" >
| < REORGANIZE: "reorganize" >
| < RETURN: "return" >
| < REVOKE: "revoke" >
| < ROLE: "role" >
| < ROLLBACK: "rollback" >
| < ROWCOUNT: "rowcount" >
| < ROWS: "rows" >
| < RULE: "rule" >
| < SAVE: "save" >
| < SCHEMA: "schema" >
| < SECURITY_AUDIT: "security_audit" >
| < SECURITY_ALARM: "security_alarm" >
| < SELECT: "select" >
| < SEQUENCE: "sequence" >
| < SESSION: "session" >
| < SET: "set" >
| < SHARED: "shared" >
| < SOME: "some" >
| < STATISTICS: "statistics" >
| < SUM: "sum" >
| < SYNONYM: "synonym" >
| < TABLE: "table" >
| < TEMPORARY: "temporary" >
| < TO: "to" >
| < TRANSACTION: "transaction" >
| < UNION: "union" >
| < UNIQUE: "unique" >
| < UNPARTITION: "unpartition" >
| < UPDATE: "update" >
| < USER: "user" >
| < USING: "using" >
| < VALUES: "values" >
| < VARYING: "varying" >
| < VIEW: "view" >
| < WHEN: "when" >
| < WHERE: "where" >
| < WHILE: "while" >
| < WITH: "with" >
| < WORK: "work" >
| < II_DBA: "$dba">
| < II_INGRES: "$ingres" >
}
/*
<DESCRIPTION_START_STATE> TOKEN:
{
< OPENDESCRIPTION: "\r\n" > : DESCRIPTION_STATE
}
*/
// <DESCRIPTION_STATE> TOKEN: /* Line */
/*
{
< CLOSEDESCRIPTION: "~" > : DEFAULT
| < DESCRIPTION: (~["~"])* "~" > : DEFAULT
}
*/
TOKEN: /* Literals */
{
< INTEGER_LITERAL: (["0"-"9"])+ >
| < FLOATING_POINT_LITERAL:
(["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?
| "." (["0"-"9"])+ (<EXPONENT>)?
| (["0"-"9"])+ (<EXPONENT>)?
>
| < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
| < SINGLE_STRING_LITERAL: "'" (~["'"])* ( "''" (~["'"])* )* "'" >
| < DOUBLE_STRING_LITERAL: "\"" (~["\""])* ( "\"\"" (~["\""])* )* "\"" >
| < BINARY_LITERAL: "0" ("x" | "X" ) ( <HEXDIGIT> )+ >
| < #HEXDIGIT: ["A"-"F", "a"-"f", "0"-"9"] >
| < MONEY_LITERAL: ("$" | "\u00a5" | "\u00a3" )? <FLOATING_POINT_LITERAL> >
}
Token string_literal() : {Token t;}
{
( t = <SINGLE_STRING_LITERAL> | t = <DOUBLE_STRING_LITERAL> )
{return t;}
}
TOKEN: /* Identifiers */
{
< ID: ( <LETTER> | "_" )+ ( <SYMBOL> | <DIGIT> | <LETTER> | "#" | "@" )* >
| < SQUARE_BRACKET_ID: ("[" <ID> "]")>
| < #VAR_NAME_BODY: ( <SYMBOL> | <DIGIT> | <LETTER> | "#" )+ ( <SYMBOL> | <DIGIT> | <LETTER> | "#" | "@" )* >
| < VAR_NAME: "@"<VAR_NAME_BODY> >
| < LABEL: <ID>":" >
| < GLOBAL_VAR_NAME: "@@"<VAR_NAME_BODY> >
| < TEMP_TABLE_NAME: "#" ( <SYMBOL> | <DIGIT> | <LETTER> | "#" | "@" )+ >
/*FIXME: Unicode code point ranges from 0000 to 10ffff, but JavaCC seems only recognize four digits following "u". Not sure what the consequence will be for now.*/
// | < #LETTER: ["A"-"Z", "a"-"z", "\u0080"-"\uffff"] > //Umlaute?!?
| < #LETTER: ["A"-"Z", "a"-"z", "ä", "Ä", "ö", "Ö", "ü", "Ü","ß","\u0080"-"\uffff"] >
| < #DIGIT: ["0"-"9"] >
| < #SYMBOL: ["$","_"] >
}
TOKEN: /* Ingres specific Identifiers */
{
//32chars max, unique til 24.char
//start with letter or "_", contain "#", "@", "$", digits, no keywords
//delimited-> "", additional: keywords, specsymb
< #SPECSYMB:
["&", "*", "@", ":", ",", "#", "=", "/", "<", ">", "(", ")", "-", "%", ".", "+", "?",
"'"," ", "_", "|", "\\","^", "{", "}", "!", "~"]> //+ASCII96, never ASCII127 aka DEL
|< #DELIM_START: ( <SPECSYMB> | <DIGIT> | <LETTER> )* > //no $ allowed
|< #DELIM_PART: ( <SPECSYMB> | <DIGIT> | <LETTER> | "$" )* >
|< DELIM_IDENT: "\"" ( <DELIM_START> )* ("\"\"" (<DELIM_PART>)* )* "\"">
}
TOKEN: /* Separators and operators */
{
< CONCAT: "||" >
| < COMMA: "," >
| < SEMICOLON: ";" >
| < DOT: "." >
| < ROWTYPE: "%rowtype" >
| < TILDE: "~" >
| < LESS: "<" >
| < LESSEQUAL: "<=" >
| < GREATER: ">" >
| < GREATEREQUAL: ">=" >
| < EQUAL: "=" >
| < NOTEQUAL: "!=" >
| < JOINPLUS: "(+)" >
| < OPENPAREN: "(" >
| < CLOSEPAREN: ")" >
| < ASTERISK: "*" >
| < SLASH: "/" >
| < PLUS: "+" >
| < MINUS: "-" >
| < QUESTIONMARK: "?" >
| < LEQJOIN: "*="> //FIXME:
| < REQJOIN: "=*">
| < JAVA_REF: ">>">
}
/*******************************************************************
* Unreserved Keywords
*******************************************************************/
Token UK_ABSOLUTE() : {Token t;}
{
(LOOKAHEAD({check("absolute")}) t = <ID> )
{return t;}
}
Token UK_AFTER() : {Token t;}
{
(LOOKAHEAD({check("after")}) t = <ID> )
{return t;}
}
Token UK_ALL() : {Token t;}
{
(LOOKAHEAD({check("all")}) t = <ID> )
{return t;}
}
Token UK_BIGINT() : {Token t;}
{
(LOOKAHEAD({check("bigint")}) t = <ID> )
{return t;}
}
Token UK_BINARY() : {Token t;}
{
(LOOKAHEAD({check("binary")}) t = <ID> )
{return t;}
}
Token UK_BEFORE() : {Token t;}
{
(LOOKAHEAD({check("before")}) t = <ID> )
{return t;}
}
Token UK_BIT() : {Token t;}
{
(LOOKAHEAD({check("bit")}) t = <ID> )
{return t;}
}
Token UK_BOOLEAN() : {Token t;}
{
(LOOKAHEAD({check("boolean")}) t = <ID> )
{return t;}
}
Token UK_CHAR() : {Token t;}
{
(LOOKAHEAD({check("char")}) t = <ID> )
{return t;}
}
Token UK_CHAR_S() : {Token t;}
{
(LOOKAHEAD({check("character")}) t = <ID> )
{return t;}
}
Token UK_DATE() : {Token t;}
{
(LOOKAHEAD({check("date")}) t = <ID> )
{return t;}
}
Token UK_DATETIME() : {Token t;}
{
(LOOKAHEAD({check("datetime")}) t = <ID> )
{return t;}
}
Token UK_DB2SQL() : {Token t;}
{
(LOOKAHEAD({check("db2sql")}) t = <ID> )
{return t;}
}
Token UK_DECIMAL() : {Token t;}
{
(LOOKAHEAD({check("decimal")}) t = <ID> )
{return t;}
}
Token UK_DECIMAL_S() : {Token t;}
{
(LOOKAHEAD({check("dec")}) t = <ID> )
{return t;}
}
TOKEN:{ < UK_DOUBLE_PRECISION: "double" ("\t"|" "|"\r"|"\n")+ "precision"> }
Token UK_DOUBLE_PRECISION() : {Token t;}
{
(LOOKAHEAD({check( UK_DOUBLE_PRECISION, "double precision")}) t = <UK_DOUBLE_PRECISION> )
{return t;}
}
Token UK_EACH() : {Token t;}
{
(LOOKAHEAD({check("each")}) t = <ID> )
{return t;}
}
Token UK_FALSE() : {Token t;}
{
(LOOKAHEAD({check("false")}) t = <ID> )
{return t;}
}
Token UK_FIRST() : {Token t;}
{
(LOOKAHEAD({check("first")}) t = <ID> )
{return t;}
}
Token UK_FLOAT() : {Token t;}
{
(LOOKAHEAD({check("float")}) t = <ID> )
{return t;}
}
Token UK_FLOAT4() : {Token t;}
{
(LOOKAHEAD({check("float4")}) t = <ID> )
{return t;}
}
Token UK_FLOAT8() : {Token t;}
{
(LOOKAHEAD({check("float8")}) t = <ID> )
{return t;}
}
Token UK_FULL() : {Token t;}
{
(LOOKAHEAD({check("full")}) t = <ID> )
{return t;}
}
Token UK_IMAGE() : {Token t;}
{
(LOOKAHEAD({check("image")}) t = <ID> )
{return t;}
}
Token UK_INNER() : {Token t;}
{
(LOOKAHEAD({check( "inner")}) t = <ID> )
{return t;}
}
Token UK_INSENSITIVE() : {Token t;}
{
(LOOKAHEAD({check("insensitive")}) t = <ID> )
{return t;}
}
Token UK_INT() : {Token t;}
{
(LOOKAHEAD({check("integer")}) t = <ID> )
{return t;}
}
Token UK_INT1() : {Token t;}
{
(LOOKAHEAD({check("integer1")}) t = <ID> )
{return t;}
}
Token UK_INT2() : {Token t;}
{
(LOOKAHEAD({check("integer2")}) t = <ID> )
{return t;}
}
Token UK_INT4() : {Token t;}
{
(LOOKAHEAD({check("integer4")}) t = <ID> )
{return t;}
}
Token UK_INT8() : {Token t;}
{
(LOOKAHEAD({check("integer8")}) t = <ID> )
{return t;}
}
Token UK_LAST() : {Token t;}
{
(LOOKAHEAD({check("last")}) t = <ID> )
{return t;}
}
Token UK_LEFT() : {Token t;}
{
(LOOKAHEAD({check("left")}) t = <ID> )
{return t;}
}
Token UK_MODE() : {Token t;}
{
(LOOKAHEAD({check("mode")}) t = <ID> )
{return t;}
}
Token UK_MONEY() : {Token t;}
{
(LOOKAHEAD({check("money")}) t = <ID> )
{return t;}
}
Token UK_NAME() : {Token t;}
{
(LOOKAHEAD({check("name")}) t = <ID> )
{return t;}
}
Token UK_NCHAR() : {Token t;}
{
(LOOKAHEAD({check("nchar")}) t = <ID> )
{return t;}
}
Token UK_NEXT() : {Token t;}
{
(LOOKAHEAD({check("next")}) t = <ID> )
{return t;}
}
Token UK_NEW() : {Token t;}
{
(LOOKAHEAD({check("new")}) t = <ID> )
{return t;}
}
Token UK_NEW_TABLE() : {Token t;}
{
(LOOKAHEAD({check("new_table")}) t = <ID> )
{return t;}
}
Token UK_NONE() : {Token t;}
{
(LOOKAHEAD({check("none")}) t = <ID> )
{return t;}
}
TOKEN:{ < UK_NO_SCROLL: "no" ("\t"|" "|"\r"|"\n")+ "scroll"> }
Token UK_NO_SCROLL() : {Token t;}
{
(LOOKAHEAD({check( UK_NO_SCROLL, "no scroll")}) t = <UK_NO_SCROLL> )
{return t;}
}
Token UK_NUMERIC() : {Token t;}
{
(LOOKAHEAD({check("numeric")}) t = <ID> )
{return t;}
}
Token UK_NVARCHAR() : {Token t;}
{
(LOOKAHEAD({check("nvarchar")}) t = <ID> )
{return t;}
}
Token UK_OF() : {Token t;}
{
(LOOKAHEAD({check("of")}) t = <ID> )
{return t;}
}
Token UK_OLD() : {Token t;}
{
(LOOKAHEAD({check("old")}) t = <ID> )
{return t;}
}
Token UK_OLD_TABLE() : {Token t;}
{
(LOOKAHEAD({check("old_table")}) t = <ID> )
{return t;}
}
Token UK_OUTER() : {Token t;}
{
(LOOKAHEAD({check("outer")}) t = <ID> )
{return t;}
}
Token UK_PRIOR() : {Token t;}
{
(LOOKAHEAD({check("prior")}) t = <ID> )
{return t;}
}
Token UK_REAL() : {Token t;}
{
(LOOKAHEAD({check("real")}) t = <ID> )
{return t;}
}
Token UK_REFERENCING() : {Token t;}
{
(LOOKAHEAD({check("referencing")}) t = <ID> )
{return t;}
}
Token UK_RELATIVE() : {Token t;}
{
(LOOKAHEAD({check("relative")}) t = <ID> )
{return t;}
}
Token UK_RESULT() : {Token t;}
{
(LOOKAHEAD({check("result")}) t = <ID> )
{return t;}
}
Token UK_RIGHT() : {Token t;}
{
(LOOKAHEAD({check("right")}) t = <ID> )
{return t;}
}
Token UK_ROW() : {Token t;}
{
(LOOKAHEAD({check("row")}) t = <ID> )
{return t;}
}
Token UK_SCROLL() : {Token t;}
{
(LOOKAHEAD({check("scroll")}) t = <ID> )
{return t;}
}
TOKEN:{ < UK_SEMI_SENSITIVE: "semi" ("\t"|" "|"\r"|"\n")+ "sensitive"> }
Token UK_SEMI_SENSITIVE() : {Token t;}
{
(LOOKAHEAD({check( UK_SEMI_SENSITIVE, "semi sensitive")}) t = <UK_SEMI_SENSITIVE> )
{return t;}
}
Token UK_SMALLDATETIME() : {Token t;}
{
(LOOKAHEAD({check("smalldatetime")}) t = <ID> )
{return t;}
}
Token UK_SMALLINT() : {Token t;}
{
(LOOKAHEAD({check("smallint")}) t = <ID> )
{return t;}
}
Token UK_SMALLMONEY() : {Token t;}
{
(LOOKAHEAD({check("smallmoney")}) t = <ID> )
{return t;}
}
Token UK_STATEMENT() : {Token t;}
{
(LOOKAHEAD({check("statement")}) t = <ID> )
{return t;}
}
Token UK_TEXT() : {Token t;}
{
(LOOKAHEAD({check("text")}) t = <ID> )
{return t;}
}
Token UK_THEN() : {Token t;}
{
(LOOKAHEAD({check("then")}) t = <ID> )
{return t;}
}
Token UK_TIME() : {Token t;}
{
(LOOKAHEAD({check("time")}) t = <ID> )
{return t;}
}
Token UK_TIMESTAMP() : {Token t;}
{
(LOOKAHEAD({check("timestamp")}) t = <ID> )
{return t;}
}
Token UK_TINYINT() : {Token t;}
{
(LOOKAHEAD({check("tinyint")}) t = <ID> )
{return t;}
}
Token UK_TRUE() : {Token t;}
{
(LOOKAHEAD({check("true")}) t = <ID> )
{return t;}
}
Token UK_UNICHAR() : {Token t;}
{
(LOOKAHEAD({check("unichar")}) t = <ID> )
{return t;}
}
Token UK_UNIVARCHAR() : {Token t;}
{
(LOOKAHEAD({check("univarchar")}) t = <ID> )
{return t;}
}
Token UK_VARBINARY() : {Token t;}
{
(LOOKAHEAD({check("varbinary")}) t = <ID> )
{return t;}
}
Token UK_VARCHAR() : {Token t;}
{
(LOOKAHEAD({check("varchar")}) t = <ID> )
{return t;}
}
TOKEN:{ < UK_VARCHAR_S: "char" ("\t"|" "|"\r"|"\n")+ "varying"> }
Token UK_VARCHAR_S() : {Token t;}
{
(LOOKAHEAD({check( UK_VARCHAR_S, "char varying")}) t = <UK_VARCHAR_S> )
{return t;}
}
TOKEN:{ < UK_VARCHAR_S1: "character" ("\t"|" "|"\r"|"\n")+ "varying"> }
Token UK_VARCHAR_S1() : {Token t;}
{
(LOOKAHEAD({check( UK_VARCHAR_S1, "character varying")}) t = <UK_VARCHAR_S1> )
{return t;}
}
/**
* Ignore exception during parsing so that the rest part can be parsed
* rule: [ delimiter()] ( statement() )* <EOF>
*/
Node startRootIgnoreException() #Start: {}
{
(
[ delimiter()]
(
try{
statement()
}catch (ParseException e) {
//TODO can we create an UnknownStatement?
exceptions.add(e);
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
} catch (Throwable t) {
//TODO: handle this throwable separately in SQLEditor:setOutlineContent.
ParseException e = new ParseException(ParserUtil.getErrorMessage(getToken(0)));
e.currentToken = getToken(0);
exceptions.add(e);
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
}
)* <EOF>
)
{ return jjtThis; }
}
ASTSQLDelimiter delimiter() #SQLDelimiter:{}
{
(LOOKAHEAD(2) (<SEMICOLON>|<GO>))+
{
return jjtThis;
}
}
void statement() : {setScope("SQL Statement", SCOPE_DEFAULT);/*the default scope*/result.clearCurrentTableNames(isContentAssist);}
{
try{
(
(
LOOKAHEAD( <CREATE> ) create_stmts()
| LOOKAHEAD( <ALTER> ) alter_stmts()
| LOOKAHEAD( <DROP> ) drop_stmts()
| LOOKAHEAD( <INSERT> ) insert_stmts()
| LOOKAHEAD( <UPDATE> ) update_stmts()
| LOOKAHEAD( <SELECT> ) select()
| LOOKAHEAD( <DELETE> ) delete_stmts()
| LOOKAHEAD( <REMOVE> ) remove_stmts()
| LOOKAHEAD(1) return_stmt()
| LOOKAHEAD(2) execute_stmt()
| LOOKAHEAD(1) if_stmt()
| LOOKAHEAD(1) print()
| LOOKAHEAD(1) unknown_sql_stmt()
) #SQLStatement
| LOOKAHEAD(1) declare()
)
[LOOKAHEAD(<SEMICOLON>|<GO>) delimiter()]
}catch(ParseException e){
exceptions.add(e);
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
//to generate an ASTSQLDelimiter node so that the statement can be separated
if (getToken(1).kind == SEMICOLON )
{
delimiter();
}
} catch (Throwable t) {
//TODO: handle this throwable separately in SQLEditor:setOutlineContent.
ParseException e = new ParseException(ParserUtil.getErrorMessage(getToken(0)));
e.currentToken = getToken(0);
exceptions.add(e);
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
if ( getToken(1).kind == SEMICOLON )
{
delimiter();
}
}
{
}
}
void unknown_sql_stmt() : {}
{
LOOKAHEAD({ !isSupportedStatementStartToken(getToken(1).kind) })
(
<CLOSE> | <COMMIT> | <CONTINUE> | <DECLARE> | <DUMP> | <EXEC> |
<GOTO> | <GRANT> | <KILL> | <LOAD> | <MODIFY> | <OPEN> | <PREPARE> |
<RETURN> | <REVOKE> |<ROLLBACK> | <SAVE> | <SET> | <WHILE> | <ID>
)
{
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
}
}
void any_stmt_token():{}
{
{
error_skiptobefore(new int[]{END}, STMT_START_TERMINATORS);
}
}
void create_stmts() : {}
{
LOOKAHEAD(2) <CREATE> <PROCEDURE> create_proc_body()
| LOOKAHEAD(2) <CREATE>
(<DBEVENT>
|<GROUP>
|unique() <INDEX>
|<INTEGRITY>
|<LOCATION>
|<PROFILE>
|<ROLE>
|<SCHEMA>
|<SECURITY_ALARM>
|<SEQUENCE>
|<SYNONYM>
|<TABLE>
|<USER>
|<VIEW>
)
any_stmt_token()
}
void create_proc_body() : {}
{
<ID>
[cdbp_parmspec()] [cdbp_resrowspec()]
(<AS>|<EQUAL>) cdbp_beblock()
}
void cdbp_parmspec() : {}
{
<OPENPAREN> cdbp_parmlist() <CLOSEPAREN>
}
void cdbp_parmlist() : {}
{
cdbp_parmitem() (<COMMA> cdbp_parmitem())*
}
void cdbp_parmitem() : {}
{
<ID> [<EQUAL>] datatype() //ID zuwenig -> lokale Vars bei dynSQL :ID
( (<WITH>|<NOT>) (<DEFAULT_VAL>|<NULL>) )* //FIXME: "default" und "null" sollen nur je 1x auftreten
}
void cdbp_resrowspec() : {}
{
UK_RESULT() UK_ROW()
(
datatype()
( (<WITH>|<NOT>) (<DEFAULT_VAL>|<NULL>) )*
)+
}
void cdbp_beblock() : {}
{
[declare()] <BEGIN> (statement())+ <END>
}
void unique() : {}
{
[ <UNIQUE> ]
}
void alter_stmts() : {}
{
<ALTER>
(<GROUP>
|<LOCATION>
|<PROFILE>
|<ROLE>
|<SECURITY_AUDIT>
|<SEQUENCE>
|<TABLE>
|<USER>
)
any_stmt_token()
}
void drop_stmts() : {}
{
LOOKAHEAD(2) <DROP> <PROCEDURE> <ID>
|LOOKAHEAD (2)<DROP>
(<DBEVENT>
|<DOMAIN>
|<GROUP>
|<INDEX>
|<INTEGRITY>
|<LOCATION>
|<PROFILE>
|<ROLE>
|<RULE>
|<SECURITY_ALARM>
|<SEQUENCE>
|<SYNONYM>
|<TABLE>
|<USER>
|<VIEW>
|<ID>
)
any_stmt_token()
}
void delete_stmts() : {}
{
delete()
}
void insert_stmts() : {}
{
insert()
}
void update_stmts() : {}
{
update()
}
void remove_stmts() : {}
{
<REMOVE>
(<DBEVENT>
|<TABLE>
)
any_stmt_token()
}
ASTSQLDataType datatype() #SQLDataType: {}
{
(
base_datatype()
)
{return jjtThis;}
}
ASTSQLDataType base_datatype() #SQLDataType: {Token t= null; int length=0, scale=-1; String name=null; }
{
try{
(
( t = UK_CHAR() | t = UK_CHAR_S() | t = UK_TEXT() | UK_VARCHAR() ) [ LOOKAHEAD(2) "(" length = number() ")" ]
| t = UK_NCHAR() [ LOOKAHEAD(2) "(" length = number() ")" ]
| t = UK_NVARCHAR() [ LOOKAHEAD(2) "(" length = number() ")" ]
| ( t = UK_TINYINT() | t = UK_SMALLINT() | t = UK_INT() | t = UK_BIGINT() )
| ( t = UK_INT1() | t = UK_INT2() | t = UK_INT4() | t = UK_INT8() )
| ( t = UK_NUMERIC() | t = UK_DECIMAL() | t = UK_DECIMAL_S() )
[ LOOKAHEAD(2) "(" length = number() [ "," scale = number() ] ")"
{
if ((length < scale))
{
ParseException e = new ParseException("You must specify a scale that is less than or equal to the size");
e.currentToken = t.next;
exceptions.add(e);
}
}
]
| t = UK_FLOAT() [ LOOKAHEAD(2) "(" length = number() ")" ]
| t = UK_DOUBLE_PRECISION()
| t = UK_FLOAT4() [ LOOKAHEAD(2) "(" length = number() ")" ]
| t = UK_FLOAT8() [ LOOKAHEAD(2) "(" length = number() ")" ]
| t = UK_REAL()
| t = UK_DATE()
| t = UK_MONEY()
// TODO:
// logical types
// byte, byte varying, long varchar, long byte
// | t = UK_BINARY() [ LOOKAHEAD(2) "(" length = number() ")" ]
// | t = UK_BIT()
// | t = UK_DATETIME()
// | t = UK_SMALLDATETIME()
// | t = UK_SMALLMONEY()
// | t = UK_TIMESTAMP()
// | t = UK_TIME()
// | t = UK_UNICHAR()[ LOOKAHEAD(2) "(" length = number() ")" ]
// | t = UK_UNIVARCHAR()[ LOOKAHEAD(2) "(" length = number() ")" ]
// | t = UK_VARBINARY() [ LOOKAHEAD(2) "(" length = number() ")" ]
// | name = java_name() [ LOOKAHEAD(2) "(" length = number() ")" ] //TODO: retrieve user defined datatype from ASE system table
)
{
if (t != null )
{
((ASTSQLDataType)jjtThis).setName(t.image);
}else{
((ASTSQLDataType)jjtThis).setName(name);
}
((ASTSQLDataType)jjtThis).setLength(length);
((ASTSQLDataType)jjtThis).setScale(scale);
return jjtThis;
}
}catch(ParseException e){
exceptions.add(e);
return jjtThis;
}
}
//not needed, if not in DataTypes
String java_name() : {Token t = null; String wholename = null; String part = null;}
{
t = id_or_string() {wholename = t.image;} [LOOKAHEAD(2) "." part = java_name() {wholename += "." + part;} ]
{return wholename;}
}
void insert() : {setScope("insert", SCOPE_TABLES);}
{
<INSERT> <INTO> ii_obj_spec() {setScope("insert", SCOPE_COLUMNS);}
optional_insert_col_list() insert_source()
}
void optional_insert_col_list() : {}
{
[ LOOKAHEAD(2) "(" insert_column_list() ")" ]
}
void insert_column_list() : {}
{
ii_col_spec()
( "," ii_col_spec() )*
}
void insert_source() : {}
{
<VALUES> "(" insert_values() ")"
| select()
}
void insert_values() : {}
{
[ insert_value_list()]
}
void insert_value_list() : {}
{
insert_value()
( "," insert_value() )*
}
void insert_value() : {}
{
expression()
| <DEFAULT_VAL>
}
void update() : {}
{
<UPDATE>
{setScope("update", SCOPE_TABLES);} ii_obj_spec()
<SET>
{setScope("update", SCOPE_COLUMNS);} set_clause_list()
{setScope("update", SCOPE_TABLES);} from_where_clause()
}
void set_clause_list() : {}
{
set_clause()
( "," set_clause() )*
}
void set_clause() : {}
{
(
LOOKAHEAD(3) primary()
| variable_assignment()
)
"=" expression()
}
void select() : {}
{
query_expression() order_by_clause()
}
void query_expression() : {}
{
query_term() ( <UNION> all_option() query_term() )*
}
void query_term() : {}
{
query_primary()
}
void all_option() : {}
{
[ UK_ALL() ]
}
void query_primary() : {}
{
simple_table()
| "(" query_expression() ")"
}
void simple_table() : {}
{
query_specification()
}
void query_specification() : {}
{
<SELECT> all_distinct()
{setScope("query_specification", SCOPE_COLUMNS);} select_list()
{setScope("query_specification", SCOPE_TABLES);}
optional_from_clause() [ where_clause() ] group_by_clause() having_clause()
}
void all_distinct() : {}
{
[ UK_ALL()
| <DISTINCT> ]
}
void delete() : {setScope("delete", SCOPE_TABLES);}
{
<DELETE> <FROM> ii_tbl_spec()
[where_clause()]
}
void subquery() : {}
{
"(" subquery_content() ")"
}
void subquery_content() #SQLStatement: {}
{
<SELECT> subq_select()
{}
}
void subq_select() : {}
{
[ subq_all_distinct() subquery_select_expression()
optional_from_clause()
[ where_clause() ]
group_by_clause() having_clause() subq_fake_union() subq_fake_order_by_clause() ]
}
void subq_all_distinct() : {}
{
[ UK_ALL()
| <DISTINCT> ]
}
void subq_fake_union() : {}
{
[ <UNION> subq_fake_select() ]
}
void subq_fake_select() : {}
{
[ LOOKAHEAD(2) subq_fake_primary() <UNION> ] subq_fake_primary()
}
void subq_fake_primary() : {}
{
<SELECT> subq_fake_all_distinct() subq_fake_select_expression()
optional_from_clause()
[ where_clause() ]
group_by_clause() having_clause()
}
void subq_fake_all_distinct() : {}
{
[ UK_ALL()
| <DISTINCT> ]
}
void subq_fake_select_expression() : {}
{
LOOKAHEAD(2) subq_expression_list()
| [ ii_schema_spec() ] "*"
}
void subq_fake_order_by_clause() : {}
{
[ <ORDER> <BY> subq_fake_order_by_list() ]
}
void subq_fake_order_by_list() : {}
{
subq_fake_order_by_item()
( "," subq_fake_order_by_item() )*
}
void subq_fake_order_by_item() : {}
{
expression() [ order_by_option() ]
}
void subq_fake_cursor_update_list() : {}
{
[ <OF> subq_fake_cursor_column_list()]
}
void subq_fake_cursor_column_list() : {}
{
subq_fake_curs_upd_column()
( "," subq_fake_curs_upd_column() )*
}
void subq_fake_curs_upd_column() : {}
{
ii_obj_spec()
}
void compound_statement() : {}
{
<BEGIN> nullprogram() <END>
}
void nullprogram() : {}
{
[ program() ]
}
void program() : {}
{
( statement() )+
}
void declare() : {}
{
{int oldScope = setScope(SCOPE_DEFINE_VARIABLES);}
declare_prefix() declaration_list()
{setScope(oldScope);}
}
void declare_prefix() #DeclareKeyword : {}
{
<DECLARE>
}
void fetch_orientation() : {}
{
//Though weird, FIRST can be used as object name, so LOOKAHEAD(2)
<FETCH> [LOOKAHEAD( UK_NEXT() | UK_PRIOR() | UK_FIRST() | UK_LAST() | UK_ABSOLUTE() | UK_RELATIVE(),
{getToken(2).kind != INTO && getToken(2).kind != FROM} )
( UK_NEXT() | UK_PRIOR() | UK_FIRST() | UK_LAST() | UK_ABSOLUTE() | UK_RELATIVE() )
]
}
void fetch_val_spec() : {Token t=null;}
{
[ t = <VAR_NAME>
| number()]
}
void fetch_into_clause() : {}
{
[ <INTO> fetch_into_list()]
}
void fetch_into_list() : {}
{
variable_assignment()
( "," variable_assignment() )*
}
void fetch_from_spec() : {}
{
[ <FROM> ]
}
void return_stmt() : {}
{
<RETURN> optional_expression()
}
void execute_stmt() : {}
{
<EXECUTE> <PROCEDURE> any_stmt_token()
}
void optional_expression() : {}
{
[ LOOKAHEAD(2) expression()]
}
void if_stmt() : {}
{
(if_prefix() statement() [ LOOKAHEAD(1) <ELSE> statement() ])
}
void if_prefix() : {}
{
<IF> boolean_expression()
}
void begin_tran() : {}
{
<BEGIN> <TRANSACTION> optional_xact_name()
}
void commit_tran() : {}
{
<COMMIT> tran_or_work() optional_xact_name()
}
void tran_or_work() : {}
{
[ <TRANSACTION>
| <WORK> ]
}
void rollback_tran() : {}
{
<ROLLBACK> tran_or_work() optional_xact_name()
}
void optional_xact_name() : {}
{
[ LOOKAHEAD(2) xact_name()]
}
void xact_name() : {}
{
<INTEGER_LITERAL> ":" <ID> "." <ID>
| id()
}
void print() : {}
{
<PRINT> pr_arglist()
}
void pr_arglist() : {}
{
printstring() arglist()
}
void arglist() : {}
{
( "," literal() )*
}
void printstring() : {}
{
string_literal()
| variable()
| null_stmt()
}
Token id_or_string() : {Token t;}
{
( t = idplus()
| t = string_literal()
)
{return t;}
}
//Special case: "NEW" can be used as id
Token idplus() : {Token t;}
{
( t = <ID>
| t = <TEMP_TABLE_NAME> //TEMP_TABLE_NAME can also be used as column name
| t = <SQUARE_BRACKET_ID>
)
{return t;}
}
void select_list() : {}
{
select_expression()
( "," select_expression() )*
}
void select_expression() : {}
{
LOOKAHEAD(<VAR_NAME> "=") ( select_or_set_variable_assignment())
| LOOKAHEAD(idplus() "=") idplus() "=" ( expression() )
| LOOKAHEAD(string_literal() "=") string_literal() "=" ( expression())
// | "*"
| LOOKAHEAD([ii_schema_spec()] "*") [ii_schema_spec()] "*"
| LOOKAHEAD(expression()) ( expression())
[
LOOKAHEAD(2)
( LOOKAHEAD(2)( optional_as() ( idplus() | string_literal() ) )
| "=" expression()
)
]
//we have put java_memberref support in expression()
//| java_memberref() "=" expression()
}
void select_or_set_variable_assignment() : {}
{
variable_assignment() "=" expression()
}
void optional_as() : {}
{
[ <AS> ]
}
void subquery_select_expression() : {}
{
LOOKAHEAD(3) subq_expression_list()
| [ ii_schema_spec() ] "*"
}
void declaration_list() : {}
{
declaration()
( comma() declaration() )*
}
void comma() #DeclareComma : {}
{
","
}
void declaration() #SQLParam: {Token name=null; String defaultValue=null; Node type=null; int direction = 0;}
{
try{
name = <VAR_NAME>
type = base_datatype()
defaultValue = optional_param_default()
direction = param_options()
}catch(ParseException e){
exceptions.add(e);
error_skiptobefore(new int[]{}, new int[]{COMMA, CLOSEPAREN, WITH, AS});
}
{
((ASTSQLParam)jjtThis).setName(name.image);
((ASTSQLParam)jjtThis).setType(type.toString());
((ASTSQLParam)jjtThis).setTypeObject((ASTSQLDataType)type);
if (defaultValue != null){
((ASTSQLParam)jjtThis).setDefaultValue(defaultValue);
}
((ASTSQLParam)jjtThis).setDirection(direction);
}
}
String optional_param_default() : {String t = null;}
{
[ "=" t = literal()]
{return t;}
}
int param_options() : {int direction = 0;}
{
[ <IN>
| out_option() {direction = 1;}]
{return direction;}
}
void out_option() : {}
{
<OUT>
| <OUTPUT>
}
void shared() : {}
{
[ <SHARED> ]
}
void forceoptions() : {}
{
[ LOOKAHEAD(2)
"("
[ LOOKAHEAD(2)
<INTEGER_LITERAL> [ LOOKAHEAD(2) forceoption_terms() ]
| <PARTITION> <ID>
| forceoption_terms()
]
")"
]
}
void forceoption_terms() : {}
{
( forceoption_term() )+
}
void forceoption_term() : {}
{
forceindex()
| forcestrategy()
}
void forceindex() : {}
{
<INDEX> ( <INTEGER_LITERAL> | idplus() )
}
void forcestrategy() : {}
{
<ID> [ number() ]
| "(" <ID> ( <ID> ")" | number() number() ")" )
}
void inner_join() : {}
{
[UK_INNER()] <JOIN>
}
void oj_operator() : {}
{
UK_LEFT() [UK_OUTER()] <JOIN>
| UK_RIGHT() [UK_OUTER()] <JOIN>
| inner_join()
}
void from_where_clause() : {}
{
[ LOOKAHEAD(2) <WHERE> <CURRENT> <OF> ii_obj_spec()
| from_clause() [ where_clause() ]
| where_clause() ]
}
void where_current_clause() : {}
{
[ LOOKAHEAD(2) <WHERE> <CURRENT> <OF> ii_obj_spec()
| where_clause() ]
}
void from_clause() : {}
{
<FROM>
from_list()
}
void optional_from_clause() : {}
{
[ from_clause() ]
}
void from_list() : {}
{
from_table()
( "," from_table() {} )*
}
void from_table() : {}
{
{setScope("from_clause", SCOPE_TABLES);}
from_item()
{setScope("from_clause", SCOPE_DEFAULT);}
}
void from_item() : {}
{
(
LOOKAHEAD(from_unit()) from_unit()
(
LOOKAHEAD(2) oj_operator() from_unit() <ON>
{setScope("from_item", SCOPE_COLUMNS);}
boolean_expression()
)*
| LOOKAHEAD(3) "(" from_unit()
(
LOOKAHEAD(2) oj_operator() from_unit() <ON> boolean_expression()
)+ ")"
)
}
void from_unit() : {}
{
( ii_obj_spec()
( [LOOKAHEAD({(getToken(1).kind == AS || getToken(1).kind == ID)
&& !(getToken(1).image.equalsIgnoreCase("inner")
|| getToken(1).image.equalsIgnoreCase("left")
|| getToken(1).image.equalsIgnoreCase("right"))
})
optional_as() idplus() ]
forceoptions() shared()
)
| "(" select() ")" optional_as() derived_table_name() optional_derived_col_name_list() shared()
)
}
void derived_table_name() : {}
{
[LOOKAHEAD({!(getToken(1).image.equalsIgnoreCase("inner") || getToken(1).image.equalsIgnoreCase("left") || getToken(1).image.equalsIgnoreCase("right"))}) idplus()]
}
void optional_derived_col_name_list() : {}
{
[LOOKAHEAD(2) "(" derived_column_list() ")"]
}
void derived_column_list() : {}
{
derived_col_name() ("," derived_col_name() )*
}
void derived_col_name() : {}
{
idplus()
}
void where_clause() : {setScope("from_clause", SCOPE_COLUMNS);}
{
<WHERE> boolean_expression()
{setScope("where_clause", SCOPE_DEFAULT);}
}
void boolean_expression() : {}
{
boolean_term() ( <OR> boolean_term() )*
}
void boolean_term() : {}
{
boolean_factor() ( <AND> boolean_factor() )*
}
void boolean_factor() : {}
{
boolean_primary()
| <NOT> boolean_primary()
}
void boolean_primary() : {}
{
boolean_function()
| LOOKAHEAD ("(" boolean_expression() ")" ) "(" boolean_expression() ")"
| predicate()
}
void group_by_clause() : {}
{
[ <GROUP> <BY> by_all() group_by_list() ]
}
void by_all() : {}
{
[ UK_ALL() ]
}
void group_by_list() : {}
{
group_by_item()
( "," group_by_item() )*
}
void group_by_item() : {}
{
{setScope("group_clause", SCOPE_COLUMNS);}
expression()
{setScope("group_clause", SCOPE_DEFAULT);}
}
void having_clause() : {}
{
[ <HAVING> {setScope("having_clause", SCOPE_COLUMNS);} boolean_expression() {setScope("having_clause", SCOPE_DEFAULT);}]
}
void order_by_clause() : {}
{
[ <ORDER> <BY> order_by_list() ]
}
void order_by_list() : {}
{
order_by_item()
( "," order_by_item() )*
}
void order_by_item() : {setScope("order_by_clause", SCOPE_COLUMNS);}
{
expression() [ order_by_option() ]{setScope("order_by_clause", SCOPE_DEFAULT);}
}
void order_by_option() : {}
{
<ASC>
| <DESC>
}
void predicate() : {}
{
LOOKAHEAD(<EXISTS>) exists_predicate() //starts with exists
| LOOKAHEAD( ("(")+ <SELECT> | expression() ) (expression()
(
LOOKAHEAD( comp_op() <ANY> ) any_predicate()
| LOOKAHEAD( comp_op() UK_ALL() ) all_predicate()
| LOOKAHEAD( comp_op() | join_op() ) comparison_predicate()
| LOOKAHEAD( [ <NOT> ] <BETWEEN> ) between_predicate()
| LOOKAHEAD( <IS> [ <NOT> ] ) null_predicate()
| LOOKAHEAD([ <NOT> ] <IN> ) in_predicate()
| LOOKAHEAD([ <NOT> ] <LIKE> ) like_predicate()
)
)
| LOOKAHEAD( row_constructor()) row_constructor() row_comparison_predicate()
}
void predicate_op() : {}
{
<EXISTS>
| LOOKAHEAD( expression() (comp_op() | join_op() | [ <NOT> ] ( <BETWEEN> | <IN> | <LIKE> ) | <IS> )) expression() (comp_op() | join_op() | [ <NOT> ] ( <BETWEEN> | <IN> | <LIKE> ) | <IS> )
| row_constructor() ( comp_op() | join_op() )
}
void comparison_predicate() : {}
{
( comp_op() | join_op() ) expression()
}
void row_comparison_predicate() : {}
{
comp_op() row_constructor()
}
void comp_op() : {}
{
"="
| "!" [ ">" | "=" | "<" ]
| "!>" | "!=" | "!<"
| ">" [ "=" ]
| ">="
| "<" [ ">" | "=" ]
| "<>" | "<="
}
void join_op() : {}
{
<LEQJOIN>
| <REQJOIN>
}
void between_predicate() : {}
{
[ <NOT> ] <BETWEEN> expression() <AND> expression()
}
void null_predicate() : {}
{
<IS> [ <NOT> ] null_stmt()
}
void in_predicate() : {}
{
[ <NOT> ] <IN> "(" ( in_value_list() | <SELECT> subq_select() ) ")"
}
void in_value_list() : {}
{
expression()
( "," expression() )*
}
void any_predicate() : {}
{
comp_op() <ANY> subquery()
}
void all_predicate() : {}
{
comp_op() UK_ALL() subquery()
}
void exists_predicate() : {}
{
<EXISTS> subquery()
}
void like_predicate() : {}
{
[ <NOT> ] <LIKE> pattern_clause()
}
void pattern_clause() : {}
{
expression() escape_clause()
}
void escape_clause() : {}
{
[ <ESCAPE> expression()]
}
void row_constructor() : {}
{
"(" row_constructor_list() ")"
}
void row_constructor_list() : {}
{
row_constructor_elem()
( "," row_constructor_elem() )*
}
void row_constructor_elem() : {}
{
expression()
}
ASTExpression expression() #Expression: {}
{
term()
(LOOKAHEAD(3)
( LOOKAHEAD(3) "|" "|"
| LOOKAHEAD(2) "+"
| LOOKAHEAD(2) "-"
| LOOKAHEAD(2) "&"
| LOOKAHEAD(2) "|"
| LOOKAHEAD(2) "^"
) term()
)*
{
return jjtThis;
}
}
void term() : {}
{
factor()
( "*" factor()
| "/" factor()
| "%" factor()
)*
}
void factor() : {}
{
[ "~" ] subfactor()
}
void subfactor() : {}
{
[ "+" | "-" ] primary()
}
void primary_1() : {}
{
LOOKAHEAD(constant()) constant()
| LOOKAHEAD("(" <SELECT>) subquery()
| LOOKAHEAD(function()) function()
| LOOKAHEAD(column()) column()
| case_expression()
| "(" expression() ")"
}
//supports javaname>>javaref
void primary() : {}
{
primary_1() ( LOOKAHEAD(2) ( <DOT> | <JAVA_REF> ) id_or_string() [ LOOKAHEAD(2) "(" expression_list() ")" ] )*
}
void case_expression() : {}
{
case_abbreviation()
| case_specification()
}
void case_abbreviation() : {}
{
nullif_format()
| coalesce_format()
}
void case_specification() : {}
{
<CASE> simple_or_searched_case()
}
void simple_or_searched_case() : {}
{
simple_case()
| searched_case()
}
void simple_case() : {}
{
expression() simple_when_clause_list() optional_else_clause() <END>
}
void searched_case() : {}
{
searched_when_clause_list() optional_else_clause() <END>
}
void simple_when_clause_list() : {}
{
simple_when_clause()
( simple_when_clause() )*
}
void simple_when_clause() : {}
{
<WHEN> expression() UK_THEN() result()
}
void searched_when_clause_list() : {}
{
searched_when_clause()
( searched_when_clause() )*
}
void searched_when_clause() : {}
{
<WHEN> boolean_expression() UK_THEN() result()
}
void optional_else_clause() : {}
{
[ <ELSE> result()]
}
void result() : {}
{
expression()
}
void coalesce_format() : {}
{
<COALESCE> "(" coalesce_list() ")"
}
void coalesce_list() : {}
{
coalesce_element()
( "," coalesce_element() )*
}
void coalesce_element() : {}
{
expression()
}
void nullif_format() : {}
{
<NULLIF> "(" expression() "," expression() ")"
}
void column() : {}
{
LOOKAHEAD(ii_col_spec()) ii_col_spec()
| LOOKAHEAD (idplus()) idplus()
}
Token id() : {Token t = null;}
{
(t = idplus()
| t = variable()
)
{return t;}
}
void string() : {}
{
string_literal()
| variable()
}
void id_string() : {}
{
idplus()
| <DOUBLE_STRING_LITERAL>
| variable()
}
void integer() : {}
{
<INTEGER_LITERAL>
| variable()
}
int number() : {int retval = 0;}
{
( "-" <INTEGER_LITERAL> {try {retval = Integer.parseInt("-" + getToken(0).image);}catch(Exception e){}}
| [ "+" ] <INTEGER_LITERAL> {try {retval = Integer.parseInt(getToken(0).image);}catch(Exception e){}}
)
{return retval;}
}
void constant() : {}
{
signed_const()
| unsigned_const()
}
Token signed_const() : {Token t;}
{
( t = <INTEGER_LITERAL>
| t = <FLOATING_POINT_LITERAL>
| t = <MONEY_LITERAL>
)
{return t;}
}
Token unsigned_const() : {Token t;}
{
( t = <BINARY_LITERAL>
| t = string_literal()
| t = null_stmt()
| t = variable()
)
{return t;}
}
String literal() : {Token t; boolean negative = false;}
{
( [ "+" | "-" { negative = true;} ] t = signed_const()
| t = unsigned_const()
| t = idplus()
| t = <PRIMARY>
| t = <FOREIGN>
)
{return negative?"-"+t.image:t.image;}
}
void binary() : {}
{
UK_BINARY()
| variable()
}
Token null_stmt() : {Token t;}
{
t = <NULL>
{return t;}
}
//variable reference
Token variable() : {Token t;}
{
( t = <VAR_NAME>
| t = dyn_question_mark()
| t = <GLOBAL_VAR_NAME>
)
{return t;}
}
Token variable_assignment() : {Token t;}
{
( t = <VAR_NAME>
)
{return t;}
}
Token dyn_question_mark() : {Token t;}
{
t = <QUESTIONMARK>
{return t;}
}
//include field reference and method reference
void java_memberref() : {}
{
primary_1() ( LOOKAHEAD(3) ( <DOT> | <JAVA_REF> ) id_or_string() [ "(" expression_list() ")" ] )*
}
void function() : {}
{
LOOKAHEAD(2) builtin_function()
| LOOKAHEAD(2) agg_function()
}
void builtin_function() : {}
{
<USER>
| ii_obj_spec() "(" expression_list() optional_using_clause() ")"
}
void subq_expression_list() : {}
{
subq_expression()
( "," subq_expression() )*
}
void subq_expression() : {}
{
LOOKAHEAD(2) idplus() "=" [ expression() ]
| LOOKAHEAD(2) expression() [ optional_as() ( idplus() | string_literal() ) ]
| LOOKAHEAD(2) string_literal() "=" expression()
}
void expression_list() : {}
{
[LOOKAHEAD(2) expression()
( LOOKAHEAD(2) "," expression() )* ]
}
void optional_using_clause() : {}
{
[ "," [ <USING> <ID>]
| <AS> datatype()
]
}
void optional_comma_argument() : {}
{
[ "," expression()]
}
void agg_function() : {}
{
agg_function_specification()
}
void agg_function_specification() : {}
{
<COUNT> "(" ( "*" | ( <DISTINCT> | all() ) expression() ) ")"
| <AVG> "(" ( ( <DISTINCT> | all() ) expression() ) ")"
| <MAX> "(" ( ( <DISTINCT> | all() ) expression() ) ")"
| <MIN> "(" ( ( <DISTINCT> | all() ) expression() ) ")"
| <SUM> "(" ( ( <DISTINCT> | all() ) expression() ) ")"
}
void all() : {}
{
[ UK_ALL() ]
}
void boolean_function() : {}
{
<UPDATE> "(" idplus() ")"
}
/****************************************************************************
** GENERIC RULES @RH@
**
** These rules are "generic" in that they are referenced by several
** productions from different statements, but serve a common purpose.
** They include:
**
** nonkeyword same as NAME; used to distinguish non-keywords in the grammar
** name_or_sconst Use for any constant; not valid for identifiers
** generic_ident any user-defined object
** internal_ident same as generic_ident, but may also include SCONST
** sconst_ident same is internal_ident, but doesn't check length of SCONST,
** used in WITH-clauses where need more context to verify length limits.
** auth_ident same as internal_ident; used to distinguish authorization identifiers
** user_ident same as auth_ident, but may also include $dba or $ingres
** schema_spec same as user_ident; used to distinguish schema identifiers
** obj_spec generic object specification
** tbl_spec same as generic_ident; used to distinguish table names
** col_spec same as generic_ident; used to distinguish column names
*****************************************************************************/
Token ii_generic_ident(): {Token t;}
{
(t = <DELIM_IDENT>)
// (t = string_literal())
|(t = <ID>)
{return t;}
}
void ii_sconst_ident(): {}
{
ii_generic_ident()
// | string_literal()
}
void ii_internal_ident(): {}
{
ii_generic_ident()
// | string_literal()
}
void ii_auth_ident(): {}
{
LOOKAHEAD(2) ii_internal_ident()
// | string_literal()
}
void ii_user_ident(): {}
{
ii_internal_ident()
|<II_DBA>
|<II_INGRES>
}
void ii_schema_spec(): {}
{
ii_user_ident()
}
void ii_tbl_spec(): {}
{
ii_generic_ident()
}
void ii_col_spec(): {}
{
ii_generic_ident()
}
void ii_obj_spec(): {}
{
LOOKAHEAD(2) ii_schema_spec() <DOT> ii_generic_ident()
| LOOKAHEAD(<SESSION>) <SESSION> <DOT> ii_generic_ident()
| ii_generic_ident()
}
JAVACODE
/**
* Skips the subsequent tokens when parsing error occurrs.
* The process will continue until the current consumed token matches <code>tokinds</code>
* or the next token to be consumed matches <code>beforekinds</code>.
*/
void error_skiptobefore(int[] tokinds, int[] beforekinds) {
boolean match = false;
Token t1 = getToken(0);
// The following loop consumes tokens all the way up to a token of
// "kind". We use a do-while loop rather than a while because the
// current token is the one immediately before the erroneous token
// (in our case the token immediately before what should have been
// "if"/"while".
do {
match = token.kind == 0 || getToken(1).kind == 0 ; // 0 means the <EOF>
if (match) {break;}
for (int i=0; i< tokinds.length; i++){
match = match || token.kind == tokinds[i];
if (match) {break;}
}
if (match) {break;}
for (int i=0; i< beforekinds.length; i++){
match = match || getToken(1).kind == beforekinds[i];
if (match) {break;}
}
if (!match){
logDebug("current token:" + token.image);
getNextToken() ;
}
} while (!match);
Token t2 = getToken(0);
if (t1 == t2 ){
//force get next token
logDebug("current token:" + token.image);
getNextToken() ;
}
}