首页 文章

antlr4空替代方案未按预期工作

提问于
浏览
1

我一般认为这个规则

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|<<<nothing>>> )突然为NEW工作 . 以前只有x?曾为ORIGINAL工作过 . 添加EOF测试肯定不会导致以前不成功的解析成功,是吗?



编辑3:编辑2击中,因为它是误导和无益的

编辑2:在反射上向语法添加EOF当然可以导致先前成功的解析失败,因为输入可以在开始时形成良好但整体上是畸形的(即想象解析表达式2 3£$%& ,开始是有效的,但总的来说它是粗鲁的)但这显然不是这里发生的事情 .

1 回答

  • 0

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

    可能,在版本2中,您收到有关可以匹配任何内容的规则的编译时警告 . 除非您真正了解原因和结果,否则您不能忽略该警告 .

相关问题