【发布时间】: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|<<<nothing>>>)突然都为 NEW 工作了。以前只有 x?为原创工作。
添加 EOF 测试肯定不会导致之前不成功的解析成功,不是吗?
编辑 3:编辑 2 具有误导性和无益,因此被删除
编辑 2:经过反思,将 EOF 添加到语法当然会导致先前成功的解析失败,因为输入在开始时可能格式正确,但整体格式错误(即想象解析表达式2 + 3 £$%&,开始是有效的,但总的来说它是粗鲁的)但这显然不是这里发生的事情。
【问题讨论】:
标签: antlr4