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

时间:2016-02-01 22:51:50

标签: antlr4

我一般认为规则

rule: ( something ? ) ;

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

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

(当然提供&#39;某些东西&#39;是单个项目或括号以实现它)。这似乎显然是正确的,但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 :(得分:0)

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

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