Java 比较antlr生成的令牌
以下是我语法的一部分(这里的Java 比较antlr生成的令牌,java,parsing,antlr,dsl,antlr4,Java,Parsing,Antlr,Dsl,Antlr4,以下是我语法的一部分(这里的'name'和'value'为简单起见是静态的,实际上不是): 现在,我想做的是以不同的方式处理不同的CMPOP(可能通过开关)。当我在FilterListener实现中计算表达式时,是否有方法获取CMPOP(=或!=)底层令牌的int/enum版本?我知道我可以使用getText()获取字符串,但是在任何地方比较字符串都可能很慢。e、 g.如果我有name=value我可以看到=TerminalNodeImpl,它有一个符号。唯一看起来相似的是type属性,但它似乎
'name'
和'value'
为简单起见是静态的,实际上不是):
现在,我想做的是以不同的方式处理不同的CMPOP(可能通过开关)。当我在FilterListener实现中计算表达式时,是否有方法获取CMPOP(=或!=)底层令牌的int/enum版本?我知道我可以使用getText()
获取字符串,但是在任何地方比较字符串都可能很慢。e、 g.如果我有name=value
我可以看到=
TerminalNodeImpl,它有一个符号。唯一看起来相似的是type
属性,但它似乎给了我CMPOP
public void exitTest4(@NotNull testParser.Test4Context ctx) {
System.out.println(ctx.CMPOP().getSymbol().toString());
int type = ctx.CMPOP().getSymbol().getType();
System.out.println(type + "," + testParser.tokenNames[type]);
}
给我:
[@1,4:4='=',<6>,1:4]
6,CMPOP
还是我走错了方向?我是否应该将其移到解析器规则而不是lexer规则,例如:'name'(等于| NOTEQUALS)'value'
我正在使用antlr4。您有两个主要选项。你可以选择最适合你的方法 选项1:将
CMPOP
更改为解析器规则,而不是lexer规则
优点:
- 易于执行更改
- 如果需要更改,
规则易于维护cmpOp
- 将
和EQUALS
作为比较运算符进行更好的概念分组NOTEQUALS
CMPOP
规则,并内联解析器规则中的集合
将当前引用CMPOP
的所有代码替换为(等于| NOTEQUALS)
优点:
- 每个比较运算符少1个解析树节点(如果这对您的情况很重要的话,内存开销会稍微减少)
getType()
。使用if(ctx.EQUALS()!=null)
检查EQUALS
(方法EQUALS()
是作为规则上下文类的一部分生成的)。我认为能够进行切换变得更加重要,尤其是随着可能值的数量增加。现在我有6个用于cmpOp,但对于其他一些代币,我有更多。如果你改为选项1,你如何得到它是否等于?解析器上下文上没有getType。
[@1,4:4='=',<6>,1:4]
6,CMPOP
switch ( ctx.CMPOP().something() ) {
EQUALS : //evaluate with = ; break
NOTEQUALS : //evaluate with != ; break
}
cmpOp
: EQUALS
| NOTEQUALS
;