/* ......................................................... -*- java -*- * FILE: SqlScript.jjt (derived from FormsPlSql.jj) * * * * DESCRIPTION: This file contains the entire grammar for PLSQL inside * * Oracle*Forms 4.5(i.e. PlSql 1.x) * * * * HISTORY: 07-APR-1997 Created Ramanathan .S (sramji@rocketmail.com) * * * * NOTE: Read the file FormsPlSql.readme for more info * * * * MODIFIED: 11-JAN-2003 Guido Draheim * * expanding the grammar to understand proper SQL scripts * * including a bunch of scripts made in the postgres flavour * * and washing it up to create a nice JJTree representation * * ................................................................... */ options{ IGNORE_CASE=true ; // DEBUG_LOOKAHEAD= true ; } PARSER_BEGIN(SqlScript) import java.io.* ; class SqlScript { public static void main( String args[] ) throws ParseException { SqlScript p = null ; if ( args.length < 1 ) { System.out.println("Reading from stdin") ; p = new SqlScript(System.in) ; } else { try { p = new SqlScript(new DataInputStream( new FileInputStream(args[0]))) ; } catch (FileNotFoundException e) { System.out.println("File " + args[0] + " not found. Reading from stdin") ; p = new SqlScript(System.in) ; } } // else ends here if ( args.length > 0 ) { System.out.println(args[0]) ; } SimpleNode t = p.SQLScript() ; System.out.println("Parse Successfull") ; t.dump(">"); } // main ends here } // class SqlScript ends here class SqlValue extends SimpleNode { String value; public SqlValue(String _value) { super(0); value = _value; } public String toString() { return ":"+value; } } PARSER_END(SqlScript) SKIP: { " " | "\t" | "\r" | "\n" } /* Prefix Meaning ------------------- K_ Keyword O_ Operator S_ Substitutes */ TOKEN: /* SQL and PLSQL Keywords. prefixed with K_ to avoid name clashes */ { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } TOKEN : /* Numeric Constants */ { < S_NUMBER: | ( ["e","E"] ([ "-","+"])? )? > | < #FLOAT: | ( "." )? | "." > | < #INTEGER: ( )+ > | < #DIGIT: ["0" - "9"] > } SPECIAL_TOKEN: { | } TOKEN: { < S_IDENTIFIER: ( )+ ( | |)* > | < #LETTER: ["a"-"z", "A"-"Z"] > | < #SPECIAL_CHARS: "$" | "_"> | < S_BIND: ":" ("." )? > | < S_CHAR_LITERAL: "'" (~["'"])* "'" ("'" (~["'"])* "'")*> | < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])* "\"" > } void S_Identifier() : { Token t; } { t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); } } void S_Quoted_Identifier() : { Token t; } { t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); } } void S_Char_Literal() : { Token t; } { t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); } } SimpleNode SQLScript(): {} { (SQLScriptStatements())+ { return jjtThis; } } void SQLScriptStatements() #void : {} { SQLStatement() | FunctionDeclaration() } /* Represents a PLSQL code block. */ void CompilationUnit(): {} { ProcedureDeclaration() | FunctionDeclaration() | SequenceOfStatements() } void DeclarationSection(): {} { "DECLARE" Declarations() } void Declarations(): {} { (( IdentifierDeclaration() // Variable or Constant Declaration | CursorDeclaration() | PragmaDeclaration() ) ";" )+ ( ProcedureDeclaration() | FunctionDeclaration() )* } void IdentifierDeclaration(): {} { RelObjectName() ( ConstantDeclaration() | VariableDeclaration() | ExceptionDeclaration() ) } void CursorDeclaration(): {} { "CURSOR" RelObjectName() ["(" ParameterList() ")" ] "IS" SelectStatement() } void ProcedureDeclaration(): {} { "PROCEDURE" RelObjectName() [ "(" ParameterList() ")" ] ( ";" // Procedure Specification | "IS" ProcedureBody() ) } void ProcedureBody(): {} { [ Declarations() ] BeginEndBlock() } void FunctionDeclaration(): {} { "FUNCTION" RelObjectName() [ "(" ParameterList() ")" ] "RETURN" TypeDeclaration() ( ";" // FunctionSpecification | "IS" FunctionBody() ) } void FunctionBody() #void : {} { [ Declarations() ] BeginEndBlock() } void PragmaDeclaration(): {} { "PRAGMA" "EXCEPTION_INIT" "(" NumOrID() "," NumOrID() ")" } void VariableDeclaration(): {} { TypeDeclaration() [ "NOT" "NULL" ] [ (":=" | "DEFAULT" ) PlSqlExpression() ] } void ConstantDeclaration(): {} { "CONSTANT" TypeDeclaration() [ "NOT" "NULL" ] (":=" | "DEFAULT" ) PlSqlExpression() } void TypeDeclaration(): {} { BasicDataTypeDeclaration() | LOOKAHEAD(2) (RelObjectName() ("%TYPE" | "%ROWTYPE")) | LOOKAHEAD(TableColumn() "%TYPE")TableColumn()"%TYPE" | RelObjectName() // For Alert declarations etc, in Forms } void BasicDataTypeDeclaration(): {} { ( "CHAR" | "VARCHAR" | "VARCHAR2" | "INTEGER" | "NUMBER" | "NATURAL" | "REAL" | "FLOAT" ) [ "(" [ "," ] ")" ] | "DATE" | "BINARY_INTEGER" | "BOOLEAN" } void ExceptionDeclaration(): {} { "EXCEPTION" } /* ---------------- DECLARATIONS SECTION ends here ------------------ */ /* ---------------- Code Section starts here ---------------------- */ void BeginEndBlock(): {} { "BEGIN" SequenceOfStatements() [ ExceptionBlock()] "END" [RelObjectName()] ";" } void SequenceOfStatements(): {} { (PLSQLStatement())+ } void ExceptionBlock(): {} { "EXCEPTION" (ExceptionHandler())+ } void ExceptionHandler(): {} { "WHEN" ( RelObjectName() ("OR" RelObjectName())* | "OTHERS" ) "THEN" SequenceOfStatements() } void PLSQLStatement(): {} { LOOKAHEAD(SubroutineCall()) SubroutineCall() | AssignmentStatement() | ExitStatement() | GotoStatement() | IfStatement() | LoopStatement() | NullStatement() | RaiseStatement() | ReturnStatement() | SQLStatement() | LabelDeclaration() | [DeclarationSection()] BeginEndBlock() } void LabelDeclaration(): {} { "<<" RelObjectName() ">>" } void SQLStatement() #void : {} { CloseStatement() | CommitStatement() | DeleteStatement() | FetchStatement() | InsertStatement() | LockTableStatement() | OpenStatement() | RollbackStatement() | SavepointStatement() | QueryStatement() | SetStatement() | UpdateStatement() } void SubroutineCall(): {} { RelObjectName() ["." DotObjectName()] [ "(" Arguments() ")" ] ";" } void AssignmentStatement(): {} { // = and . = ( (RelObjectName() ["." DotObjectName()] ":=" PlSqlExpression()) | ( ":=" PlSqlExpression()) ) ";" } void ExitStatement(): {} { "EXIT" [ RelObjectName()] ["WHEN" PlSqlExpression()] ";" } void GotoStatement(): {} { "GOTO" RelObjectName() ";" } void IfStatement(): {} { "IF" PlSqlExpression() "THEN" SequenceOfStatements() ("ELSIF" PlSqlExpression() "THEN" SequenceOfStatements() )* ["ELSE" SequenceOfStatements() ] "END" "IF" [RelObjectName()] ";" } void LoopStatement(): {} { NormalLoop() | WhileLoop() | ForLoop() } void NormalLoop(): {} { "LOOP" SequenceOfStatements() "END" "LOOP" [RelObjectName()] ";" } void WhileLoop(): {} { "WHILE" PlSqlExpression() NormalLoop() } void ForLoop(): {} { LOOKAHEAD(NumericForLoopLookahead()) NumericForLoop() | CursorForLoop() } void NumericForLoopLookahead(): {} { "FOR" RelObjectName() "IN" ["REVERSE"] PlSqlSimpleExpression() ".." } void NumericForLoop(): {} { "FOR" RelObjectName() "IN" ["REVERSE"] PlSqlSimpleExpression() ".." PlSqlSimpleExpression() NormalLoop() } void CursorForLoop(): {} { "FOR" RelObjectName() "IN" ( RelObjectName() [ "(" Arguments() ")"] | "(" SelectStatement() ")" ) NormalLoop() } void NullStatement(): {} { "NULL" ";" } void RaiseStatement(): {} { "RAISE" [RelObjectName()] ";" } void ReturnStatement(): {} { "RETURN" [ PlSqlExpression() ] ";" } void CloseStatement(): {} { "CLOSE" RelObjectName() ";" } void CommitStatement(): {} { "COMMIT" ["WORK"] ["COMMENT" S_Char_Literal()] ";" } void FetchStatement(): {} { "FETCH" (RelObjectName()) "INTO" (RelObjectName() | ) ("," (RelObjectName() | ))* ";" } void LockTableStatement(): {} { "LOCK" "TABLE" TableReference() ("," TableReference())* "IN" LockMode() "MODE" ["NOWAIT"] ";" } void OpenStatement(): {} { "OPEN" RelObjectName() ["(" Arguments() ")"] ";" } void RollbackStatement(): {} { "ROLLBACK" ["WORK"] ["TO" ["SAVEPOINT"] RelObjectName()] ["COMMENT" S_Char_Literal()] ";" } void SetTransactionStatement(): {} { "SET" "TRANSACTION" (("READ" ("ONLY" | "WRITE")) |("USE" "ROLLBACK" "SEGMENT" RelObjectName()) ) ";" } void SetVariableStatement(): {} { "SET" RelObjectName() "TO" Arguments() ";" } void SetStatement() #void : {} { LOOKAHEAD(SetTransactionStatement()) SetTransactionStatement() | SetVariableStatement() } void LockMode(): {} { ("ROW" ("SHARE" | "EXCLUSIVE")) | ("SHARE" ["UPDATE" | ("ROW" "EXCLUSIVE")]) | ("EXCLUSIVE") } void SavepointStatement(): {} { "SAVEPOINT" RelObjectName() ";" } void UpdateStatement(): {} { "UPDATE" TableReference() [RelObjectName()] "SET" ColumnValues() [ "WHERE" ( SQLExpression() | "CURRENT" "OF" RelObjectName())] ";" } void ColumnValues(): {} { TableColumn() "=" UpdatedValue() ("," TableColumn() "=" UpdatedValue())* } void UpdatedValue(): // Can be a subquery or a expression {} { LOOKAHEAD(("(")+ "SELECT") "(" SelectStatement() ")" | PlSqlExpression() } void InsertStatement(): {} { "INSERT" "INTO" TableReference() [ "(" TableColumn() ("," TableColumn())* ")" ] ( "VALUES" "(" PlSqlExpressionList() ")" | SelectStatement() ) ";" } void DeleteStatement(): {} { "DELETE" ["FROM"] TableReference() [RelObjectName()] ["WHERE" (SQLExpression() | "CURRENT" "OF" RelObjectName() ) ] ";" } void QueryStatement(): {} { SelectStatement() ";" } // PLSQL Expression and it's childs void PlSqlExpression(): {} { PlSqlExpressions() } void PlSqlExpressions() #void : {} { LOOKAHEAD(PlSqlOrExpression()) PlSqlOrExpression() | PlSqlAndExpressions() } void PlSqlOrExpression(): {} { PlSqlAndExpressions() ("OR" PlSqlAndExpressions())+ } void PlSqlAndExpressions() #void : {} { LOOKAHEAD(PlSqlAndExpression()) PlSqlAndExpression() | PlSqlUnaryLogicalExpressions() } void PlSqlAndExpression(): {} { PlSqlUnaryLogicalExpressions() ( "AND" PlSqlUnaryLogicalExpressions())+ } void PlSqlUnaryLogicalExpressions() #void : {} { LOOKAHEAD(PlSqlUnaryLogicalExpression()) PlSqlUnaryLogicalExpression() | PlSqlRelationalExpressions() } void PlSqlUnaryLogicalExpression(): {} { "NOT" PlSqlRelationalExpressions() } void PlSqlRelationalExpressions() #void : {} { LOOKAHEAD(PlSqlRelationalExpression()) PlSqlRelationalExpression() | PlSqlSimpleExpressions() } void PlSqlRelationalExpression(): {} { PlSqlSimpleExpressions() ( Relop() PlSqlSimpleExpressions() | LOOKAHEAD(2) PlSqlInClause() | LOOKAHEAD(2) PlSqlBetweenClause() | LOOKAHEAD(2) PlSqlLikeClause() | IsNullClause() ) } void PlSqlExpressionList(): {} { PlSqlExpression() ("," PlSqlExpression())* } void PlSqlInClause(): {} { ["NOT"] "IN" "(" PlSqlExpressionList()")" } void PlSqlBetweenClause(): {} { ["NOT"] "BETWEEN" PlSqlSimpleExpressions() "AND" PlSqlSimpleExpressions() } void PlSqlLikeClause(): {} { ["NOT"] "LIKE" PlSqlSimpleExpressions() } void IsNullClause(): {} { "IS" ["NOT"] "NULL" } void PlSqlSimpleExpression(): {} { PlSqlSimpleExpressions() } void PlSqlSimpleExpressions() #void : {} { LOOKAHEAD(PlSqlAdditiveExpression()) PlSqlAdditiveExpression() | PlSqlMultiplicativeExpressions() } void PlSqlAdditiveExpression(): {} { PlSqlMultiplicativeExpressions() ( ("+" | "-" | "||") PlSqlMultiplicativeExpressions() )+ } void PlSqlMultiplicativeExpressions() #void : {} { LOOKAHEAD(PlSqlMultiplicativeExpression()) PlSqlMultiplicativeExpression() | PlSqlExpotentExpressions() } void PlSqlMultiplicativeExpression(): {} { PlSqlExpotentExpressions() ( ("*" | "/") PlSqlExpotentExpressions())+ } void PlSqlExpotentExpressions() #void : {} { LOOKAHEAD(PlSqlExpotentExpression()) PlSqlExpotentExpression() | PlSqlUnaryExpressions() } void PlSqlExpotentExpression(): {} { PlSqlUnaryExpressions() ( "**" PlSqlUnaryExpressions())+ } void PlSqlUnaryExpressions() #void : {} { LOOKAHEAD(PlSqlUnaryExpression()) PlSqlUnaryExpression() | PlSqlPrimaryExpression() } void PlSqlUnaryExpression(): {} { (("+" | "-") PlSqlPrimaryExpression()) } void PlSqlPrimaryExpression(): {} { "NULL" | LOOKAHEAD(2) (RelObjectName() ("%FOUND" | "%NOTFOUND" | "%ISOPEN" | "%ROWCOUNT")) | LOOKAHEAD(2) (RelObjectName() "(" Arguments() ")" ) | (RelObjectName() ["." DotObjectName()]) // cursor.var | ("SQL" ("%FOUND" | "%NOTFOUND" | "%ISOPEN" | "%ROWCOUNT")) | | | "(" PlSqlExpression() ")" } /* ----------------------- PLSQL Code Block Ends here -------------- */ /* ---------------- General Productions --------------------- */ void TableColumn(): {} { // user.table.column RelObjectName() [ "." DotObjectName() ["." DotObjectName()]] } void RelObjectName() #ObjectName : { Token t; } { t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue } void DotObjectName() #ObjectName : // only put after "." match { Token t; } // here we list some char-sequences that { // would be returned as a special token t= // but they are not special here { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue | t= { jjtThis.jjtAddChild(new SqlValue(t.image), 0); }//SqlValue } void OracleObjectName(): // usually unused now - see above {} { | } void Relop(): {} { "=" | "!=" | "#" | "<>" | ">" | ">=" | "<" | "<=" } void TableReference(): {} { RelObjectName() ["." DotObjectName()] } void ParameterList(): {} { Parameter() ( "," Parameter() )* } void NumOrID(): {} { | (["+" | "-"] ) } void Parameter(): {} { RelObjectName() [ ["IN"] ["OUT"] TypeDeclaration() [(":=" | "DEFAULT" ) PlSqlExpression()] ] } // Just a synonym for PlSqlExpressionList for better readability void Arguments(): {} { PlSqlExpressionList() } /* --------------- General Productions ends here --------------- */ /* ----------- SQL productions start here ----------------- */ void SelectStatement(): {} { SelectWithoutOrder() [ OrderByClause() ] [ ForUpdateClause() ] } void SelectWithoutOrder(): {} { "SELECT" [ "ALL" | "DISTINCT" ] SelectList() [IntoClause()] FromClause() [ WhereClause() ] [ ConnectClause() ] [ GroupByClause() ] [ SetClause() ] } /* Checks for whatever follows SELECT */ void SelectList(): {} { "*" | SelectItem() ("," SelectItem())* } void SelectItem(): {} { // LOOKAHEAD(SelectAllItems()) SelectAllItems() //| SQLSimpleExpression() // Column or Expression // [] // Column Alias LOOKAHEAD(FunctionCall()) FunctionCall() [AsObjectName()] | LOOKAHEAD(SelectAllItems()) SelectAllItems() | LOOKAHEAD(TableColumn()) TableColumn() [AsObjectName()] | "" [AsObjectName()] } void SelectAllItems(): {} { /* table.* OR schema.table.* */ LOOKAHEAD(2) RelObjectName() "." "*" | RelObjectName() "." DotObjectName() "." "*" } void AsObjectName(): {} { RelObjectName() | "AS" DotObjectName() } void IntoClause(): {} { "INTO" IntoItem() ("," IntoItem())* } void IntoItem(): {} { (RelObjectName() ["." DotObjectName()] ) | () } void FromClause(): {} { "FROM" FromItem() ( "," FromItem())* } void FromItem(): {} { // TableReference() // [ ] /** Alias Name **/ ( TableReference() | "(" FromItemExpression() ")" ) ( LOOKAHEAD(JoinerExpression()) JoinerExpression() ["AS" AsObjectName()] | [AsObjectName()]) } void FromItemExpression(): {} { ( TableReference() | "(" FromItemExpression() ")") (JoinerExpression())* } void JoinerExpression(): {} { "JOIN" TableReference() [JoinWhereClause()] | LOOKAHEAD(2) RelObjectName() "JOIN" TableReference() [JoinWhereClause()] } void JoinWhereClause(): {} { "ON" SQLExpression() } void WhereClause(): {} { "WHERE" SQLExpression() } void ConnectClause(): {} { // The following grammar will take 2 "START WITH" expressions // which is not correct. But alright, because only valid statements // will be given. (["START" "WITH" SQLExpression()] "CONNECT" "BY" SQLExpression() ["START" "WITH" SQLExpression()]) } void GroupByClause(): {} { "GROUP" "BY" SQLExpressionList() ["HAVING" SQLExpression()] } void SetClause(): {} { (("UNION" ["ALL"]) | "INTERSECT" | "MINUS") // LOOKAHEAD("(") because Oracle supports "(" after a UNION (LOOKAHEAD("(") ("(" SelectWithoutOrder() ")") | SelectWithoutOrder() ) } void OrderByClause(): {} { "ORDER" "BY" SQLSimpleExpression() ["ASC" | "DESC" ] ("," SQLSimpleExpression() ["ASC" | "DESC"])* } void ForUpdateClause(): {} { "FOR" "UPDATE" "OF" TableColumn() ("," TableColumn())* } void SQLExpression(): {} { SQLOrExpressions() } void SQLOrExpressions() #void : {} { LOOKAHEAD(SQLOrExpression()) SQLOrExpression() | SQLAndExpressions() } void SQLOrExpression(): {} { SQLAndExpressions() ("OR" SQLAndExpressions())+ } void SQLAndExpressions() #void : {} { LOOKAHEAD(SQLAndExpression()) SQLAndExpression() | SQLUnaryLogicalExpressions() } void SQLAndExpression(): {} { SQLUnaryLogicalExpressions() ( "AND" SQLUnaryLogicalExpressions())+ } void SQLUnaryLogicalExpressions() #void : {} { LOOKAHEAD(2) ExistsClause() | SQLRelationalExpressions() } void ExistsClause(): {} { ["NOT"] "EXISTS" "(" SubQuery() ")" } void SQLRelationalExpressions() # void : {} { LOOKAHEAD(SQLRelationalExpression()) SQLRelationalExpression() | /* Only after looking past "(", Expression() and "," we will know that it is expression list */ (LOOKAHEAD(SQLRelopExpression()) SQLRelopExpression() | LOOKAHEAD("(" SQLSimpleExpression() ",") "(" SQLExpressionList() ")" | (LOOKAHEAD(2) SQLPriorExpression() | SQLSimpleExpressions()) ) } void SQLRelationalExpression() : {} { /* Only after looking past "(", Expression() and "," we will know that it is expression list */ ( LOOKAHEAD("(" SQLSimpleExpression() ",") "(" SQLExpressionList() ")" | (LOOKAHEAD(2) SQLPriorExpression() | SQLSimpleExpressions()) ) /* Lookahead(2) is required because of NOT IN,NOT BETWEEN and NOT LIKE */ //( SQLRelationalOperatorExpression() ( LOOKAHEAD(2) (SQLInClause()) | LOOKAHEAD(2) (SQLBetweenClause()) | LOOKAHEAD(2) (SQLLikeClause()) | IsNullClause() ) } void SQLPriorExpression(): {} { ["NOT"] "PRIOR" SQLSimpleExpressions() } void SQLExpressionList(): {} { SQLSimpleExpression() ("," SQLSimpleExpression())* } void SQLRelopExpression(): {} { ( LOOKAHEAD("(" SQLSimpleExpression() ",") "(" SQLExpressionList() ")" | (LOOKAHEAD(2) SQLPriorExpression() | SQLSimpleExpressions()) ) Relop() /* Only after seeing an ANY/ALL or "(" followed by a SubQuery() we can determine that is is a sub-query */ ( LOOKAHEAD("ANY" | "ALL" | "(" "SELECT") (["ALL" | "ANY"] "(" SubQuery() ")") | LOOKAHEAD(2) SQLPriorExpression() | SQLSimpleExpressions() ) } void SQLRelationalOperatorExpression(): {} { Relop() /* Only after seeing an ANY/ALL or "(" followed by a SubQuery() we can determine that is is a sub-query */ ( LOOKAHEAD("ANY" | "ALL" | "(" "SELECT") (["ALL" | "ANY"] "(" SubQuery() ")") | LOOKAHEAD(2) SQLPriorExpression() | SQLSimpleExpression() ) } void SQLInClause(): {} { ["NOT"] "IN" "(" (SQLExpressionList() | SubQuery()) ")" } void SQLBetweenClause(): {} { ["NOT"] "BETWEEN" SQLSimpleExpression() "AND" SQLSimpleExpression() } void SQLLikeClause(): {} { ["NOT"] "LIKE" SQLSimpleExpression() } void SQLSimpleExpression(): {} { SQLSimpleExpressions() } void SQLSimpleExpressions() #void : {} { SQLAdditiveExpressions() } void SQLAdditiveExpressions() #void : {} { LOOKAHEAD(SQLAdditiveExpression()) SQLAdditiveExpression() | SQLMultiplicativeExpressions() } void SQLAdditiveExpression(): {} { SQLMultiplicativeExpressions() ( ("+" | "-" | "||") SQLMultiplicativeExpressions())+ } void SQLMultiplicativeExpressions() #void : {} { LOOKAHEAD(SQLMultiplicativeExpression()) SQLMultiplicativeExpression() | SQLExpotentExpressions() } void SQLMultiplicativeExpression(): {} { SQLExpotentExpressions() ( ("*" | "/") SQLExpotentExpressions())+ } void SQLExpotentExpressions() #void : {} { LOOKAHEAD(SQLExpotentExpression()) SQLExpotentExpression() | SQLUnaryExpressions() } void SQLExpotentExpression(): {} { SQLUnaryExpressions() ( "**" SQLUnaryExpressions())+ } void SQLUnaryExpressions() #void : {} { LOOKAHEAD(SQLUnaryExpression()) SQLUnaryExpression() | SQLPrimaryExpression() } void SQLUnaryExpression(): {} { ("+" | "-") SQLPrimaryExpression() } void SQLPrimaryExpression(): {} { "NULL" | LOOKAHEAD(FunctionCall()) FunctionCall() | LOOKAHEAD(OuterJoinExpression()) OuterJoinExpression() | TableColumn() // | | | | "(" SQLExpression() ")" } void FunctionCall(): {} { // caters the following // function(args) // package.function(args) // user.package.function(args) // however note that "distinct/all/*" can be only used with // inbuilt functions but no distinction is made between inbuilt // function and custom functions RelObjectName() [ "." DotObjectName() ["." DotObjectName()]] "(" [ ["DISTINCT" | "ALL"] (SQLArguments() | "*") ] ")" } void SQLArguments(): {} { SQLExpressionList() } void OuterJoinExpression(): {} { // user.table.col RelObjectName() [ "." DotObjectName() ["." DotObjectName()]] "(" "+" ")" } void SubQuery(): {} { SelectWithoutOrder() }