ANTLR 接受特殊字符,如 .标识符或表达式中的 (dot) 和 (逗号)

ANTLR accepting special characters like . (dot) and , (comma) in identifier or expression

提问人:User1512 提问时间:9/15/2023 最后编辑:User1512 更新时间:9/20/2023 访问量:81

问:

我正在尝试使用 ANTLR 为输入数据 (Map) 执行动态表达式,并使用 stackoverflow 帖子中 @Bart Kiers 的答案,我能够做到这一点。

我尝试在语法中添加 , , 条件,并尝试从 java 端为其添加逻辑。对于函数的情况,我尝试最好使用特殊字符拆分一组字符串。但是当我将它们添加到表达式中时,出现如下错误INSTARTSWITHENDSWITH IN , (comma)

line 1:64 token recognition error at: ','

让我知道如何在表达式中允许特殊字符。

我使用的语法文件

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 )
java 解析 antlr 逻辑运 条件运算符

评论

1赞 Berc07 9/15/2023
尝试在特殊字符前添加“\”(反斜杠)。
0赞 User1512 9/15/2023
不幸的是,我无法在输入中传递反斜杠,因为它可能会影响需求:(
1赞 sepp2k 9/15/2023
在你的语法中,你试图接受逗号的什么地方?

答:

0赞 Bart Kiers 9/15/2023 #1

在规则的开头添加: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 )

enter image description here

评论

0赞 User1512 9/16/2023
谢谢你的回答。我仍然收到异常“error(122):Filter.g4:7:0:规则表达式:必须标记所有备选方案或无”。顺便说一句,我也想传递其他特殊字符,因为它的用户输入和任何值都可以包含特殊字符。我是否可以提供一种语法来接受给定表达式中任何位置的特殊字符?
0赞 Bart Kiers 9/16/2023
然后你没有按照我的建议去做:)
0赞 User1512 9/20/2023
我添加了与您提到的相同的语句,但不知何故它引发了异常。现在它工作正常:)
0赞 Bart Kiers 9/21/2023
你忘了在替代方案的末尾添加(我建议你这样做)。如果它现在有效,您可能刚刚添加了它。错误不可能奇迹般地消失:)#multipleExpression