【问题标题】:Bison dangling else野牛在别处晃来晃去
【发布时间】:2013-04-24 13:24:10
【问题描述】:

我的语法中有以下规则:

block:                  TLBRACE statements TRBRACE
                        | TLBRACE TRBRACE
                        ;


statements:             statement 
                        | statements statement 
                        ;

statement:              TIF TLPAREN expression TRPAREN TTHEN statement
                        | TIF TLPAREN expression TRPAREN TTHEN statement TELSE statement
                        | TWHILE TLPAREN expression TRPAREN statement 
                        | TDO statement TLPAREN expression TRPAREN 
                        | TFOR TLPAREN forinits TSEMICOLON expression TSEMICOLON expressions TRPAREN statement 
                        | block 
                        | declaration TSEMICOLON
                        | expression TSEMICOLON
                        ;

我知道悬空的 else 问题。这就是我在语法文件顶部指定“%left TELSE”的原因。无论如何,即使我指示 Bison 优先使用 TELSE 令牌,也会产生移位/减少冲突。我还尝试删除“%left TELSE”命令(只是看看它是否有任何区别)并且没有任何变化。我总是有同样的移位/减少冲突。

我使用 Bison 的 --verbose 标志得到的输出是:

State 117

   32 statement: "if" "(" expression ")" "then" statement .  ["identifier", "string value", "double", "int", "lint", "message", "string", "double value", "int value", "(", "{", "}", "-", "do", "else", "for", "if", "while", "binary not"]
   33          | "if" "(" expression ")" "then" statement . "else" statement

    "else"  shift and going to state 122

    "else"    [reducing with rule 32 (statement)]
    $default  reducing with rule 32 (statement) 

【问题讨论】:

  • shift/reduce 是警告,而不是错误。
  • 如果我指定“%left TELSE”,我希望不会有 shift/reduce 冲突。没有任何地方写到某事是错误的。
  • 使用语句的产生规则是什么?看起来您可能在语法中使用了两次标记“else”。
  • 我编辑要回答的问题。

标签: if-statement compiler-construction grammar bison


【解决方案1】:

我在声明%left TTHEN 时消除了冲突。我不能给你一个完整的解释,但运算符优先级与一个接一个地比较运算符有关。

【讨论】:

  • 我认为您的答案是正确的,因为我通过摆脱 TTHEN 令牌摆脱了 shift/reduce 冲突。谢谢。
【解决方案2】:

使用%nonassoc 解决此问题的最佳方法。

%nonassoc THEN

%nonassoc ELSE

%%


statement:              TIF TLPAREN expression TRPAREN TTHEN statement %prec THEN

                        | TIF TLPAREN expression TRPAREN TTHEN statement TELSE statement


%%

这里,解析器将token压入栈中,当IF表达式被压入,下一个token为ELSE时,就会发生冲突。

解析器应根据if_statement 规则减少IF 表达式,或者将下一个ELSE 标记移入堆栈。您必须确定规则的优先级,在这种情况下,您必须通过使用%nonassoc%prec 赋予ELSE 令牌比if_statement 更高的优先级。在%nonassocELSE的优先级大于THEN,通过使用%precif_statment的优先级小于if_else_statment,冲突就解决了。

【讨论】:

  • 感谢您的回答。您能否添加一些解释,为什么这是最好的方法,它到底是做什么的?
  • 这里解析器将令牌推入堆栈,当IF expr被压入并且下一个令牌为ELSE时会发生冲突,解析器应该根据if_statement规则减少IF expr或者它应该移位下一个标记 ELSE 进入堆栈。您必须确定规则的优先级,在这种情况下,您必须使用 %nonassoc 和 %prec 为 ELSE 令牌赋予比 if_statement 更高的优先级。在 ELSE 的 %nonassoc 优先级大于 THEN 并且使用 if_statment 的 %prec 优先级小于 if_else_statment 并且不会发生冲突。
  • 谢谢!通过选择edit 将其包含在您的答案中可能不是一个坏主意。这次我给你推荐了一个。
【解决方案3】:

这是一个常见问题。查看Reforming the grammar to remove shift reduce conflict in if-then-else,它解释了冲突解决的工作原理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多