📄 plsqlgrammar.g
字号:
| select_expression
;
select_expression:
#( "select" ( "all"! | "distinct"! )? select_list
("into" column_name)?
//"from" table_reference_list
table_reference_list_from
//( "where" where_condition )?
(where_condition_whole)?
( connect_clause )?
( group_clause )?
( ( set_clause ) => set_clause )?
( ( order_clause ) => order_clause )?
( ( update_clause ) => update_clause )? )
;
select_list:
( ( displayed_column ) => displayed_column ( COMMA displayed_column )*
| ASTERISK )
;
table_reference_list_from:
"from" selected_table ( COMMA! selected_table )*
;
table_reference_list:
selected_table ( COMMA selected_table )*
;
where_condition_whole:
"where" condition
;
where_condition:
condition
;
displayed_column :
( (schema_name DOT)? (variable)? table_name DOT ASTERISK ) => ( ( schema_name DOT )? table_name DOT ASTERISK )
| ( exp_simple ( alias )? )
;
schema_name:
identifier
;
table_name:
identifier
;
exp_simple:
expression
;
expression:
term ( ( PLUS | MINUS ) term )*
| boolean_literal
;
alias:
( "as" )? identifier
;
term:
factor ( ( multiply | DIVIDE ) factor )*
;
multiply:
ASTERISK
;
factor:
factor2 ( VERTBAR VERTBAR factor2 )*
;
factor2:
( sql_literal ) => sql_literal
| ( ( PLUS | MINUS ) expression ) => ( PLUS | MINUS ) expression
| ( function ( OPEN_PAREN! expression ( COMMA expression )* CLOSE_PAREN ) ) => function ( OPEN_PAREN expression ( COMMA expression )* CLOSE_PAREN )
| ( group_function OPEN_PAREN ( ASTERISK | "all" | "distinct" )? (expression)? CLOSE_PAREN ) => group_function OPEN_PAREN ( ASTERISK | "all" | "distinct" )? (expression)? CLOSE_PAREN
| ( user_defined_function ( OPEN_PAREN expression ( COMMA expression )* CLOSE_PAREN ) ) => user_defined_function ( OPEN_PAREN expression ( COMMA expression )* CLOSE_PAREN )
| ( OPEN_PAREN! expression CLOSE_PAREN! ) => OPEN_PAREN! expression CLOSE_PAREN!
| ( variable ) => variable
| expression_list
;
expression_list:
OPEN_PAREN! expression ( COMMA expression )+ CLOSE_PAREN!
;
sql_literal:
( NUMBER | QUOTED_STRING | "null" )
;
variable:
( column_spec ( OPEN_PAREN! PLUS CLOSE_PAREN! ) ) => column_spec ( OPEN_PAREN! PLUS CLOSE_PAREN! )
| column_spec
;
column_spec:
( ( schema_name DOT )? table_name DOT )? column_name
;
user_defined_function:
( ( schema_name DOT )? package_name DOT )? identifier
;
column_name:
identifier
;
function:
number_function
| char_function
| group_function
| conversion_function
| other_function
;
number_function:
"abs" | "ceil" | "floor" | "mod" | "power" | "round"
| "sign" | "sqrt" | "trunc"
;
char_function:
"chr" | "initcap" | "lower" | "lpad" | "ltrim" | "replace"
| "rpad" | "rtrim" | "soundex" | "substr" | "translate" | "upper"
| "ascii" | "instr" | "length"
| "concat"
;
group_function:
"avg" | "count" | "max" | "min" | "stddev" | "sum"
| "variance"
;
conversion_function:
"chartorowid" | "convert" | "hextoraw" | "rawtohex" | "rowidtochar"
| "to_char" | "to_date" | "to_number"
;
other_function
:
"decode" | "dump" | "greatest" | "least" | "nvl"
| "uid" | "userenv" | "vsize"
;
pseudo_column:
"user" | "sysdate"
;
selected_table:
( table_spec | subquery ) ( alias )?
;
table_spec:
( schema_name DOT )? table_name ( AT_SIGN link_name )?
;
table_alias:
( schema_name DOT )? table_name ( AT_SIGN link_name )? ( alias )?
;
link_name:
identifier
;
condition:
logical_term ( "or" logical_term )*
;
logical_term:
logical_factor ( "and" logical_factor )*
;
logical_factor:
( ( "prior" ) ? exp_simple relational_op ( "prior" )? exp_simple ) => ( ( "prior" ) ? exp_simple relational_op ( "prior" )? exp_simple )
| ( exp_simple ( "not" )? "in" ) => exp_simple ("not")? "in" exp_set
| ( exp_simple ( "not" )? "like" ) => exp_simple ( "not" )? "like" expression ( "escape" QUOTED_STRING )?
| ( exp_simple ( "not" )? "between" ) => exp_simple ( "not" )? "between" exp_simple "and" exp_simple
| ( exp_simple "is" ( "not" )? "null" ) => exp_simple "is" ( "not" )? "null"
| ( quantified_factor ) => quantified_factor
| ( "not" condition ) => "not" condition
| ( OPEN_PAREN! condition CLOSE_PAREN! )
;
quantified_factor:
( exp_simple relational_op ( "all" | "any" )? subquery ) => exp_simple relational_op ( "all" | "any" )? subquery
| ( ( "not" )? "exists" subquery ) => ( "not" )? "exists" subquery
| subquery
;
relational_op:
EQ | LT | GT | NOT_EQ | LE | GE
;
exp_set:
( exp_simple ) => exp_simple
| subquery
;
subquery:
OPEN_PAREN! select_command CLOSE_PAREN!
;
connect_clause:
( "start" "with" condition )? // the start can be before the connect by
"connect" "by"
( ( "prior" exp_simple relational_op exp_simple )
| ( exp_simple relational_op exp_simple "prior" ) )
( ( ( "prior" )? condition ) => ("prior")? condition
| exp_simple relational_op ( "prior" )? exp_simple ( "and" condition )?
)
condition
( "start" "with" condition )?
;
group_clause:
"group" "by" expression ( COMMA expression )* ( "having" condition )?
;
set_clause:
( ( "union" "all" ) | "intersect" | "minus" ) select_command
;
order_clause:
"order" "by" sorted_def ( COMMA sorted_def )*
;
sorted_def:
(( expression ) => expression | ( NUMBER ) => NUMBER ) ( "asc" | "desc" )?
;
update_clause:
"for" "update" ( "of" column_name ( COMMA column_name )* )? ( "nowait" )?
;
insert_command:
"insert" "into" table_reference_list
( OPEN_PAREN! column_spec CLOSE_PAREN! )?
( ( "values" OPEN_PAREN! (variable_name) (COMMA variable_name)* CLOSE_PAREN! )
| select_statement )
;
update_command:
( subquery_update ) => subquery_update
| simple_update
;
simple_update:
"update" table_alias
"set" column_spec EQ ( ( expression ) => expression | subquery )
( COMMA column_spec EQ ( ( expression ) => expression | subquery ) )*
"where" condition
;
subquery_update:
"update" table_alias
"set" OPEN_PAREN! column_spec ( COMMA column_spec )* CLOSE_PAREN! EQ subquery
"where" condition
;
set_transaction_command:
"set" "transaction" "read" "only"
;
close_statement :
"close" cursor_name
;
fetch_statement:
"fetch" cursor_name "into"
( ( variable_name (COMMA variable_name )* )
| record_name )
;
lock_table_statement:
"lock" "table" table_reference_list
"in" lock_mode "mode" ( "nowait" )?
;
lock_mode:
"row" "share"
|"row" "exclusive"
|"share" "update"
|"share"
|"share""row""exclusive"
|"exclusive"
;
open_statement:
"open" cursor_name (OPEN_PAREN! plsql_exp_list! CLOSE_PAREN!)?
;
rollback_statement:
"rollback" ( "work" )?
( "to" ( "savepoint" )? savepoint_name )?
( "comment" quoted_string )?
;
savepoint_statement:
"savepoint" savepoint_name
;
savepoint_name:
identifier
;
identifier:
( IDENTIFIER | QUOTED_STRING | keyword )
;
quoted_string : QUOTED_STRING ;
match_string : QUOTED_STRING ;
keyword
:
"abs"
| "ascii"
| "ceil"
| "chartorowid"
| "chr"
| "concat"
| "convert"
| "count"
| "decode"
| "dump"
| "floor"
| "greatest"
| "hextoraw"
| "initcap"
| "instr"
| "intersect"
| "least"
| "length"
| "lower"
| "lpad"
| "ltrim"
// | "max" // oracle
// | "min" // oracle
// | "minus" // oracle
// | "mod" // oracle
// | "not" // oracle
// | "nowait" // oracle
| "nvl"
| "power"
// | "prior" // oracle
| "rawtohex"
| "replace"
| "round"
| "rowidtochar"
| "rpad"
| "rtrim"
| "sign"
| "soundex"
| "sqrt"
// | "stddev" // oracle
| "substr"
// | "sum" // oracle
| "sysdate"
| "to_char"
| "to_date"
| "to_number"
| "translate"
| "trunc"
// | "uid" // oracle
| "upper"
| "user" // ansi
| "userenv"
// | "variance" // oracle
| "vsize"
;
//
// Lexer
//
class PLSqlLexer extends Lexer;
options {
exportVocab = PLSql;
testLiterals = false;
k = 2;
caseSensitive = false;
caseSensitiveLiterals = false;
charVocabulary = '\3' .. '\177';
}
IDENTIFIER options { testLiterals=true; }
:
'a' .. 'z' ( 'a' .. 'z' | '0' .. '9' | '_' | '$' | '#' )*
;
ANY_CHARACTER:
'a' .. 'z'
;
QUOTED_STRING
:
'\'' ( ~'\'' )* '\''
;
SEMI : ';';
COLON: ':';
DOT : '.' ;
COMMA : ',' ;
ASTERISK : '*' ;
AT_SIGN : '@' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
PLUS : '+' ;
MINUS : '-' ;
DIVIDE : '/' ;
EQ : '=' ;
PERCENTAGE : '%' ;
DOUBLEDOT: "..";
START_LABEL :
"<<"
;
END_LABEL:
">>"
;
ASSIGNMENT_EQ:
":="
;
VERTBAR : '|' ;
//LABELNAME
// :
// ( 'a' .. 'z' | '0' .. '9' ) ( IDENTIFIER | WS | PLUS | MINUS | DIVIDE | VERTBAR | EQ | SEMI | ASTERISK | '<' | '>' | OPEN_PAREN | CLOSE_PAREN | '{' | '}' | '[' | ']' | '?' | '!' | '~' | ':' | AT_SIGN | '\'' | '\"' | '^' | '&' )*
// ;
// Why did I do this? Isn't this handle by just increasing the look ahead?
NOT_EQ :
'<' { _ttype = LT; }
( ( '>' { _ttype = NOT_EQ; } )
| ( '=' { _ttype = LE; } ) )?
| "!=" | "^="
;
GT : '>' ( '=' { _ttype = GE; } )? ;
// This is not right. It will never pickup a leading PLUS, MINUS, or DOT.
// Should look at examples/java/java/java.g and follow that example. Not
// a priority just yet though.
NUMBER
:
( PLUS | MINUS )?
( ( N DOT N ) => N DOT N | DOT N | N )
( "e" ( PLUS | MINUS )? N )?
;
protected
N : '0' .. '9' ( '0' .. '9' )* ;
// Not sure exactly what the purpose of a double quote is. It has cropped up
// around column names and aliases. Maybe that means you could have
// table names, column names, or even aliases with spaces. If so, they should
// no longer be skipped and added the rules.
DOUBLE_QUOTE : '"' { $setType(Token.SKIP); } ;
//Added by Qazi to preserve the newlines and white spaces and single line comments
WS : (' '
| '\t'
| ('\n'|'\r'('\n')?) {newline();}
)+
;
// Single-line comments
SL_COMMENT
: "--"
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
//{$setType(Token.SKIP); newline();}
{newline();}
;
// Taken right from antlr-2.7.1/examples/java/java/java.g ...
// multiple-line comments
ML_COMMENT
: "/*"
( /* '\r' '\n' can be matched in one alternative or by matching
'\r' in one iteration and '\n' in another. I am trying to
handle any flavor of newline that comes in, but the language
that allows both "\r\n" and "\r" and "\n" to all be valid
newline is ambiguous. Consequently, the resulting grammar
must be ambiguous. I'm shutting this warning off.
*/
options {
generateAmbigWarnings=false;
}
:
{ LA(2)!='/' }? '*'
| '\r' '\n' {newline();}
| '\r' {newline();}
| '\n' {newline();}
| ~('*'|'\n'|'\r')
)*
"*/"
//{$setType(Token.SKIP);}
{newline();}
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -