Bison 改革语法以消除移位,减少if-then-else中的冲突
对于给定的语法,如何消除bison的shift-reduce冲突Bison 改革语法以消除移位,减少if-then-else中的冲突,bison,shift-reduce-conflict,Bison,Shift Reduce Conflict,对于给定的语法,如何消除bison的shift-reduce冲突 selection-stmt -> if ( expression ) statement | if ( expression ) statement else statement 非常感谢提供修改语法的解决方案。您需要认识到这样一个事实:if-else案例中的中间语句不能是(或以)悬挂if结尾(if没有其他)。最简单的方法是将stmt规则一分为二: stmt -> st
selection-stmt -> if ( expression ) statement |
if ( expression ) statement else statement
非常感谢提供修改语法的解决方案。您需要认识到这样一个事实:if-else案例中的中间
语句不能是(或以)悬挂if结尾(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->which
规则,其中which
不以stmt
结尾的stmt
规则将进入stmt不以if
结尾的stmt
规则,而任何以stmt
结尾的规则将分成两个版本;在不以if
结尾规则中的不以if
结尾的版本和在悬挂if
规则中的悬挂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代码>不要这样做。有一个更简单的解决方案。如果您知道LR解析器是如何工作的,那么您就知道冲突发生在这里:
if ( expression ) statement * else statement
其中,星形标记光标的当前位置。解析器必须回答的问题是“我应该移位还是减少?”。通常,您希望将else
绑定到最近的if
,这意味着您希望立即移动else
标记。现在减少将意味着您希望else
等待绑定到“较旧的”if
现在,您希望“告诉”解析器生成器“当令牌“else”
和规则“stm->if(exp)stm”之间存在移位/减少冲突时,令牌必须获胜”。为此,请为规则的优先级“指定一个名称”(例如,“然后”
),并指定“然后”
的优先级低于“其他”
。比如:
// Precedences go increasing, so "then" < "else".
%nonassoc "then"
%nonassoc "else"
%%
stm: "if" "(" exp ")" stm %prec "then"
| "if" "(" exp ")" stm "else" stm
就足够了。使if-else比正常语句的级别更高,例如:
statements:
statements lineEnd statement
| statements lineEnd IfStat
| statements lineEnd IfElseStat
| IfStat
| IfElseStat
;
IfStat:
if ( statement )
;
IfElse:
IfStat else statement
;
你能详细说明一下…其他语句吗…我没有其他使用selection stmt的产品,但我仍然收到一个错误,说使用无用的非终端这就是我所做的:selection stmt:open | closed;打开:IF LFT_BRKT表达式RGT_BRKT语句| IF LFT_BRKT表达式RGT_BRKT关闭,否则打开;关闭:如果LFT_BRKT表达式RGT_BRKT关闭,则关闭,否则关闭;完整的语法在这里,您需要去掉所有的xxx stmt
中间非终端,将所有stmt
规则组合成一个组,然后将它们拆分为悬挂/非悬挂if版本。您使用的这个stmt是什么。还有,你是从哪里来的?请查看链接中的语法,并张贴答案。Thanks@AakashAnuj:stmt
此处替换语法中的语句。删除语法中以-stmt
结尾的所有规则,并将语句
规则替换为上面的stmt
规则。如果不需要,可以删除DO
规则并添加';'返回表达式“;”|返回“;”
。对于未来的个人,帮助我解决了类似的问题。另外,将开关--debug
和--verbose
传递给bison并查看生成的文件。并不是所有的信息都打印到标准输出。如果有一个非终结符N after语句,我怎么做呢?如下所示:if_关键字'('expression N')'M语句N ELSE_关键字M语句在这里,M和N是非终结符。@VishwasJain这一切都取决于你的if-then规则。如果“else”M
部分是可选的,则应采用相同的方法。问题已解决!我认为这不能解决这个问题。
statements:
statements lineEnd statement
| statements lineEnd IfStat
| statements lineEnd IfElseStat
| IfStat
| IfElseStat
;
IfStat:
if ( statement )
;
IfElse:
IfStat else statement
;