Bison 改革语法以消除移位,减少if-then-else中的冲突

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

对于给定的语法,如何消除bison的shift-reduce冲突

 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
;