首页 > 解决方案 > 您如何在 Antlr4 的语法操作中引用可选规则“规则名称?”?

问题描述

TL;DR:您如何rulename?从语法操作中引用可选规则?


我试过这个,它显然失败了,因为当规则不匹配时$valueNone(null)value,并且访问 null 引用的属性会产生错误:

| NOP3 value? {print( $value.ret )}

然后我尝试了这个,但现在我得到了我无法引用 RuleContext $value本身但我必须引用它的属性之一的错误:(error(67): missing attribute access on rule reference value in $value

| NOP3 value? {print( $value.ret if $value is not None else "empty" )}

我能够使用这种肮脏的解决方法来使其工作,该解决方法注入了插入到 if 的自定义hacky代码,如果在子规则不匹配时触发其 else 子句,但它很难看,我想应该有一个更好的解决方案:

    | NOP3 value? {else:
    class obj(object):
        pass    
    localctx._value = obj()
    localctx._value.ret = None
print( $value.ret )}  

注意:$value.ret是子规则的返回值。

编辑:Bart Kiers的回答的迭代:因为如果
子规则不匹配,我 真的不需要做任何事情,我可以像这样简化它:

| NOP3 ( value {do_something()} )?  

所以基本上制作value?了一个子规则并将动作嵌入其中,而不是父规则。

标签: parsingcompiler-constructionantlrantlr4

解决方案


我认为您必须测试None这种情况:

| NOP3 value? {print("nada" if $value is None else $value.ret)}

或类似的东西:

| NOP3 v=value? {print("nada" if $v is None else $v.ret)}

甚至像这样的东西也可以工作:

| NOP3 (value {print($value.ret)} | {print("nada")})

(假设您正在嵌入 Python 代码)

但是,我强烈建议不要在语法中嵌入特定于目标的代码:最好在侦听器或访问者中完成。


推荐阅读