比较antlr生成的令牌



我有以下作为我的语法的一部分(这里'name''value'只是为了简单而静态的,在实践中它们不是):

test4 : 'name' CMPOP 'value';
CMPOP       :   EQUALS | NOTEQUALS;
EQUALS      :   '=';
NOTEQUALS   :   '!=';

现在,我想做的是处理不同的cmpop不同(可能通过开关)。是否有一种方法可以获得CMPOP(=或!=)底层令牌的int/enum版本,而我正在评估FilterListener实现中的表达式?我知道我可以用getText()得到字符串,但比较字符串到处都是缓慢的。例如,如果我有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

我想做的是:

switch ( ctx.CMPOP().something() ) {
  EQUALS : //evaluate with = ; break
  NOTEQUALS : //evaluate with != ; break
}

还是我走错路了?我是否应该将其移动到解析器规则而不是词法分析器规则中,例如:'name' (EQUALS | NOTEQUALS) 'value' ?

我用的是antlr4

您有两个主要选择。你可以选择最适合你的方法。

选项1:将CMPOP更改为解析器规则而不是词法分析器规则

cmpOp
  : EQUALS
  | NOTEQUALS
  ;

优点:

  • 易于执行更改
  • 如果需要更改,可以轻松维护cmpOp规则
  • EQUALSNOTEQUALS作为比较运算符的更好的概念分组

选项2:删除CMPOP规则,并将该集内联到解析器规则

(EQUALS | NOTEQUALS)代替当前引用CMPOP的所有代码

优点:

  • 每个比较操作符减少1个解析树节点(如果对您的情况很重要,可以略微减少内存开销)

相关内容

  • 没有找到相关文章

最新更新