ANTLR:如何检测两次出现的相同模式作为单独的 "visits"

ANTLR: How to detect two occurrences of same pattern as separate "visits"

我有一个简单的语法:

constant:  ptype (rangebox)* ID (rangebox)* '=' expr END ;
ptype: 'logic' | 'integer' ;
rangebox: '[' expr ':' expr ']' ;
/* expr related rules which are not relevant here */

我正在使用 ANTLR 的 Python 输出,在我的 Python 程序中,我正在使用访问者(而不是侦听器)来构建我的数据结构。在 visitConstant 中,如果我执行 visitRangebox(),这是一个问题,因为它 returns 所有范围框匹配(在 ID 之前或之后)。我需要将 ID 之前的范围框匹配项存储在一个单独的列表中,并将 ID 之后的匹配项存储在一个单独的列表中。如何在 visitConstant 中分别访问它们?

编辑:忘了说我确实尝试过类似的东西:

leftRanges = self.visit(ctx.rangebox(0))
rightRanges = self.visit(ctx.rangebox(1))

但是我得到这个错误:

AttributeError: 'NoneType' object has no attribute 'accept'

编辑:我通过先添加一个检查来修复属性错误(duh!)。但是我现在看到的是 0 或 1 不对应 ID 之前或之后。它仅表示所有范围列表中的索引。如何区分遇到 ID 之前和之后发生的范围匹配?

它们不匹配,因为 ANTLR 将它们全部放在一个列表中。您可以做的一件事是创建仅包含范围框的新规则。像这样:

constant:  ptype (left_rangebox)* ID (right_rangebox)* '=' expr END ;
ptype: 'logic' | 'integer' ;
rangebox: '[' expr ':' expr ']' ;
left_rangebox: rangebox ;
right_rangebox: rangebox ;

然后您可以通过创建 for 循环来访问它们。我不太了解 Python,但这是 Java 中的做法:

for(Left_rangeboxContext ctxt : ctx.left_rangebox){
    visit(ctxt);
}

另一个解决方案可能是使用 ANTLR 的标签。不过,我不确定这是否有效,但可能值得一试:

constant:  ptype left=(rangebox)* ID right=(rangebox)* '=' expr END ;

想法是,在 ANTLR 中,您可以在使用解析器或词法分析器规则时进行标记,因此在访问它们时可以更轻松地访问它们。当您有上下文列表时,我不确定它是否有效。如果不是,第一个解决方案应该仍然有效:)