比较antlr生成的令牌

时间:2014-06-24 15:23:34

标签: java parsing antlr dsl antlr4

我将以下内容作为语法的一部分(此处'name''value'为了简单起见只是静态的,实际上并非如此):

test4 : 'name' CMPOP 'value';

CMPOP       :   EQUALS | NOTEQUALS;
EQUALS      :   '=';
NOTEQUALS   :   '!=';

现在,我想做的是以不同方式处理不同的CMPOP(可能通过开关)。当我在FilterListener实现中评估表达式时,有没有办法获得CMPOP(=或!=)底层的令牌的int / enum版本?我知道我可以使用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 个答案:

答案 0 :(得分:2)

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

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

cmpOp
  : EQUALS
  | NOTEQUALS
  ;

优点:

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

选项2:删除CMPOP规则,并在解析器规则中内联

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

优点:

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