/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
/** | |
* An JP QL grammar parser. | |
* | |
* Samples: | |
* SELECT COUNT(p) FROM Person AS p | |
* SELECT OBJECT(identifier) FROM schema identifier | |
* SELECT identifier FROM schema AS identifier | |
* | |
* @author Patrick Linskey | |
* @author Marc Prud'hommeaux | |
*/ | |
options { | |
NODE_PREFIX = "JPQL"; | |
NODE_PACKAGE = "org.apache.openjpa.kernel.jpql"; | |
MULTI = false; | |
NODE_DEFAULT_VOID = true; | |
JAVA_UNICODE_ESCAPE = true; | |
STATIC = false; | |
NODE_USES_PARSER = true; | |
LOOKAHEAD = 1; | |
// debugging variables | |
// DEBUG_PARSER = true; // simple parser debug | |
// DEBUG_TOKEN_MANAGER = true; // more verbose token manager debug | |
// DEBUG_LOOKAHEAD = true; // more verbose lookahead debug | |
SANITY_CHECK = true; // check for left-recursion, etc (must always be true) | |
// FORCE_LA_CHECK = true; | |
} | |
PARSER_BEGIN(JPQL) | |
package org.apache.openjpa.kernel.jpql; | |
import java.io.*; | |
/** | |
* @nojavadoc | |
*/ | |
public class JPQL | |
{ | |
String jpql; | |
boolean inEnumPath; | |
public JPQL (String jpql) | |
{ | |
this (new StringReader (jpql)); | |
this.jpql = jpql; | |
} | |
public static void main (String[] args) | |
throws Exception | |
{ | |
if (args.length > 0) | |
{ | |
for (int i = 0; i < args.length; i++) | |
{ | |
JPQL parser = new JPQL (args[i]); | |
SimpleNode ast = (SimpleNode) parser.parseQuery (); | |
ast.dump (System.out, ""); | |
} | |
} | |
else | |
{ | |
JPQL parser = new JPQL (System.in); | |
while (true) | |
{ | |
System.out.print ("Enter Expression: "); | |
System.out.flush (); | |
try | |
{ | |
SimpleNode ast = (SimpleNode) parser.parseQuery (); | |
if (ast == null) | |
return; | |
else | |
ast.dump (System.out, ""); | |
} | |
catch (Throwable x) | |
{ | |
x.printStackTrace (); | |
return; | |
} | |
} | |
} | |
} | |
} | |
PARSER_END(JPQL) | |
SKIP : | |
{ | |
" " | |
| "\n" | |
| "\r" | |
| "\t" | |
} | |
TOKEN [ IGNORE_CASE ]: /* basics */ | |
{ | |
< COMMA: "," > | |
| < DOT: "." > | |
| < EQ: "=" > | |
| < NE: "<>" > | |
| < GT: ">" > | |
| < GE: ">=" > | |
| < LT: "<" > | |
| < LE: "<=" > | |
| < PLUS: "+" > | |
| < MINUS: "-" > | |
| < TIMES: "*" > | |
| < DIV: "/" > | |
| < NEW: "NEW" > | |
| < ALL: "ALL" > | |
| < ANY: "ANY" > | |
| < EXISTS: "EXISTS" > | |
| < SOME: "SOME" > | |
| < EMPTY: "EMPTY" > | |
| < ASC: "ASC" > | |
| < DESC: "DESC" > | |
| < ORDER: "ORDER" > | |
| < BY: "BY" > | |
| < IS: "IS" > | |
| < MEMBER: "MEMBER" > | |
| < OF: "OF" > | |
| < LIKE: "LIKE" > | |
| < ESCAPE: "ESCAPE" > | |
| < BETWEEN: "BETWEEN" > | |
| < NULL: "NULL" > | |
| < KEY: "KEY" > | |
| < VALUE: "VALUE" > | |
| < TYPE: "TYPE" > | |
| < ENTRY: "ENTRY" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* aggregates */ | |
{ | |
< AVG: "AVG" > | |
| < MIN: "MIN" > | |
| < MAX: "MAX" > | |
| < SUM: "SUM" > | |
| < COUNT: "COUNT" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* boolean arithmetic */ | |
{ | |
< OR: "OR" > | |
| < AND: "AND" > | |
| < NOT: "NOT" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* functions returning strings */ | |
{ | |
< CONCAT: "CONCAT" > | |
| < SUBSTRING: "SUBSTRING" > | |
| < TRIM: "TRIM" > | |
| < LOWER: "LOWER" > | |
| < UPPER: "UPPER" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* trim specification */ | |
{ | |
< LEADING: "LEADING" > | |
| < TRAILING: "TRAILING" > | |
| < BOTH: "BOTH" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* functions returning numerics */ | |
{ | |
< LENGTH: "LENGTH" > | |
| < LOCATE: "LOCATE" > | |
| < ABS: "ABS" > | |
| < SQRT: "SQRT" > | |
| < MOD: "MOD" > | |
| < SIZE: "SIZE" > | |
| < INDEX: "INDEX" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* functions returning datetime */ | |
{ | |
< CURRENT_DATE: "CURRENT_DATE" > | |
| < CURRENT_TIME: "CURRENT_TIME" > | |
| < CURRENT_TIMESTAMP: "CURRENT_TIMESTAMP" > | |
} | |
TOKEN [ IGNORE_CASE ]: /* type of query */ | |
{ | |
< SELECT: "SELECT" > | |
| < DISTINCT: "DISTINCT" > | |
| < FROM: "FROM" > | |
| < UPDATE: "UPDATE" > | |
| < DELETE: "DELETE" > | |
| < WHERE: "WHERE" > | |
| < GROUP: "GROUP" > | |
| < HAVING: "HAVING" > | |
| < AS: "AS" > | |
| < LEFT: "LEFT" > | |
| < OUTER: "OUTER" > | |
| < INNER: "INNER" > | |
| < JOIN: "JOIN" > | |
| < FETCH: "FETCH" > | |
| < IN: "IN" > | |
| < SET: "SET" > | |
| < OBJECT: "OBJECT" > | |
| < CASE: "CASE" > | |
| < WHEN: "WHEN" > | |
| < ELSE: "ELSE" > | |
| < THEN: "THEN" > | |
| < END: "END" > | |
| < NULLIF: "NULLIF" > | |
| < COALESCE: "COALESCE" > | |
| < CLASS: "CLASS" > | |
} | |
/* inspired by the Java 1.0.2 specification */ | |
/* ### should we limit this to the length that is valid in java? */ | |
TOKEN : /* literals */ | |
{ | |
< INTEGER_LITERAL: ((["0"-"9"])+) (["l","L"])? > | |
| < DECIMAL_LITERAL: | |
(((["0"-"9"])* "." (["0"-"9"])+) (<EXPONENT>)? (["f","F","d","D"])? | |
| ((["0"-"9"])+ ".") (<EXPONENT>)? (["f","F","d","D"])? | |
| ((["0"-"9"])+) (<EXPONENT>) (["f","F","d","D"])? | |
| ((["0"-"9"])+) (<EXPONENT>)? (["f","F","d","D"])?) > | |
| < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | |
| < STRING_LITERAL: "'" | |
(("''" | ~["'"]) | |
/* | |
(("''" | ~["'","\\","\n","\r"]) | |
| ("\\" | |
( ["n","t","b","r","f","\\","'"] | |
| ["0"-"7"] ( ["0"-"7"] )? | |
| ["0"-"3"] ["0"-"7"] ["0"-"7"] | |
) | |
) | |
*/ | |
)* | |
"'" | |
> | |
// Double quoted string | |
| < STRING_LITERAL2: "\"" ( (~["\""]) )* "\"" | |
> | |
| < CHARACTER_LITERAL: "'" | |
( (~["'","\\","\n","\r"]) | |
| ("\\" | |
( ["n","t","b","r","f","\\","'"] | |
| ["0"-"7"] ( ["0"-"7"] )? | |
| ["0"-"3"] ["0"-"7"] ["0"-"7"] | |
) | |
) | |
) | |
"'" | |
> | |
| < DATE_LITERAL: "{d '" (["0"-"9", "-"])* "'}" | |
> | |
| < TIME_LITERAL: "{t '" (["0"-"9", ":"])* "'}" | |
> | |
| < TIMESTAMP_LITERAL: "{ts '" (["0"-"9", "-", ":", " ", "."])* "'}" | |
> | |
} | |
TOKEN [ IGNORE_CASE ]: /* boolean literals can be case-insensitive */ | |
{ | |
< BOOLEAN_LITERAL: "TRUE" | "FALSE" > | |
} | |
/* From the Java 1.0.2 specification */ | |
TOKEN : /* IDENTIFIERS */ | |
{ | |
< IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* > | |
| | |
< #LETTER: | |
[ | |
"\u0024", // $ | |
"\u0041"-"\u005a", // A-Z | |
"\u005f", // _ | |
"\u0061"-"\u007a", // a-z | |
"\u00c0"-"\u00d6", | |
"\u00d8"-"\u00f6", | |
"\u00f8"-"\u00ff", | |
"\u0100"-"\u1fff", | |
"\u3040"-"\u318f", | |
"\u3300"-"\u337f", | |
"\u3400"-"\u3d2d", | |
"\u4e00"-"\u9fff", | |
"\uf900"-"\ufaff" | |
] | |
> | |
| | |
< #DIGIT: | |
[ | |
"\u0030"-"\u0039", // 0-9 | |
"\u0660"-"\u0669", | |
"\u06f0"-"\u06f9", | |
"\u0966"-"\u096f", | |
"\u09e6"-"\u09ef", | |
"\u0a66"-"\u0a6f", | |
"\u0ae6"-"\u0aef", | |
"\u0b66"-"\u0b6f", | |
"\u0be7"-"\u0bef", | |
"\u0c66"-"\u0c6f", | |
"\u0ce6"-"\u0cef", | |
"\u0d66"-"\u0d6f", | |
"\u0e50"-"\u0e59", | |
"\u0ed0"-"\u0ed9", | |
"\u1040"-"\u1049" | |
] | |
> | |
} | |
Node parseQuery() : { } | |
{ | |
(select_statement() | update_statement() | delete_statement()) <EOF> | |
{ | |
return jjtree.rootNode(); | |
} | |
} | |
void select_statement() #SELECT : { } | |
{ | |
select_clause() | |
from_clause() | |
[where_clause()] | |
[groupby_clause()] | |
[having_clause()] | |
[orderby_clause()] | |
} | |
void update_statement() #UPDATE : { } | |
{ | |
update_clause() [ where_clause() ] | |
} | |
void delete_statement() #DELETE : { } | |
{ | |
<DELETE> <FROM> (from_item() #FROM) [where_clause()] | |
} | |
void from_clause() #FROM : { } | |
{ | |
<FROM> identification_variable_declaration() | |
(LOOKAHEAD(1) <COMMA> (LOOKAHEAD(collection_member_declaration()) collection_member_declaration() | LOOKAHEAD(identification_variable_declaration())identification_variable_declaration()))* | |
} | |
void identification_variable_declaration(): { } | |
{ | |
from_item() (LOOKAHEAD(fetch_join()) fetch_join() | LOOKAHEAD(inner_join()) inner_join() | LOOKAHEAD(outer_join()) outer_join())* | |
} | |
void from_item() #FROMITEM : { } | |
{ | |
abstract_schema_name() [LOOKAHEAD(1)<AS>] [LOOKAHEAD(identification_variable())identification_variable()] | |
} | |
void subquery_from_clause() #FROM : { } | |
{ | |
<FROM> subquery_from_item() | |
( LOOKAHEAD(1) <COMMA> subquery_from_item() )* | |
} | |
void subselect_identification_variable_declaration(): { } | |
{ | |
from_item() (LOOKAHEAD(inner_join()) inner_join() | LOOKAHEAD(outer_join()) outer_join())* | |
} | |
void subquery_from_item() : { } | |
{ | |
LOOKAHEAD(collection_member_declaration()) collection_member_declaration() | |
| LOOKAHEAD(subselect_identification_variable_declaration()) subselect_identification_variable_declaration() | |
} | |
void inner_join() #INNERJOIN : { } | |
{ | |
[<INNER>] <JOIN> path() [<AS>] identification_variable() | |
} | |
void collection_member_declaration() #INNERJOIN : { } | |
{ | |
// synonymous with "INNER JOIN path AS identifier" (InnerJoin) | |
<IN> "(" (LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path()) ")" [ LOOKAHEAD(1)<AS>] identification_variable() | |
} | |
void outer_join() #OUTERJOIN : { } | |
{ | |
<LEFT> [ <OUTER>] <JOIN> path() [ LOOKAHEAD(1)<AS>] identification_variable() | |
} | |
void fetch_join() : { } | |
{ | |
outer_fetch_join() | inner_fetch_join() | |
} | |
void outer_fetch_join() #OUTERFETCHJOIN : { } | |
{ | |
<LEFT> [<OUTER>] <JOIN> <FETCH> path() | |
} | |
void inner_fetch_join() #INNERFETCHJOIN : { } | |
{ | |
[<INNER>] <JOIN> <FETCH> path() | |
} | |
void path() #PATH : { } | |
{ | |
// a path is any dot-separated path expression starting with a | |
// non-reserved word | |
identification_variable() (LOOKAHEAD(2) <DOT> path_component())+ | |
} | |
void update_clause() : { } | |
{ | |
<UPDATE> from_item() #FROM set_clause() | |
} | |
void set_clause() : { } | |
{ | |
<SET> update_item() (<COMMA> update_item())* | |
} | |
void update_item() #UPDATEITEM : { } | |
{ | |
path() EQ() new_value() | |
} | |
void new_value() #UPDATEVALUE : { } | |
{ | |
LOOKAHEAD(case_expression()) case_expression() | | |
LOOKAHEAD(arithmetic_expression()) arithmetic_expression() | | |
LOOKAHEAD(string_primary()) string_primary() | | |
LOOKAHEAD(datetime_primary()) datetime_primary() | | |
LOOKAHEAD(boolean_primary()) boolean_primary() | | |
LOOKAHEAD(enum_primary()) enum_primary() | | |
LOOKAHEAD(simple_entity_expression()) simple_entity_expression() | | |
<NULL> | |
} | |
void simple_entity_expression() : { } | |
{ | |
identification_variable() | input_parameter() | |
} | |
void select_clause() #SELECTCLAUSE : { } | |
{ | |
<SELECT> [distinct()] select_expressions() | |
} | |
void simple_select_clause() #SELECTCLAUSE : { } | |
{ | |
<SELECT> [distinct()] subselect_expressions() | |
} | |
void select_expressions() #SELECTEXPRESSIONS : { } | |
{ | |
select_expression() (<COMMA> select_expression())* | |
} | |
void select_expression() #SELECTEXPRESSION : { } | |
{ | |
(LOOKAHEAD(scalar_expression()) scalar_expression() | |
| LOOKAHEAD(aggregate_select_expression()) aggregate_select_expression() | |
| LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(qualified_identification_variable()) qualified_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
| <OBJECT> "(" identification_variable() ")" | |
| constructor_expression() | |
| LOOKAHEAD(entity_type_expression()) entity_type_expression() | |
| LOOKAHEAD(select_extension()) select_extension() | |
) [ LOOKAHEAD(1)[<AS>] identification_variable()] | |
} | |
void select_extension() #SELECTEXTENSION : { } | |
{ | |
scalar_function() | |
} | |
void subselect_expressions() #SELECTEXPRESSIONS : { } | |
{ | |
subselect_expression() (<COMMA> subselect_expression())* | |
} | |
void subselect_expression() #SELECTEXPRESSION : { } | |
{ | |
LOOKAHEAD(scalar_expression()) scalar_expression() | |
| LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(qualified_identification_variable()) qualified_identification_variable() | |
| LOOKAHEAD(aggregate_select_expression()) aggregate_select_expression() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
} | |
void constructor_expression() #CONSTRUCTOR : { } | |
{ | |
<NEW> classname() constructor_parameters() | |
} | |
void classname() #CLASSNAME : | |
{ Token t; } | |
{ | |
identification_variable() (<DOT> identification_variable())* | |
} | |
void constructor_parameters() #CONSTRUCTORPARAMS : { } | |
{ | |
"(" (constructor_parameter()) (<COMMA> (constructor_parameter()))* ")" | |
} | |
void constructor_parameter() #CONSTRUCTORPARAM : { } | |
{ | |
LOOKAHEAD(scalar_expression()) scalar_expression() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(qualified_identification_variable()) qualified_identification_variable() | |
| LOOKAHEAD(path()) path() | |
| LOOKAHEAD(aggregate_select_expression()) aggregate_select_expression() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
} | |
/* rewritten to reduce lookaheads */ | |
void aggregate_select_expression() #AGGREGATE : { } | |
{ | |
(avg() | max() | min() | sum() | count()) | |
} | |
void distinct() #DISTINCT : { } | |
{ | |
<DISTINCT> | |
} | |
void aggregate_path() : { } | |
{ | |
"(" ( | |
LOOKAHEAD(arithmetic_expression()) arithmetic_expression() | | |
LOOKAHEAD(distinct_path()) distinct_path() | | |
LOOKAHEAD(path()) path() | | |
LOOKAHEAD(qualified_path()) qualified_path() | | |
LOOKAHEAD(identification_variable()) identification_variable() | |
) ")" | |
} | |
void distinct_path() #DISTINCTPATH : { } | |
{ | |
<DISTINCT> ( | |
LOOKAHEAD(path()) path() | | |
LOOKAHEAD(qualified_path()) qualified_path() | | |
LOOKAHEAD(qualified_identification_variable()) qualified_identification_variable() | | |
LOOKAHEAD(identification_variable()) identification_variable() | |
) | |
} | |
void count() #COUNT : { } | |
{ | |
<COUNT> aggregate_path() | |
} | |
void avg() #AVERAGE : { } | |
{ | |
<AVG> aggregate_path() | |
} | |
void max() #MAX : { } | |
{ | |
<MAX> aggregate_path() | |
} | |
void min() #MIN : { } | |
{ | |
<MIN> aggregate_path() | |
} | |
void sum() #SUM : { } | |
{ | |
<SUM> aggregate_path() | |
} | |
void where_clause() #WHERE : { } | |
{ | |
<WHERE> conditional_expression() | |
} | |
void groupby_clause() #GROUPBY : { } | |
{ | |
<GROUP> <BY> groupby_item() | |
(LOOKAHEAD(2) <COMMA> (groupby_item()))* | |
} | |
void groupby_item() : { } | |
{ | |
LOOKAHEAD(path()) path() | |
| LOOKAHEAD(groupby_extension()) groupby_extension() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
} | |
void groupby_extension() #GROUPBYEXTENSION : { } | |
{ | |
scalar_function() | |
} | |
void having_clause() #HAVING : { } | |
{ | |
<HAVING> conditional_expression() | |
} | |
void subquery() #SUBSELECT : { } | |
{ | |
simple_select_clause() | |
subquery_from_clause() | |
[LOOKAHEAD(where_clause()) where_clause()] | |
[LOOKAHEAD(groupby_clause()) groupby_clause()] | |
[LOOKAHEAD(having_clause()) having_clause()] | |
} | |
/* changed to eliminate left recursion */ | |
void conditional_expression() : { } | |
{ | |
conditional_term() (LOOKAHEAD(2) <OR> (conditional_expression() #OR(2)))* | |
} | |
/* changed to eliminate left recursion */ | |
void conditional_term() : { } | |
{ | |
conditional_factor() (LOOKAHEAD(2) <AND> (conditional_term() #AND(2)))* | |
} | |
void conditional_factor() : { } | |
{ | |
LOOKAHEAD(<NOT> conditional_primary()) | |
(<NOT> conditional_primary() #NOT) | conditional_primary() | |
} | |
void conditional_primary() : { } | |
{ | |
LOOKAHEAD(simple_cond_expression()) | |
simple_cond_expression() | "(" conditional_expression() ")" | |
} | |
void simple_cond_expression() : { } | |
{ | |
//LOOKAHEAD(all_or_any_expression()) all_or_any_expression() | | |
LOOKAHEAD(exists_expression()) exists_expression() | | |
LOOKAHEAD(comparison_expression()) comparison_expression() | | |
LOOKAHEAD(between_expression()) between_expression() | | |
LOOKAHEAD(like_expression()) like_expression() | | |
LOOKAHEAD(in_expression()) in_expression() | | |
LOOKAHEAD(null_comparison_expression()) null_comparison_expression() | | |
LOOKAHEAD(empty_collection_comparison_expression()) empty_collection_comparison_expression() | | |
LOOKAHEAD(collection_member_expression()) collection_member_expression() | |
} | |
void between_expression() #BETWEEN : { } | |
{ | |
LOOKAHEAD(6) arithmetic_expression() | |
[<NOT> { jjtThis.not = true; }] <BETWEEN> arithmetic_expression() | |
<AND> arithmetic_expression() | |
| LOOKAHEAD(6) string_expression() | |
[<NOT> { jjtThis.not = true; }] <BETWEEN> string_expression() <AND> string_expression() | |
| LOOKAHEAD(6) datetime_expression() | |
[<NOT> { jjtThis.not = true; }] <BETWEEN> datetime_expression() <AND> datetime_expression() | |
} | |
void in_expression() #IN : { } | |
{ | |
(path() | scalar_function() | type_discriminator()) [ LOOKAHEAD(1) <NOT> { jjtThis.not = true; }] <IN> | |
("(" (literal_or_param() | |
(<COMMA> (literal_or_param()))* | subquery()) | |
")" | |
| collection_valued_input_parameter() | |
) | |
} | |
void entity_type_literal() #TYPELITERAL : { } | |
{ | |
identification_variable() | |
} | |
void literal_or_param() : { } | |
{ | |
(numeric_literal() | |
| string_literal() | |
| string_literal2() | |
| boolean_literal() | |
| input_parameter() | |
| entity_type_literal()) | |
} | |
void like_expression() #LIKE : { } | |
{ | |
string_expression() [<NOT> { jjtThis.not = true; }] <LIKE> pattern_value() | |
} | |
void null_comparison_expression() #ISNULL : { } | |
{ | |
(input_parameter() | |
| LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| <VALUE> "(" identification_variable() ")" | |
| LOOKAHEAD(aggregate_select_expression()) aggregate_select_expression() | |
) <IS> [<NOT> { jjtThis.not = true; }] <NULL> | |
} | |
void empty_collection_comparison_expression() #ISEMPTY : { } | |
{ | |
(LOOKAHEAD(path()) path() | LOOKAHEAD(qualified_path()) qualified_path()) | |
<IS> [<NOT> { jjtThis.not = true; }] <EMPTY> | |
} | |
void collection_member_expression() #MEMBEROF : { } | |
{ | |
(LOOKAHEAD(path()) path() | input_parameter() | LOOKAHEAD(literal()) literal() | path_component()) | |
[<NOT> { jjtThis.not = true; }] <MEMBER> [<OF>] | |
(LOOKAHEAD(path()) path() | LOOKAHEAD(qualified_path()) qualified_path()) | |
} | |
void exists_expression() #EXISTS : { } | |
{ | |
[<NOT> { jjtThis.not = true; }] <EXISTS> "(" subquery() ")" | |
} | |
void all_or_any_expression() : { } | |
{ | |
any_expression() | some_expression() | all_expression() | |
} | |
void any_expression() #ANY : { } | |
{ | |
<ANY> "(" subquery() ")" | |
} | |
void some_expression() #ANY : { } | |
{ | |
// SOME and ANY are synonymous | |
<SOME> "(" subquery() ")" | |
} | |
void all_expression() #ALL : { } | |
{ | |
<ALL> "(" subquery() ")" | |
} | |
void comparison_expression() : { } | |
{ | |
// comparison_expression ::= string_value comparison_operator {string_expression | all_or_any_expression} | boolean_value { =|<>} {boolean_expression | all_or_any_expression} | datetime_primary comparison_operator {datetime_expression | all_or_any_expression} | entity_bean_value { = | <> } {entity_bean_expression | all_or_any_expression} | arithmetic_value comparison_operator {arithmetic_expression | all_or_any_expression | |
LOOKAHEAD(arithmetic_comp()) arithmetic_comp() | | |
LOOKAHEAD(string_comp()) string_comp() | | |
LOOKAHEAD(boolean_comp()) boolean_comp() | | |
LOOKAHEAD(enum_comp()) enum_comp() | | |
LOOKAHEAD(datetime_comp()) datetime_comp() | | |
LOOKAHEAD(entity_comp()) entity_comp() | | |
LOOKAHEAD(entity_type_comp()) entity_type_comp() | |
} | |
void string_comp() : { } | |
{ | |
string_expression() ( | |
(<EQ> (string_expression()|all_or_any_expression()) #EQUALS(2)) | |
| (<NE> (string_expression()|all_or_any_expression()) #NOTEQUALS(2)) | |
| (<GT> (string_expression() | all_or_any_expression()) #GREATERTHAN(2)) | |
| (<GE> (string_expression() | all_or_any_expression()) #GREATEROREQUAL(2)) | |
| (<LT> (string_expression() | all_or_any_expression()) #LESSTHAN(2)) | |
| (<LE> (string_expression() | all_or_any_expression()) #LESSOREQUAL(2)) | |
) | |
} | |
void boolean_comp() : { } | |
{ | |
boolean_expression() ( | |
(<EQ> (boolean_expression() | all_or_any_expression()) #EQUALS(2)) | |
| (<NE> (boolean_expression() | all_or_any_expression()) #NOTEQUALS(2)) | |
) | |
} | |
void enum_comp() : { } | |
{ | |
enum_expression() ( | |
(<EQ> (enum_expression() | all_or_any_expression()) #EQUALS(2)) | |
| (<NE> (enum_expression() | all_or_any_expression()) #NOTEQUALS(2)) | |
) | |
} | |
void entity_comp() : { } | |
{ | |
entity_bean_expression() ( | |
(<EQ> ((LOOKAHEAD(all_or_any_expression()) all_or_any_expression() | entity_bean_expression()) #EQUALS(2))) | |
| (<NE> ((LOOKAHEAD(all_or_any_expression()) all_or_any_expression() | entity_bean_expression()) #NOTEQUALS(2))) | |
) | |
} | |
void arithmetic_comp() : { } | |
{ | |
// arithmetic_value() ( | |
arithmetic_expression() ( | |
(<EQ> (arithmetic_expression() | all_or_any_expression()) #EQUALS(2)) | |
| (<GT> (arithmetic_expression() | all_or_any_expression()) #GREATERTHAN(2)) | |
| (<GE> (arithmetic_expression() | all_or_any_expression()) #GREATEROREQUAL(2)) | |
| (<LT> (arithmetic_expression() | all_or_any_expression()) #LESSTHAN(2)) | |
| (<LE> (arithmetic_expression() | all_or_any_expression()) #LESSOREQUAL(2)) | |
| (<NE> (arithmetic_expression() | all_or_any_expression()) #NOTEQUALS(2)) | |
) | |
} | |
void datetime_comp() : { } | |
{ | |
datetime_expression() ( | |
(<EQ> (datetime_expression() | all_or_any_expression()) #EQUALS(2)) | |
| (<GT> (datetime_expression() | all_or_any_expression()) #GREATERTHAN(2)) | |
| (<GE> (datetime_expression() | all_or_any_expression()) #GREATEROREQUAL(2)) | |
| (<LT> (datetime_expression() | all_or_any_expression()) #LESSTHAN(2)) | |
| (<LE> (datetime_expression() | all_or_any_expression()) #LESSOREQUAL(2)) | |
| (<NE> (datetime_expression() | all_or_any_expression()) #NOTEQUALS(2)) | |
) | |
} | |
void scalar_function() : { } | |
{ | |
functions_returning_numerics() | |
| functions_returning_datetime() | |
| functions_returning_strings() | |
} | |
void arithmetic_value() : { } | |
{ | |
path() | functions_returning_numerics() | "(" subquery() ")" | |
} | |
/* changed to eliminate left recursion */ | |
void arithmetic_expression() : { } | |
{ | |
arithmetic_term() | |
((<PLUS> arithmetic_expression() #ADD(2)) | |
| (<MINUS> arithmetic_expression() #SUBTRACT(2)))* | |
} | |
/* changed to eliminate left recursion */ | |
void arithmetic_term() : { } | |
{ | |
arithmetic_factor() | |
((<TIMES> arithmetic_term() #MULTIPLY(2)) | |
| (<DIV> arithmetic_term() #DIVIDE(2)))* | |
} | |
void arithmetic_factor() : { } | |
{ | |
numeric_literal() | | |
input_parameter() | | |
LOOKAHEAD(path()) path() | | |
LOOKAHEAD(qualified_path()) qualified_path() | | |
LOOKAHEAD(general_identification_variable()) general_identification_variable() | | |
LOOKAHEAD(identification_variable()) identification_variable() | | |
LOOKAHEAD("(" arithmetic_expression()) "(" arithmetic_expression() ")" | | |
LOOKAHEAD(functions_returning_numerics()) functions_returning_numerics() | | |
LOOKAHEAD(aggregate_select_expression()) aggregate_select_expression() | | |
LOOKAHEAD(case_expression()) case_expression() | | |
LOOKAHEAD("(" subquery()) "(" subquery() ")" | |
} | |
void qualified_path() #QUALIFIEDPATH : { } | |
{ | |
( <KEY> "(" identification_variable() ")" #KEY(1) | |
| <VALUE> "(" identification_variable() ")" | |
) (LOOKAHEAD(2) <DOT> path_component())+ | |
} | |
void qualified_identification_variable() #QUALIFIEDIDENTIFIER : { } | |
{ | |
( <KEY> "(" identification_variable() ")" #KEY(1) | |
| <VALUE> "(" identification_variable() ")" #VALUE(1) | |
| <ENTRY> "(" identification_variable() ")" #ENTRY(1) | |
) | |
} | |
void general_identification_variable() #GENERALIDENTIFIER : { } | |
{ | |
( <KEY> "(" identification_variable() ")" #KEY(1) | |
| <VALUE> "(" identification_variable() ")" #VALUE(1) | |
) | |
} | |
void entity_type_comp() : { } | |
{ | |
(entity_type_expression() | entity_type_literal()) | |
( <EQ> (entity_type_expression() | entity_type_literal()) #EQUALS(2) | |
| <NE> (entity_type_expression() | entity_type_literal()) #NOTEQUALS(2) | |
) | |
} | |
void type_discriminator() #TYPE : { } | |
{ | |
<TYPE> "(" (LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
| LOOKAHEAD(input_parameter()) input_parameter()) | |
")" | |
} | |
void entity_type_expression(): { } | |
{ | |
type_discriminator() | | |
input_parameter() | |
} | |
void scalar_expression() #SCALAREXPRESSION : { } | |
{ | |
LOOKAHEAD(arithmetic_expression()) arithmetic_expression() | | |
LOOKAHEAD(case_expression()) case_expression() | | |
LOOKAHEAD(string_primary()) string_primary() | | |
LOOKAHEAD(datetime_primary()) datetime_primary() | | |
LOOKAHEAD(enum_primary()) enum_primary() | | |
LOOKAHEAD(boolean_primary()) boolean_primary() | | |
LOOKAHEAD(entity_type_expression()) entity_type_expression() | |
} | |
void case_expression() #CASE : { } | |
{ | |
<CASE> | |
( LOOKAHEAD(general_case_expression()) general_case_expression() | |
| LOOKAHEAD(simple_case_expression()) simple_case_expression() | |
) | | |
<COALESCE> coalesce_expression() | | |
<NULLIF> nullif_expression() | |
} | |
void general_case_expression() #GENERALCASE : { } | |
{ | |
(when_clause())+ | |
<ELSE> (LOOKAHEAD(2) scalar_expression() | entity_type_literal()) | |
<END> | |
} | |
void when_clause() #WHEN : { } | |
{ | |
<WHEN> conditional_expression() | |
<THEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal()) | |
} | |
void simple_case_expression() #SIMPLECASE : { } | |
{ | |
(LOOKAHEAD(type_discriminator()) type_discriminator() | LOOKAHEAD(path()) path()) | |
(simple_when_clause())+ | |
<ELSE> (LOOKAHEAD(2) scalar_expression() | entity_type_literal()) | |
<END> | |
} | |
void simple_when_clause() #WHENSCALAR : { } | |
{ | |
<WHEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal()) | |
<THEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal()) | |
} | |
void coalesce_expression() #COALESCE : { } | |
{ | |
// COALESCE(e1,e2) => CASE WHEN e1 IS NOT NULL THEN e1 ELSE e2 END | |
// COALESCE(e1,e2,...,eN) => CASE WHEN e1 IS NOT NULL THEN e1 ELSE COALESCE(e2,...eN) END | |
"(" scalar_expression() (<COMMA> scalar_expression())+ ")" | |
} | |
void nullif_expression() #NULLIF : { } | |
{ | |
// NULLIF(e1,e2) => CASE WHEN e1=e2 THEN NULL ELSE e1 END | |
"(" scalar_expression() <COMMA> scalar_expression() ")" | |
} | |
void negative() #NEGATIVE : { } | |
{ | |
<MINUS> | |
} | |
void string_value() : { } | |
{ | |
path() | functions_returning_strings() | "(" subquery() ")" | |
} | |
void string_expression() : { } | |
{ | |
input_parameter() | string_primary() | |
} | |
void string_primary() : { } | |
{ | |
string_literal() | string_literal2() | LOOKAHEAD(path()) path() | | |
LOOKAHEAD(qualified_path()) qualified_path() | | |
LOOKAHEAD(general_identification_variable()) general_identification_variable() | | |
LOOKAHEAD(identification_variable()) identification_variable() | | |
LOOKAHEAD("(" string_expression()) "(" string_expression() ")" | | |
functions_returning_strings() | LOOKAHEAD("(" subquery()) "(" subquery() ")" | |
| case_expression() | |
} | |
void datetime_expression() : { } | |
{ | |
datetime_primary() | "(" subquery() ")" | |
} | |
void datetime_primary() : { } | |
{ | |
date_literal() | time_literal() | timestamp_literal() | | |
LOOKAHEAD(path()) path() | functions_returning_datetime() | input_parameter() | aggregate_select_expression() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
| case_expression() | |
} | |
void boolean_value() : { } | |
{ | |
path() | "(" subquery() ")" | |
} | |
void boolean_expression() : { } | |
{ | |
boolean_primary() | "(" subquery() ")" | |
} | |
void boolean_primary() : { } | |
{ | |
LOOKAHEAD(path()) path() | boolean_literal() | input_parameter() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
| case_expression() | |
} | |
void enum_expression() : { } | |
{ | |
enum_primary() | "(" subquery() ")" | |
} | |
void enum_primary() : { } | |
{ | |
LOOKAHEAD(2) path() | |
| LOOKAHEAD(enum_literal()) enum_literal() | |
| LOOKAHEAD(input_parameter()) input_parameter() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| LOOKAHEAD(identification_variable()) identification_variable() | |
| case_expression() | |
} | |
void enum_literal() : { } | |
{ | |
{ inEnumPath = true; } | |
path() | |
{ inEnumPath = false; } | |
} | |
void entity_bean_value() : { } | |
{ | |
LOOKAHEAD(path()) path() | |
| LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(path_component()) path_component() | |
} | |
void entity_bean_expression() : { } | |
{ | |
input_parameter() | entity_bean_value() | |
} | |
void functions_returning_strings() : { } | |
{ | |
concat() | substring() | trim() | lower() | upper() | |
} | |
void concat() #CONCAT : { } | |
{ | |
<CONCAT> "(" string_expression() <COMMA> string_expression() [ <COMMA> string_expression() ] ")" | |
} | |
void substring() #SUBSTRING : { } | |
{ | |
<SUBSTRING> "(" string_expression() <COMMA> arithmetic_expression() [ <COMMA> arithmetic_expression() ] ")" | |
} | |
void trim() #TRIM : { } | |
{ | |
<TRIM> "(" [LOOKAHEAD(2)[trim_specification()] [trim_character()] <FROM>] | |
string_expression() ")" | |
} | |
void lower() #LOWER : { } | |
{ | |
<LOWER> "(" string_expression() ")" | |
} | |
void upper() #UPPER : { } | |
{ | |
<UPPER> "(" string_expression() ")" | |
} | |
void trim_specification() : { } | |
{ | |
LOOKAHEAD(2) (<LEADING> #TRIMLEADING) | (<TRAILING> #TRIMTRAILING) | (<BOTH> #TRIMBOTH) | |
} | |
void functions_returning_numerics() : { } | |
{ | |
length() | locate() | abs() | sqrt() | mod() | size() | index() | |
} | |
void length() #LENGTH : { } | |
{ | |
<LENGTH> "(" string_expression() ")" | |
} | |
void locate() #LOCATE : { } | |
{ | |
<LOCATE> "(" string_expression() <COMMA> string_expression() | |
[<COMMA> arithmetic_expression()] ")" | |
} | |
void abs() #ABS : { } | |
{ | |
<ABS> "(" arithmetic_expression() ")" | |
} | |
void sqrt() #SQRT : { } | |
{ | |
<SQRT> "(" arithmetic_expression() ")" | |
} | |
void mod() #MOD : { } | |
{ | |
<MOD> "(" arithmetic_expression() <COMMA> arithmetic_expression() ")" | |
} | |
void size() #SIZE : { } | |
{ | |
<SIZE> "(" (LOOKAHEAD(path()) path() | | |
LOOKAHEAD(qualified_path()) qualified_path()) ")" | |
} | |
void index() #INDEX : { } | |
{ | |
<INDEX> "(" identification_variable() ")" | |
} | |
void functions_returning_datetime() : { } | |
{ | |
(<CURRENT_DATE> #CURRENTDATE) | |
| (<CURRENT_TIME> #CURRENTTIME) | |
| (<CURRENT_TIMESTAMP> #CURRENTTIMESTAMP) | |
} | |
void orderby_clause() #ORDERBY : { } | |
{ | |
<ORDER> <BY> orderby_item() (<COMMA> orderby_item())* | |
} | |
void orderby_item() #ORDERBYITEM : { } | |
{ | |
(LOOKAHEAD(path()) path() | LOOKAHEAD(qualified_path()) qualified_path() | |
| LOOKAHEAD(general_identification_variable()) general_identification_variable() | |
| orderby_extension() | identification_variable() | |
) | |
[ <ASC> #ASCENDING | <DESC> #DESCENDING ] | |
} | |
void orderby_extension() #ORDERBYEXTENSION : { } | |
{ | |
aggregate_select_expression() | |
} | |
void abstract_schema_name() #ABSTRACTSCHEMANAME : { } | |
{ | |
path_component() (<DOT> path_component())* | |
} | |
void tok() #TOK : | |
{ Token t; } | |
{ | |
t = <IDENTIFIER> { jjtThis.setToken (t); } | |
} | |
void identification_variable() #IDENTIFIER : | |
{ Token t; } | |
{ | |
t = <IDENTIFIER> { jjtThis.setToken (t); } | |
} | |
void path_component() #IDENTIFICATIONVARIABLE : | |
{ Token t; } | |
{ | |
// unlike the identifier(), the path_component() *can* be a | |
// reserved word. E.g., Order.group.length is a perfectly | |
// valid path expression | |
( | |
t = <NEW> | |
| t = <ALL> | |
| t = <ANY> | |
| t = <EXISTS> | |
| t = <SOME> | |
| t = <EMPTY> | |
| t = <ASC> | |
| t = <DESC> | |
| t = <ORDER> | |
| t = <IS> | |
| t = <MEMBER> | |
| t = <OF> | |
| t = <LIKE> | |
| t = <ESCAPE> | |
| t = <BETWEEN> | |
| t = <NULL> | |
| t = <AVG> | |
| t = <MIN> | |
| t = <MAX> | |
| t = <SUM> | |
| t = <COUNT> | |
| t = <OR> | |
| t = <AND> | |
| t = <NOT> | |
| t = <CONCAT> | |
| t = <SUBSTRING> | |
| t = <TRIM> | |
| t = <LOWER> | |
| t = <UPPER> | |
| t = <LEADING> | |
| t = <TRAILING> | |
| t = <BOTH> | |
| t = <LENGTH> | |
| t = <LOCATE> | |
| t = <ABS> | |
| t = <SQRT> | |
| t = <MOD> | |
| t = <SIZE> | |
| t = <CURRENT_DATE> | |
| t = <CURRENT_TIME> | |
| t = <CURRENT_TIMESTAMP> | |
| t = <SELECT> | |
| t = <DISTINCT> | |
| t = <FROM> | |
| t = <UPDATE> | |
| t = <DELETE> | |
| t = <WHERE> | |
| t = <GROUP> | |
| t = <BY> | |
| t = <HAVING> | |
| t = <AS> | |
| t = <LEFT> | |
| t = <OUTER> | |
| t = <INNER> | |
| t = <JOIN> | |
| t = <FETCH> | |
| t = <IN> | |
| t = <SET> | |
| t = <OBJECT> | |
| t = <IDENTIFIER> | |
| t = <CASE> | |
| t = <COALESCE> | |
| t = <NULLIF> | |
| t = <WHEN> | |
| t = <THEN> | |
| t = <ELSE> | |
| t = <END> | |
| t = <KEY> | |
| t = <VALUE> | |
| t = <ENTRY> | |
| t = <INDEX> | |
| t = <TYPE> | |
| t = <CLASS> | |
) { jjtThis.setToken (t); } | |
} | |
void literal() : { } | |
{ | |
numeric_literal() | boolean_literal() | string_literal() | string_literal2() | enum_literal() | date_literal() | | |
time_literal() | timestamp_literal() | |
} | |
void numeric_literal() : { } | |
{ | |
LOOKAHEAD(decimal_literal()) decimal_literal() | integer_literal() | |
} | |
void integer_literal() #INTEGERLITERAL : | |
{ Token t; } | |
{ | |
[<PLUS> | negative()] t = <INTEGER_LITERAL> { jjtThis.setToken (t); } | |
} | |
void decimal_literal() #DECIMALLITERAL : | |
{ Token t; } | |
{ | |
[<PLUS> | negative()] t = <DECIMAL_LITERAL> { jjtThis.setToken (t); } | |
} | |
void boolean_literal() #BOOLEANLITERAL : | |
{ Token t; } | |
{ | |
t = <BOOLEAN_LITERAL> { jjtThis.setToken (t); } | |
} | |
void string_literal() #STRINGLITERAL : | |
{ Token t; } | |
{ | |
t = <STRING_LITERAL> { jjtThis.setToken (t); } | |
} | |
void string_literal2() #STRINGLITERAL2 : | |
{ Token t; } | |
{ | |
t = <STRING_LITERAL2> { jjtThis.setToken (t); } | |
} | |
void date_literal() #DATELITERAL : | |
{ Token t; } | |
{ | |
t = <DATE_LITERAL> { jjtThis.setToken (t); } | |
} | |
void time_literal() #TIMELITERAL : | |
{ Token t; } | |
{ | |
t = <TIME_LITERAL> { jjtThis.setToken (t); } | |
} | |
void timestamp_literal() #TIMESTAMPLITERAL : | |
{ Token t; } | |
{ | |
t = <TIMESTAMP_LITERAL> { jjtThis.setToken (t); } | |
} | |
void input_parameter() : { } | |
{ | |
named_input_parameter() | positional_input_parameter() | |
} | |
void collection_valued_input_parameter() #COLLECTIONPARAMETER: { } | |
{ | |
named_input_parameter() | positional_input_parameter() | |
} | |
void named_input_parameter() #NAMEDINPUTPARAMETER : { } | |
{ | |
":" path_component() | |
} | |
void positional_input_parameter() #POSITIONALINPUTPARAMETER : | |
{ Token t; } | |
{ | |
"?" t = <INTEGER_LITERAL> { jjtThis.setToken (t); } | |
} | |
void pattern_value() #PATTERNVALUE : { } | |
{ | |
(input_parameter() | string_literal() | string_literal2()) | |
[(<ESCAPE> escape_character() #ESCAPECHARACTER)] | |
} | |
void escape_character() #ESCAPECHARACTER : | |
{ Token t; } | |
{ | |
t = <STRING_LITERAL> { jjtThis.setToken (t); } | |
} | |
void trim_character() #TRIMCHARACTER : | |
{ Token t; } | |
{ | |
t = <STRING_LITERAL> { jjtThis.setToken (t); } | |
} | |
void EQ() #EQUALS : { } | |
{ | |
<EQ> | |
} | |
void NE() #NOTEQUALS : { } | |
{ | |
<NE> | |
} | |
void GT() #GREATERTHAN : { } | |
{ | |
<GT> | |
} | |
void GE() #GREATEROREQUAL : { } | |
{ | |
<GE> | |
} | |
void LT() #LESSTHAN : { } | |
{ | |
<LT> | |
} | |
void LE() #LESSOREQUAL : { } | |
{ | |
<LE> | |
} |