ANTLR:如何检测两次出现相同模式的单独"访问"

时间:2016-04-04 22:44:45

标签: python antlr visitor

我有一个简单的语法:

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

我正在使用ANTLR的Python输出,在我的Python程序中,我使用visitor(而不是监听器)来构建我的数据结构。在visitConstant中,如果我执行visitRangebox(),则会出现问题,因为它会返回所有范围框匹配项(ID之前或之后)。我需要将ID之前的rangebox匹配存储在单独的列表中,然后将它们存储在单独的列表中。如何在visitConstant中单独访问它们?

编辑:忘记提及我确实尝试了类似的事情:

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

但是我收到了这个错误:

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

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

1 个答案:

答案 0 :(得分:1)

他们不匹配,因为ANTLR将他们全部列在一起。您可以做的事情是创建仅包含rangebox的新规则。像这样:

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中,您可以在使用解析器或词法分析器规则时进行标记,这样您在访问它们时就可以更轻松地访问它们。当你有一个上下文列表时,我不确定它是否有效。如果没有,第一个解决方案应该仍然有效:)