/* ................................................................... * * FILE: 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 * * ................................................................... */ options{ IGNORE_CASE=true ; // DEBUG_LOOKAHEAD= true ; } PARSER_BEGIN(FormsPlSql) import java.io.* ; class FormsPlSql { public static void main( String args[] ) throws ParseError { FormsPlSql p = null ; if ( args.length < 1 ) { System.out.println("Reading from stdin") ; p = new FormsPlSql(System.in) ; } else { try { p = new FormsPlSql(new DataInputStream( new FileInputStream(args[0]))) ; } catch (FileNotFoundException e) { System.out.println("File " + args[0] + " not found. Reading from stdin") ; p = new FormsPlSql(System.in) ; } } // else ends here if ( args.length > 0 ) { System.out.println(args[0]) ; } p.CompilationUnit() ; System.out.println("Parse Successfull") ; } // main ends here } // class FormsPlSql ends here PARSER_END(FormsPlSql) 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","\""])* "\"" > } /* 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(): {} { ( ConstantDeclaration() | VariableDeclaration() | ExceptionDeclaration() ) } void CursorDeclaration(): {} { "CURSOR" ["(" ParameterList() ")" ] "IS" SelectStatement() } void ProcedureDeclaration(): {} { "PROCEDURE" [ "(" ParameterList() ")" ] ( ";" // Procedure Specification | "IS" ProcedureBody() ) } void ProcedureBody(): {} { [ Declarations() ] BeginEndBlock() } void FunctionDeclaration(): {} { "FUNCTION" [ "(" ParameterList() ")" ] "RETURN" TypeDeclaration() ( ";" // FunctionSpecification | "IS" FunctionBody() ) } void FunctionBody(): {} { [ 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) ( ("%TYPE" | "%ROWTYPE")) | LOOKAHEAD(TableColumn() "%TYPE")TableColumn()"%TYPE" | // 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" [] ";" } void SequenceOfStatements(): {} { (PLSQLStatement())+ } void ExceptionBlock(): {} { "EXCEPTION" (ExceptionHandler())+ } void ExceptionHandler(): {} { "WHEN" ( ("OR" )* | "OTHERS" ) "THEN" SequenceOfStatements() } void PLSQLStatement(): {} { LOOKAHEAD(SubroutineCall()) SubroutineCall() | AssignmentStatement() | ExitStatement() | GotoStatement() | IfStatement() | LoopStatement() | NullStatement() | RaiseStatement() | ReturnStatement() | SQLStatement() | LabelDeclaration() | [DeclarationSection()] BeginEndBlock() } void LabelDeclaration(): {} { "<<" ">>" } void SQLStatement(): {} { CloseStatement() | CommitStatement() | DeleteStatement() | FetchStatement() | InsertStatement() | LockTableStatement() | OpenStatement() | RollbackStatement() | SavepointStatement() | QueryStatement() | SetTransactionStatement() | UpdateStatement() } void SubroutineCall(): {} { ["."] [ "(" Arguments() ")" ] ";" } void AssignmentStatement(): {} { // = and . = ( ( ["." ] ":=" PlSqlExpression()) | ( ":=" PlSqlExpression()) ) ";" } void ExitStatement(): {} { "EXIT" [ ] ["WHEN" PlSqlExpression()] ";" } void GotoStatement(): {} { "GOTO" ";" } void IfStatement(): {} { "IF" PlSqlExpression() "THEN" SequenceOfStatements() ("ELSIF" PlSqlExpression() "THEN" SequenceOfStatements() )* ["ELSE" SequenceOfStatements() ] "END" "IF" [] ";" } void LoopStatement(): {} { NormalLoop() | WhileLoop() | ForLoop() } void NormalLoop(): {} { "LOOP" SequenceOfStatements() "END" "LOOP" [] ";" } void WhileLoop(): {} { "WHILE" PlSqlExpression() NormalLoop() } void ForLoop(): {} { LOOKAHEAD(NumericForLoopLookahead()) NumericForLoop() | CursorForLoop() } void NumericForLoopLookahead(): {} { "FOR" "IN" ["REVERSE"] PlSqlSimpleExpression() ".." } void NumericForLoop(): {} { "FOR" "IN" ["REVERSE"] PlSqlSimpleExpression() ".." PlSqlSimpleExpression() NormalLoop() } void CursorForLoop(): {} { "FOR" "IN" ( [ "(" Arguments() ")"] | "(" SelectStatement() ")" ) NormalLoop() } void NullStatement(): {} { "NULL" ";" } void RaiseStatement(): {} { "RAISE" [] ";" } void ReturnStatement(): {} { "RETURN" [ PlSqlExpression() ] ";" } void CloseStatement(): {} { "CLOSE" ";" } void CommitStatement(): {} { "COMMIT" ["WORK"] ["COMMENT" ] ";" } void FetchStatement(): {} { "FETCH" () "INTO" ( | ) ("," ( | ))* ";" } void LockTableStatement(): {} { "LOCK" "TABLE" TableReference() ("," TableReference())* "IN" LockMode() "MODE" ["NOWAIT"] ";" } void OpenStatement(): {} { "OPEN" ["(" Arguments() ")"] ";" } void RollbackStatement(): {} { "ROLLBACK" ["WORK"] ["TO" ["SAVEPOINT"] ] ["COMMENT" ] ";" } void SetTransactionStatement(): {} { "SET" "TRANSACTION" (("READ" ("ONLY" | "WRITE")) |("USE" "ROLLBACK" "SEGMENT" ) ) ";" } void LockMode(): {} { ("ROW" ("SHARE" | "EXCLUSIVE")) | ("SHARE" ["UPDATE" | ("ROW" "EXCLUSIVE")]) | ("EXCLUSIVE") } void SavepointStatement(): {} { "SAVEPOINT" ";" } void UpdateStatement(): {} { "UPDATE" TableReference() [] "SET" ColumnValues() [ "WHERE" ( SQLExpression() | "CURRENT" "OF" )] ";" } 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() [] ["WHERE" (SQLExpression() | "CURRENT" "OF" ) ] ";" } void QueryStatement(): {} { SelectStatement() ";" } // PLSQL Expression and it's childs void PlSqlExpression(): {} { PlSqlAndExpression() ("OR" PlSqlAndExpression())* } void PlSqlAndExpression(): {} { PlSqlUnaryLogicalExpression() ( "AND" PlSqlUnaryLogicalExpression())* } void PlSqlUnaryLogicalExpression(): {} { ["NOT"] PlSqlRelationalExpression() } void PlSqlRelationalExpression(): {} { PlSqlSimpleExpression() ( Relop() PlSqlSimpleExpression() | LOOKAHEAD(2) PlSqlInClause() | LOOKAHEAD(2) PlSqlBetweenClause() | LOOKAHEAD(2) PlSqlLikeClause() | IsNullClause() )? } void PlSqlExpressionList(): {} { PlSqlExpression() ("," PlSqlExpression())* } void PlSqlInClause(): {} { ["NOT"] "IN" "(" PlSqlExpressionList()")" } void PlSqlBetweenClause(): {} { ["NOT"] "BETWEEN" PlSqlSimpleExpression() "AND" PlSqlSimpleExpression() } void PlSqlLikeClause(): {} { ["NOT"] "LIKE" PlSqlSimpleExpression() } void IsNullClause(): {} { "IS" ["NOT"] "NULL" } void PlSqlSimpleExpression(): {} { PlSqlMultiplicativeExpression() ( ("+" | "-" | "||") PlSqlMultiplicativeExpression() )* } void PlSqlMultiplicativeExpression(): {} { PlSqlExpotentExpression() ( ("*" | "/") PlSqlExpotentExpression())* } void PlSqlExpotentExpression(): {} { PlSqlUnaryExpression() ( "**" PlSqlUnaryExpression())* } void PlSqlUnaryExpression(): {} { (("+" | "-") PlSqlPrimaryExpression()) | PlSqlPrimaryExpression() } void PlSqlPrimaryExpression(): {} { "NULL" | LOOKAHEAD(2) (("%FOUND" | "%NOTFOUND" | "%ISOPEN" | "%ROWCOUNT")) | LOOKAHEAD(2) ( "(" Arguments() ")" ) | ( ["." ]) // cursor.var | ("SQL" ("%FOUND" | "%NOTFOUND" | "%ISOPEN" | "%ROWCOUNT")) | | | | "(" PlSqlExpression() ")" } /* ----------------------- PLSQL Code Block Ends here -------------- */ /* ---------------- General Productions --------------------- */ void TableColumn(): {} { // user.table.column OracleObjectName() [ "." OracleObjectName() ["." OracleObjectName()]] } void OracleObjectName(): {} { | } void Relop(): {} { "=" | "!=" | "#" | "<>" | ">" | ">=" | "<" | "<=" } void TableReference(): {} { OracleObjectName() ["." OracleObjectName()] } void ParameterList(): {} { Parameter() ( "," Parameter() )* } void NumOrID(): {} { | (["+" | "-"] ) } void Parameter(): {} { [ ["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(2) OracleObjectName()".*" /* table.* */ | LOOKAHEAD(4) OracleObjectName()"." OracleObjectName() ".*" /* schema.table.* */ | SQLSimpleExpression() // Column or Expression [] // Column Alias } void IntoClause(): {} { "INTO" IntoItem() ("," IntoItem())* } void IntoItem(): {} { ( ["." ] ) | () } void FromClause(): {} { "FROM" FromItem() ( "," FromItem())* } void FromItem(): {} { TableReference() [ ] /** Alias Name **/ } 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(): {} { SQLAndExpression() ("OR" SQLAndExpression())* } void SQLAndExpression(): {} { SQLUnaryLogicalExpression() ( "AND" SQLUnaryLogicalExpression())* } void SQLUnaryLogicalExpression(): {} { LOOKAHEAD(2) ExistsClause() | (["NOT"] SQLRelationalExpression()) } void ExistsClause(): {} { ["NOT"] "EXISTS" "(" SubQuery() ")" } void SQLRelationalExpression(): {} { /* Only after looking past "(", Expression() and "," we will know that it is expression list */ (LOOKAHEAD("(" SQLSimpleExpression() ",") "(" SQLExpressionList() ")" | (["PRIOR"] SQLSimpleExpression())) /* 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 SQLExpressionList(): {} { SQLSimpleExpression() ("," SQLSimpleExpression())* } 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() ")") | ["PRIOR"] SQLSimpleExpression() ) } void SQLInClause(): {} { ["NOT"] "IN" "(" (SQLExpressionList() | SubQuery()) ")" } void SQLBetweenClause(): {} { ["NOT"] "BETWEEN" SQLSimpleExpression() "AND" SQLSimpleExpression() } void SQLLikeClause(): {} { ["NOT"] "LIKE" SQLSimpleExpression() } void SQLSimpleExpression(): {} { SQLMultiplicativeExpression() ( ("+" | "-" | "||") SQLMultiplicativeExpression())* } void SQLMultiplicativeExpression(): {} { SQLExpotentExpression() ( ("*" | "/") SQLExpotentExpression())* } void SQLExpotentExpression(): {} { SQLUnaryExpression() ( "**" SQLUnaryExpression())* } 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 OracleObjectName() [ "." OracleObjectName() ["." OracleObjectName()]] "(" [ ["DISTINCT" | "ALL"] (SQLArguments() | "*") ] ")" } void SQLArguments(): {} { SQLExpressionList() } void OuterJoinExpression(): {} { // user.table.col OracleObjectName() [ "." OracleObjectName() ["." OracleObjectName()]] "(" "+" ")" } void SubQuery(): {} { SelectWithoutOrder() }