为什么在ANTLR4规则中标记外部备选方案会阻止访问者/侦听器中的此规则可用?

问题描述:

对于像下面这样的规则:为什么在ANTLR4规则中标记外部备选方案会阻止访问者/侦听器中的此规则可用?

lastFormalParameter 
     :  variableModifier* unannType annotation* ELLIPSIS variableDeclaratorId #LastParamVarargs 
     |  formalParameter #LastParamBasic 
     ; 

替代品被标记(#),为什么不会生成的观众/听众包括visitLastFormalParameter/enterLastFormalParameter/exitLastFormalParameter方法用户代码重写?只有外部替代标签的方法可以被覆盖。有没有办法使工具生成缺少的方法,而不是用实际规则替换带标签的替代方法(下面)?

lastFormalParameter 
     :  lastParamVarargs 
     |  lastParamBasic 
     ; 
lastParamVarargs 
     :  variableModifier* unannType annotation* ELLIPSIS variableDeclaratorId 
     ; 
lastParamBasic 
     :  formalParameter 
     ; 

这是4.7。

another SO question解释说,4天前。这里带有标签的要点是规则上下文被每个alt的个别上下文替换。

+0

至少对我来说,这似乎是一个错误。它应该是可配置的。在当我解析的代码仅部分有效。我的情况下,父上下文将被确认(例如在解析树可视化显示),而不是替代品 - 这意味着他们的回调将永远在听者/参观者被击中,但父母的规则是,但它不能被访问。令人难以置信的令人沮丧的是,因为解析器确实能够完全识别你想要的内容,但它只是逗你玩笑,几乎嘲弄你。 – predi

+0

无论规则alt是否被标记,如果解析器都没有匹配,那么规则节点将不会被添加到分析树中。根本没有规则或标记的上下文访问。即使在分解规则示例中,如果'lastParamVarargs'和'lastParamBasic'规则都不匹配,那么'lastFormalParameter'规则将不匹配。解析器因此不会在解析树中生成'LastFormalParameterContext'节点 - 访问者将无法访问。 – GRosenberg

如上所述here和@ MikeLischke的链接,这是正常的。

您仍然可以查看或收听由实现一个通用的回调,并委托给一个“假”之一,如果你需要实现共同所有的替代功能删除的规则。

例如,在一个游客,你会覆盖visit(ParseTree),它被调用为每个规则,然后检查它是否代表了目标父规则。它仍然是分析树的一部分,但作为实际命中的规则的超类(标记的替代方法之一)。

@Override 
public Object visit(ParseTree tree) { 
    if (tree instanceof LastFormalParameterContext) { 
     return visitLastFormalParameterContext((LastFormalParameterContext) tree); 
    } 
    return super.visit(tree); 
} 

private Object visitLastFormalParameterContext(LastFormalParameterContext ctx) { 
    // ... 
    return null; 
} 

在一个倾听者,你有enterEveryRule(ParserRuleContext)exitEveryRule(ParserRuleContext)在您的处置,以达到相同的。