如何针对给定语法删除bison的shift-reduce冲突?
selection-stmt -> if ( expression ) statement |
if ( expression ) statement else statement
提供修改过的语法的解决方案将受到高度赞赏。
答案 0 :(得分:37)
有一个更简单的解决方案。如果你知道LR解析器是如何工作的,那么你知道冲突发生在这里:
if ( expression ) statement * else statement
其中星号标记光标的当前位置。解析器必须回答的问题是“我应该转移,还是应该减少”。通常,您希望将else
绑定到最近的if
,这意味着您现在要转移else
令牌。现在减少意味着您希望else
等待绑定到“较旧”if
。
现在,您想“告诉”您的解析器生成器“当令牌"else"
与规则”stm - >之间存在转换/减少冲突时if(exp)stm“,那么令牌必须赢”。为此,请为您的规则优先级“命名”(例如"then"
),并指定"then"
的优先级低于"else"
。类似的东西:
// Precedences go increasing, so "then" < "else".
%nonassoc "then"
%nonassoc "else"
%%
stm: "if" "(" exp ")" stm %prec "then"
| "if" "(" exp ")" stm "else" stm
使用Bison语法。
实际上,我最喜欢的答案是赋予"then"
和"else"
相同的优先权。当优先级相等时,为了打破想要转移的令牌和想要减少的规则之间的联系,Bison / Yacc将查看关联性。在这里,你想要促进权利相关性(更准确地说,你想促进“转变”),所以:
%right "then" "else" // Same precedence, but "shift" wins.
就足够了。
答案 1 :(得分:6)
你需要认识到if-else案例中的中间statement
不能(或以其结尾)悬挂if(如果没有其他的话)。最简单的方法是拆分stmt
规则为两个:
stmt -> stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if
stmt-not-ending-with-dangling-if ->
if ( expression ) stmt-not-ending-with-dangling-if else stmt-not-ending-with-dangling-if |
...other statements not ending with dangling if...
stmt-ending-with-dangling-if ->
if ( expression ) stmt |
if ( expression ) stmt-not-ending-with-dangling-if else stmt-ending-with-dangling-if |
...other statements ending with dangling if...
其他stmt -> whatever
规则whatever
未以stmt
结尾的内容符合stmt-not-ending-with-if
规则,而任何stmt
规则均以stmt
结尾not-ending-with-if
分为两个版本; not-ending-with-if
规则中的dangling-if
版本和dangling-if
规则中的stmt : stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if
stmt-not-ending-with-dangling-if :
IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-not-ending-with-dangling-if |
WHILE '(' expr ')' stmt-not-ending-with-dangling-if |
DO stmt WHILE '(' expr ')' ';' |
expr ';' |
'{' stmt-list '}'
stmt-ending-with-dangling-if:
IF '(' expr ')' stmt |
IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-ending-with-dangling-if |
WHILE '(' expr ')' stmt-ending-with-dangling-if
版本。
修改强>
与其他作品更完整的语法:
WHILE (expr) stmt
stmt
之类的规则会被分成两部分(因为它们以expr;
结尾),而像{{1}}这样的规则却没有。{/ p>
答案 2 :(得分:0)
使if else比正常语句更高级别,例如:
statements:
statements lineEnd statement
| statements lineEnd IfStat
| statements lineEnd IfElseStat
| IfStat
| IfElseStat
;
IfStat:
if ( statement )
;
IfElse:
IfStat else statement
;