【问题标题】:antlr4 empty alternative not working as expectedantlr4 空替代方案未按预期工作
【发布时间】:2016-02-01 22:51:50
【问题描述】:

我认为一般来说是规则

rule: ( something ? ) ;

通常可以表示为没有任何内容的交替,具有相同的语义

rule: ( something |  ) ;   <-- empty alt here

(当然,前提是“某事”是一个单独的项目或括在括号中以使其如此)。这似乎显然是正确的,但 antlr4 没有。这段代码符合我的预期

version 1, works

opt_cursor_into_spec :
        ( cursor_into_spec ? )
    ;

cursor_into_spec :
        INTO
        sident ( COMMA sident ) *  
    ;

但这不是;无法解析输入:

version 2, fails

opt_cursor_into_spec :   // this rule's changed
        cursor_into_spec
    |
        // empty alt
    ;

cursor_into_spec :       // this is the same
        INTO
        sident ( COMMA sident ) *
    ;

这是第 2 版诊断跟踪的一部分,请注意 [***]

consume [@1,8:11='crsr',<483>,2:6] rule regular_ident
exit    regular_ident, LT(1)=<EOF>
exit    sident, LT(1)=<EOF>
exit    cic_cursor_name, LT(1)=<EOF>
exit    cursor_ident_clause, LT(1)=<EOF>
enter   opt_cursor_into_spec, LT(1)=<EOF>
line 4:0 no viable alternative at input '<EOF>'  [***]
exit    opt_cursor_into_spec, LT(1)=<EOF>
exit    fetch_statement, LT(1)=<EOF>
exit    sql_item, LT(1)=<EOF>
enter   opt_sql_separators, LT(1)=<EOF>
exit    opt_sql_separators, LT(1)=<EOF>
exit    sql_items, LT(1)=<EOF>

这很奇怪,因为在 *** 它声称没有可行的替代方案,但在它之前的那一行说它已输入 opt_cursor_into_spec,但此规则有一个空替代方案,它肯定总是匹配 - 总是可以匹配空字符串,我想?

我对这种等价的假设也是如此......

( x ? ) ===  ( x | <<<nothing>>> )

...不正确,还是什么? 这个 Q 不是关于代码,而是关于我对语义的理解。如果有人认为这些应该做同样的事情,我会尝试发布可重现的代码。



编辑:现在更困惑了。一个精简的语法没有重现。关于文件结尾的一些事情是可疑的,因为要解析的输入只是fetch a,并且根据诊断跟踪它似乎被完全解析,然后失败。唔。我在起始规则中添加了一个显式的 EOF,所以(有点简化)

sql_items : sql_item * ;  // ORIGINAL

变成了

sql_items : sql_item * EOF;  // NEW

两者(x?x|&lt;&lt;&lt;nothing&gt;&gt;&gt;)突然都为 NEW 工作了。以前只有 x?为原创工作。 添加 EOF 测试肯定不会导致之前不成功的解析成功,不是吗?



编辑 3:编辑 2 具有误导性和无益,因此被删除

编辑 2:经过反思,将 EOF 添加到语法当然会导致先前成功的解析失败,因为输入在开始时可能格式正确,但整体格式错误(即想象解析表达式2 + 3 £$%&amp;,开始是有效的,但总的来说它是粗鲁的)但这显然不是这里发生的事情。

【问题讨论】:

    标签: antlr4


    【解决方案1】:

    在版本 1 中,如果规则 cursor_into_spec 匹配,则规则 opt_cursor_into_spec 匹配。在版本 2 中,规则 opt_cursor_into_spec 将始终匹配。因此语法的语义,特别是由于具有opt_cursor_into_spec 作为元素的规则,会有所不同。

    很可能,在版本 2 中,您会收到关于可以匹配任何内容的规则的编译时警告。除非您真正了解因果关系,否则您不能忽略警告。

    【讨论】:

    • 谢谢,但我可能会误解。不幸的是,我没有发布足够清晰的代码,但是在 V1 中(以及在 V2 中), cursor_into_spec not 被使用 - 我故意使用的输入不会调用该规则。此外,您说“在 V1 中...匹配 iff 规则 cursor_into_spec 匹配”但肯定 cursor_into_spec 不需要匹配,因为 ?以下 - 它是可选的 - 不需要匹配。如果不清楚,我会发布一些代码来复制(你想要吗?)。仅供参考在 V2 中我没有收到任何错误;我不允许他们。为了清楚起见,你不同意我在底部的等价吗?
    • 等价在程序上不正确。 Antlr 不认为规则仅仅是逻辑结构。我通过规则追踪路径。如果cursor_into_spec 永远不会匹配,那么 v1 永远不会匹配; v2 将匹配,因为空 alt 将匹配而无需消耗任何东西。
    • 现在更加困惑了。要清楚“匹配”,我的意思是“解析成功/没有错误”。你说 如果 cursor_into_spec 永远不会匹配,那么 v1 永远不会匹配 - 但 v1 是成功的代码,而 v2 将匹配,因为空 alt 将匹配而无需消耗任何东西 确实,但 V2 失败了 - 请参阅我帖子中的 [***] 位。好的,我将尝试获得最少的代码来重现。
    猜你喜欢
    • 2011-12-15
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多