这个问题是关于如何在访问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+)(\\]))?");
答案 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]'
时没有可行的选择很高兴知道为什么,但至少我有一个解决方案。