在我的语法中解决转移 - 减少冲突的问题

时间:2009-05-26 12:34:11

标签: parsing grammar shift-reduce-conflict irony

我正在尝试用Irony编写一个小解析器。不幸的是,我得到了“轮班减少冲突”。语法不是我的强项,我只需要完成这一小事。这是产生错误的简化语法:

ExpressionTerm := "asd"
LogicalExpression :=
    ExpressionTerm |
    LogicalExpression "AND" LogicalExpression |
    LogicalExpression "OR" LogicalExpression

“转移 - 减少冲突”是什么意思,我该如何解决?我认为这意味着我的语法含糊不清,但我不能充分扭曲我的逻辑,看看如何。

已添加:要澄清 - “asd”只是一个文字字符串“asd”。所以我希望这个语法解析下面的表达式:

asd
asd AND asd
asd AND asd OR asd
asd OR asd AND asd OR asd

已添加2:忘了说,语法的根目录为LogicalExpression

已添加3:啊,我明白了!歧义是因为像

这样的表达
asd AND asd OR asd

可以用两种不同的方式解释:

(asd AND asd) OR asd
asd AND (asd OR asd)

但我怎么能解决这个问题?好吧,我可以把AND或OR中的一个强于另一个(我原本打算)。但是现在我看到即使只有一个操作员也会出现错误。换句话说,这也会产生相同的错误:

LogicalExpression := "asd" | LogicalExpression "OR" LogicalExpression

在这种情况下我想要这个:

asd OR asd OR asd

要解析为:

(asd OR asd) OR asd

这样做的非模糊方式是什么?

已添加4:知道了!

LogicalExpression1 := LogicalExpression1 "OR" LogicalExpression2 | LogicalExpression2
LogicalExpression2 := LogicalExpression2 "AND" LogicalExpression3 | LogicalExpression3
LogicalExpression3 := "NOT" LogicalExpression4 | LogicalExpression4
LogicalExpression4 := "asd" | "(" LogicalExpression1 ")"

这解析所有布尔表达式,运算符优先级为NOT-> AND-> OR。 “asd”可以替换为您的术语表达。

4 个答案:

答案 0 :(得分:3)

如果你只使用一个前瞻,你的语法就会模糊不清。为了说明什么是“asd”?它是ExpressionTerm还是更长期的。这是转移减少冲突。我怀疑这里也有减少冲突的冲突。

大多数LL(1)/ LALR(1)生成器将通过优先级运算符提供一些处理shift-reduce冲突的方法。大多数人也会在出现换班减少冲突时默认为最长的序列,因此通常可以忽略这些序列(经过一些审查)。 (在这种情况下,您可能需要将单个术语移到底部才能使其正常运行)。

答案 1 :(得分:1)

Shift-Reduce冲突意味着你的语法含糊不清。使用递归规则,令牌“asd”可以解释为ExpressionTermLogicalExpression的一部分,并且解析器无法确定哪一个。需要一个额外的规则来打破平局。

答案 2 :(得分:0)

在解析器方面,转换减少冲突是让你的大脑更难的事情之一。说明冲突的最简单方法是使用伪代码:

if (a) then
   if (b) then
     printf('a + b');
   else
     print('this could be a + !b or !a');

else语句可以绑定到第一个或第二个if。在模糊语法的情况下,您通常会定义一个值来表示语法中预期的减少转移警告的数量。

或者,您可以使用LL(k)或LL(*)解析器。这些类型的解析器没有移位/减少歧义。根据您的应用程序,它们可能比LALR(1)解析器更容易或更难。

答案 3 :(得分:0)

语法在LL(1)LALR(1)中不明确,因为asd令牌可以在ExpressionTerm中替换,而LogicalExpression也可以压缩语法规则来解决转移/减少冲突