问题描述
输入:toAccount = 'Electricity/Water'
语法:
grammar FQL;
/*
* Parser rules
*/
query
: (orExpression | orderByExpression EOF)* ;
orExpression
: andExpression (OR andExpression)* ;
andExpression
: expression (AND expression)* ;
expression
: (regularExpression | betweenExpression | periodExpression)
| parenthesisExpression ;
parenthesisExpression
: L_PAREN expr=orExpression R_PAREN ;
orderByExpression
: ORDER_BY field=IDENTIFIER order=(DESC | ASC ) ;
// regular expressions - NOT regex
regularExpression
: (stringExpression | intExpression | booleanExpression | dateExpression) ;
stringExpression
: field=IDENTIFIER operator=STRING_OPERATOR value=STRING_VALUE ;
intExpression
: field=IDENTIFIER operator=(INT_OPERATOR | STRING_OPERATOR) value=INT_VALUE ;
booleanExpression
: field=IDENTIFIER operator=STRING_OPERATOR value=(TRUE | FALSE) ;
dateExpression
: field=IDENTIFIER operator=STRING_OPERATOR value=DATE_VALUE ;
// BETWEEN expressions
betweenExpression
: (betweenStringExpression | betweenIntExpression ) ;
betweenStringExpression
: field=IDENTIFIER BETWEEN left=STRING_VALUE AND right=STRING_VALUE ;
betweenIntExpression
: field=IDENTIFIER BETWEEN left=INT_VALUE AND right=INT_VALUE ;
// period expressions
periodExpression
: periodConstExpression ;
periodConstExpression
: field=IDENTIFIER operator=STRING_OPERATOR value=(CURRENT |
LAST |
CURRENT_YEAR |
LAST_YEAR |
GRAND_TOTAL) ;
/*
* Lexer rules
*/
fragment B : ('B' | 'b') ;
fragment E : ('E' | 'e') ;
fragment T : ('T' | 't') ;
fragment W : ('W' | 'w') ;
fragment N : ('N' | 'n') ;
fragment A : ('A' | 'a') ;
fragment D : ('D' | 'd') ;
fragment C : ('C' | 'c') ;
fragment U : ('U' | 'u') ;
fragment R : ('R' | 'r') ;
fragment L : ('L' | 'l') ;
fragment S : ('S' | 's') ;
fragment Y : ('Y' | 'y') ;
fragment G : ('G' | 'g') ;
fragment O : ('O' | 'o') ;
fragment F : ('F' | 'f') ;
fragment SPACE : ' ' ;
// Keywords
BETWEEN : B E T W E E N ;
AND : A N D ;
OR : O R ;
ORDER_BY : O R D E R SPACE B Y ;
DESC : D E S C ;
ASC : A S C ;
TRUE : T R U E ;
FALSE : F A L S E ;
// Constant values
CURRENT : C U R R E N T ;
LAST : L A S T ;
YEAR : Y E A R ;
GRAND_TOTAL : G R A N D '_' T O T A L ;
CURRENT_YEAR : CURRENT '_' YEAR ;
LAST_YEAR : LAST '_' YEAR ;
STRING_OPERATOR : '=' ;
INT_OPERATOR : '>' | '<' | '>=' | '<=' | '!=' ;
L_PAREN : '(' ;
R_PAREN : ')' ;
IDENTIFIER : [a-zA-Z]+ ;
INT_VALUE : [0-9]+ ;
STRING_VALUE : '\'' [a-zA-Z0-9-/ ]+ '\'' ;
DATE_VALUE : [0-9-]+ ;
NEWLINE : ('\r'? '\n' | '\r')+ ;
WHITESPACE : ' ' -> skip;
引发异常:
java.lang.StackOverflowError: null
at org.antlr.v4.runtime.misc.Array2DHashSet.getBucket(Array2DHashSet.java:108) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
at org.antlr.v4.runtime.misc.Array2DHashSet.getorAddImpl(Array2DHashSet.java:63) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
at org.antlr.v4.runtime.misc.Array2DHashSet.getorAdd(Array2DHashSet.java:59) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
at org.antlr.v4.runtime.atn.ATNConfigSet.add(ATNConfigSet.java:146) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
at org.antlr.v4.runtime.atn.ATNConfigSet.add(ATNConfigSet.java:122) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
at org.antlr.v4.runtime.atn.LexerATNSimulator.closure(LexerATNSimulator.java:446) ~[antlr4-runtime-4.8-1.jar!/:4.8-1]
我猜想它与STRING_VALUE
中的/有关,因为没有它,表达式就可以成功解析。我尝试调试它,但我不了解ANTLR幕后的情况。我还用Google搜索了ANTLR的转义符,但据我了解,没有必要逃脱斜线。
有什么想法吗?
解决方法
问题出在设置范围运算符(又名“破折号”)上。要将范围运算符包括为文字,您必须对其进行转义
STRING_VALUE: '\'' [a-zA-Z0-9\-/ ]+ '\'' ;
或将其指定为集合中的最后一个成员项。
DATE_VALUE : [0-9-]+ ;