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
    作为比较运算符进行更好的概念分组
选项2:删除
CMPOP
规则,并内联解析器规则中的集合 将当前引用
CMPOP
的所有代码替换为
(等于| NOTEQUALS)

优点:

  • 每个比较运算符少1个解析树节点(如果这对您的情况很重要的话,内存开销会稍微减少)

您认为这样做(切换到getType()而不是getText())总体上是一个好主意,还是可能很容易出错(例如跨版本)?我想知道这样做的常用方法是什么。您不需要切换到
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
  ;