在访问Antlr规则时区分可选标记

时间:2013-11-16 04:37:35

标签: antlr4

这个问题是关于如何在访问antlr规则时区分可选令牌。

我有一个解析器规则,我在一个名为'assign'的antlr4语法中定义,它试图将表达式的结果分配给由INT表示的标记,例如215 =“FOO”。它还允许分配标签 index ,例如215 [2] =“FOO”。我的问题是如何通过在评估分配规则期间查看antlr提供的对象来区分形式215与形式215 [2]的INT?

assign  : INT '=' expr  ;
INT     : '-'? DIGIT+ ('[' DIGIT+ ']')?;
DIGIT   :  [0-9] ;

我已经定义了一个访问者方法来捕获解析器对令牌流的“assign”规则的评估:

215 [2] = “foo” 的

@Override
public String visitAssign(@NotNull FixRulesParser.AssignContext ctx) {
String left = ctx.getStart().getText();
String right = ctx.getStop().getText();
...

此时left =“215 [2]”和right =“FOO”

ctx对象是否提供了一种方法来确定赋值的左侧(215 [2])是否实际包含INT定义的可选“[2]”?我想区分215 [2]和215的形式的INT。我使用Java正则表达式解析'左'(见下文)来做出决定,但我想知道我是否可以直接从antlr得到答案。< / p>

Pattern p = Pattern.compile("(-?\\d+)((\\[)(\\d+)(\\]))?");

1 个答案:

答案 0 :(得分:3)

我在阅读"The Antlr Reference - Chapter 12"后找到的一个解决方案是将 Index “[2]”定义为它自己的词法分析器,并将其放在单独的通道上。

assign  : INT '=' expr  ;
INT : '-'? DIGIT+ ;
IDX : '[' DIGIT+ ']' -> channel(TAG_INDEX);
DIGIT   : [0-9] ;

然后我可以在visitAssign()中做出决定:

@Override
public String visitAssign(@NotNull FixRulesParser.AssignContext ctx) {
    BufferedTokenStream tokens = tokenStream; // passed in to the constructor as arg 
    Token t = tokens.get(1);
    int type = t.getType();
    if (type == FixRulesParser.IDX) {
        System.out.println("YES");
    } else {
        System.out.println("NO");
    }

我认为这里的教训是,如果您需要单独引用IDX,则IDX不应与任何其他令牌结合使用。

有一件事让我感到困惑的是,如果我删除了TAG_INDEX频道:

IDX : '[' DIGIT+ ']';

我得到:第1:4行在输入'215 [2]'

时没有可行的选择

很高兴知道为什么,但至少我有一个解决方案。