Parsing 不明确的语法或产生式规则何时可以?(野牛移位/减少警告)

Parsing 不明确的语法或产生式规则何时可以?(野牛移位/减少警告),parsing,bison,shift-reduce-conflict,Parsing,Bison,Shift Reduce Conflict,当然,有很多关于解决轮班/减少错误的文档和方法。野牛文件建议正确的解决方案通常是只%期望它们并处理它 当你有这样的事情: S: S 'b' S | 't' S: S 'b' T | T T: 't' 您可以通过以下方式轻松解决这些问题: S: S 'b' S | 't' S: S 'b' T | T T: 't' 我的问题是:让语法变得模棱两可和%预期移位/减少问题更好,还是尝试调整语法以避免它们更好?我怀疑存在一种平衡,它是基于作者的需要,但我真的不知道。您可以使用运算符优先级指导冲突

当然,有很多关于解决轮班/减少错误的文档和方法。野牛文件建议正确的解决方案通常是只%期望它们并处理它

当你有这样的事情:

S: S 'b' S | 't'
S: S 'b' T | T
T: 't'
您可以通过以下方式轻松解决这些问题:

S: S 'b' S | 't'
S: S 'b' T | T
T: 't'

我的问题是:让语法变得模棱两可和%预期移位/减少问题更好,还是尝试调整语法以避免它们更好?我怀疑存在一种平衡,它是基于作者的需要,但我真的不知道。

您可以使用运算符优先级指导冲突解决。将
'b'
声明为左关联运算符或右关联运算符,您至少涵盖了这种情况


对于更复杂的模式,只要最终的解析器在所有情况下都产生正确的结果,警告就不需要太多担心。虽然如果你不能用声明得到正确的结果,你必须重写语法。

在我上学期的编译器课程中,我们使用了bison,并为pascal的一个子集构建了一个编译器

如果语言足够复杂,就会出现一些错误。只要你明白它们为什么会在那里,以及你必须做些什么来移除它们,我们发现一切都是好的。如果有什么东西,但由于行为会按我们希望的那样起作用,并且需要大量的思考和工作才能使它有价值(同时也使语法复杂化),我们就不去管它了。只需确保您完全理解错误,并将其记录在某个地方(即使是为您自己),以便您始终知道错误发生了什么


这是一个成本/收益分析,一旦事情真的涉及到了,但首先应该考虑解决它,然后真正弄清楚这项工作会是什么(如果这项工作破坏了其他工作,或使其他工作变得更困难),然后从那里开始。永远不要把它们当作普通的东西。

当我需要证明一个语法是明确的时,我倾向于先把它写成一个,然后手工将它转换成我用于项目需要的工具集的任何语法类型。根据我的经验,需要这种级别的证明是非常罕见的,尽管如此,因为我遇到的大多数移位/减少冲突都是相当琐碎的,以证明(按照示例的顺序)的正确性。

正如我读到的,你的问题是“什么时候模糊的语法或产生式规则可以?”

首先考虑你所描述的语言。允许在语言中使用模棱两可的产生式规则意味着什么

您的示例描述了一种可能包含以下表达式的语言:
tb-bt-bt

在第二个示例中解析的表达式将是
(((t)bt)bt)
,但在模糊语法中,它也可能变成
(tb(tb(tb(t)))
甚至
(tb)bt(tb)
。哪些是有效的可能取决于语言。如果
b
操作符对减法进行建模,那么它确实不应该是含糊不清的,但是如果是加法,它可能是可以的。这实际上取决于语言


第二个要考虑的问题是,当冲突解决后,最终产生的语法源文件看起来是什么样的。与其他源代码一样,语法是要被人类阅读的,其次也是计算机阅读的。更倾向于使用能够从语法中更清楚地解释解析器试图做什么的符号。也就是说,如果解析器正在执行一些可能未定义的行为,例如,函数参数在渴望语言中的求值顺序,则会使语法看起来模棱两可

嗯,是的,我的例子是故意的琐碎。另一个常见的例子是if-then-else(也称为悬挂else)。如果不改变/减少,这个问题很难解决——问题是:值得吗。但不确定它是否能改变问题。