I want to parse SQL expression that contains and
and or
key words. The problem is Antlrwork
can throw exception for error grammar, but generated java code can not throw exception. Meanwhile, i find that generated java code is error that only can generate a half of AST and have no error information, that execute path can not reach point of exception.
This is my dot g files:
grammar ContainsExpr;
options {
language = Java;
output=AST;
ASTLabelType=CommonTree;
}
tokens {
DIVIDE = '/' ;
PLUS = '+' ;
MINUS = '-' ;
STAR = '*' ;
MOD = '%' ;
AMPERSAND = '&' ;
TILDE = '~' ;
BITWISEOR = '|' ;
COMMA = ',';
DOT = '.';
LPAREN = '(' ;
RPAREN = ')' ;
EQUAL = '=';
NOTEQUAL = '!=';
LESSTHANOREQUALTO = '<=';
LESSTHAN = '<';
GREATERTHANOREQUALTO = '>=';
GREATERTHAN = '>';
AND = 'AND';
OR = 'OR' ;
TRUE = 'TRUE';
FALSE = 'FALSE';
KW_NEAR = 'NEAR';
DOUBLE_QUOTE = '\"';
SINGLE_QUOTE = '\'';
TOK_NEAR;
TOK_ITEMS;
TOK_PARAMETER;
TOK_WILDCARDS;
}
@header {
package test1;
}
@members {
//override method
public void reportError(RecognitionException e) {
displayRecognitionError(this.getTokenNames(), e);
}
@Override
public void emitErrorMessage(String message) {
throw new RuntimeException(message);
}
}
@lexer::header {
package test1;
}
@lexer::members {
//override method
public void reportError(RecognitionException e) {
displayRecognitionError(this.getTokenNames(), e);
}
}
@rulecatch {
catch (RecognitionException e) {
reportError(e);
throw e;
}
}
// LITERALS
fragment
Letter
: 'a'..'z' | 'A'..'Z'
;
fragment
Digit
:
'0'..'9'
;
fragment
Exponent
:
('e' | 'E') ( PLUS|MINUS )? (Digit)+
;
Number
:
(Digit)+ ( DOT (Digit)* (Exponent)? | Exponent)?
;
fragment
UnquotedString
:
( ~(SINGLE_QUOTE|DOUBLE_QUOTE|' '|'\t'|'\n'|LPAREN|RPAREN|COMMA))+
;
fragment
QuotedLiteral
:
DOUBLE_QUOTE ( ~(DOUBLE_QUOTE|'\\') | ('\\' .) )* DOUBLE_QUOTE
;
Parameter
:
UnquotedString | QuotedLiteral
;
WS : (' '|'\r'|'\t'|'\n'|'\u000C')* {$channel=HIDDEN;}
;
eval
:
searchCondition
;
//AND has precedence over OR
searchCondition
:
andExpr (precedenceOrOperator^ andExpr)*
;
andExpr
:
subCondition (precedenceAndOperator^ subCondition)*
;
precedenceAndOperator
:
AND | AMPERSAND
;
precedenceOrOperator
:
OR | BITWISEOR
;
subCondition
:
atom
| LPAREN searchCondition RPAREN
;
atom
:
subEressixpon
;
subEressixpon
:
Parameter -> ^(TOK_PARAMETER Parameter)
;
When input incorrectly expression expr1 epxr2
(The AND is skipped), The execution result of java code is "expr1".
The generated java code of searchCondition rule is incorrect:
try {
// ( andExpr ( precedenceOrOperator ^ andExpr )* )
// andExpr ( precedenceOrOperator ^ andExpr )*
{
root_0 = (CommonTree)adaptor.nil();
pushFollow(FOLLOW_andExpr_in_searchCondition714);
andExpr2=andExpr();
state._fsp--;
adaptor.addChild(root_0, andExpr2.getTree());
// ( precedenceOrOperator ^ andExpr )*
loop1:
while (true) {
int alt1=2;
int LA1_0 = input.LA(1);
if ( (LA1_0==BITWISEOR||LA1_0==OR) ) {
alt1=1;
}
switch (alt1) {
case 1 :
// precedenceOrOperator ^ andExpr
{
pushFollow(FOLLOW_precedenceOrOperator_in_searchCondition717);
precedenceOrOperator3=precedenceOrOperator();
state._fsp--;
root_0 = (CommonTree)adaptor.becomeRoot(precedenceOrOperator3.getTree(), root_0);
pushFollow(FOLLOW_andExpr_in_searchCondition720);
andExpr4=andExpr();
state._fsp--;
adaptor.addChild(root_0, andExpr4.getTree());
}
break;
default :
break loop1;
}
}
}
retval.stop = input.LT(-1);
retval.tree = (CommonTree)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException e) {
reportError(e);
throw e;
}
finally {
// do for sure before leaving
}
In while
loop, When LA1_0
is OR
key words, It will be normal reach point of exception. So it will can not to throw exception.