Я пытаюсь выполнить динамические выражения для входных данных (Map) с помощью ANTLR и ответа @Bart Kiers из поста stackoverflow Мне удалось это сделать.
Я пытался добавить IN
, STARTSWITH
, ENDSWITH
условие в грамматоре и пытался добавить для него логику со стороны Java. В случае функции IN
я пытаюсь разделить набор строк, желательно используя специальный символ , (comma)
. Но когда я добавляю их в свое выражение, я получаю следующую ошибку:
line 1:64 token recognition error at: ','
Подскажите, как разрешить использование специальных символов в выражении.
Файл Grammer, который я использовал
grammar SimpleBoolean;
parse
: expression EOF
;
expression
: LPAREN expression RPAREN #parenExpression
| NOT expression #notExpression
| left=expression op=comparator right=expression #comparatorExpression
| left=expression op=binary right=expression #binaryExpression
| bool #boolExpression
| IDENTIFIER #identifierExpression
| DECIMAL #decimalExpression
;
comparator
: GT | GE | LT | LE | EQ | NE | IN | NOTIN | STARTSWITH | ENDSWITH | NULL | NOTNULL
;
binary
: AND | OR
;
bool
: TRUE | FALSE
;
AND : 'AND' ;
OR : 'OR' ;
NOT : 'NOT';
TRUE : 'TRUE' ;
FALSE : 'FALSE' ;
GT : '>' ;
GE : '>=' ;
LT : '<' ;
LE : '<=' ;
EQ : '=' ;
NE : '!=' ;
IN : 'IN' ;
NOTIN : 'NOTIN' ;
STARTSWITH : 'STARTSWITH' ;
ENDSWITH : 'ENDSWITH' ;
NULL : 'NULL' ;
NOTNULL : 'NOTNULL' ;
LPAREN : '(' ;
RPAREN : ')' ;
DECIMAL : '-'? [0-9]+ ( '.' [0-9]+ )? ;
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]* ;
WS : [ \r\t\u000C\n]+ -> skip;
Измененный EvalVisitor.class
Добавлены строки ниже
if (ctx.op.EQ() != null) {
return this.visit(ctx.left).equals(this.visit(ctx.right));
}
else if (ctx.op.IN() != null) {
String checkVal[] = this.visit(ctx.right).toString().split(",");
boolean valuePresent = false;
for(String value : checkVal) {
if (value.equals(this.visit(ctx.left).toString()))
valuePresent = true;
}
return valuePresent;
}
Выражение, которое я передал,
ID = ID AND NOT ( comments = comments AND system IN system,admin,developer )
К сожалению, я не могу передать обратную косую черту во входных данных, поскольку это может повлиять на требование :(
В каком месте вашей грамматики вы пытаетесь поставить запятые?
Добавьте expression ( ',' expression )+
в начало правила expression
:
expression
: expression ( ',' expression )+ #multipleExpression
| ...
;
После добавления правила выше:
grammar SimpleBoolean;
parse
: expression EOF
;
expression
: expression ( ',' expression )+ #multipleExpression
| LPAREN expression RPAREN #parenExpression
| NOT expression #notExpression
| left=expression op=comparator right=expression #comparatorExpression
| left=expression op=binary right=expression #binaryExpression
| bool #boolExpression
| IDENTIFIER #identifierExpression
| DECIMAL #decimalExpression
;
comparator
: GT | GE | LT | LE | EQ | NE | IN | NOTIN | STARTSWITH | ENDSWITH | NULL | NOTNULL
;
binary
: AND | OR
;
bool
: TRUE | FALSE
;
AND : 'AND' ;
OR : 'OR' ;
NOT : 'NOT';
TRUE : 'TRUE' ;
FALSE : 'FALSE' ;
GT : '>' ;
GE : '>=' ;
LT : '<' ;
LE : '<=' ;
EQ : '=' ;
NE : '!=' ;
IN : 'IN' ;
NOTIN : 'NOTIN' ;
STARTSWITH : 'STARTSWITH' ;
ENDSWITH : 'ENDSWITH' ;
NULL : 'NULL' ;
NOTNULL : 'NOTNULL' ;
LPAREN : '(' ;
RPAREN : ')' ;
DECIMAL : '-'? [0-9]+ ( '.' [0-9]+ )? ;
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]* ;
WS : [ \r\t\u000C\n]+ -> skip;
входные данные вашего примера 9355560 = 9355560 AND NOT ( comments = comments AND system IN system,admin,developer )
анализируются следующим образом (без ошибок!):
спасибо за Ваш ответ. Я все еще получаю исключение «ошибка (122): Filter.g4:7:0: выражение правила: необходимо пометить все альтернативы или ничего». Кстати, я хотел бы передать и другие специальные символы, поскольку пользовательский ввод и любые значения могут содержать специальные символы. Смогу ли я предоставить грамматику для принятия специальных символов в любом месте данного выражения?
Тогда вы не сделали так, как я предложил :)
Я добавил тот же оператор, о котором вы упомянули, но каким-то образом он выдал исключение. Теперь все работает нормально :)
Вы забыли добавить #multipleExpression
в конце альтернативы (что я и предложил вам сделать). Если теперь это работает, возможно, вы только что добавили его. Ошибка не могла исчезнуть чудесным образом :)
Попробуйте поставить '\' (обратную косую черту) перед специальным символом.