【问题标题】:Rewriting Bison grammar to fix shift/reduce conflicts重写 Bison 语法以修复移位/减少冲突
【发布时间】:2013-09-14 04:28:10
【问题描述】:

以下是我的 Bison 语法规则的相关部分:

statement:
  expression ';' |
  IF expression THEN statement ELSE statement END_IF ';' 
  ;

expression:
  IDENTIFIER |
  IDENTIFIER '('expressions')' |
  LIT_INT |
  LIT_REAL |
  BOOL_OP |
  LOG_NOT expression |
  expression operator expression |
  '('expression')'
  ;

expressions:
  expression |
  expressions ',' expression  
  ;

operator: 
  REL_OP |
  ADD_OP |
  MULT_OP |
  LOG_OR  |
  LOG_AND
  ;

编译时,我遇到 10 个移位/减少冲突:

5 个冲突是由 LOG_NOT 表达式 规则引起的:

State 45

   25 expression: LOG_NOT expression .
   26           | expression . operator expression

    REL_OP   shift, and go to state 48
    ADD_OP   shift, and go to state 49
    MULT_OP  shift, and go to state 50
    LOG_OR   shift, and go to state 51
    LOG_AND  shift, and go to state 52

    REL_OP    [reduce using rule 25 (expression)]
    ADD_OP    [reduce using rule 25 (expression)]
    MULT_OP   [reduce using rule 25 (expression)]
    LOG_OR    [reduce using rule 25 (expression)]
    LOG_AND   [reduce using rule 25 (expression)]
    $default  reduce using rule 25 (expression)

    operator  go to state 54

5个冲突是由表达式运算符表达式规则引起的:

State 62

   26 expression: expression . operator expression
   26           | expression operator expression .

    REL_OP   shift, and go to state 48
    ADD_OP   shift, and go to state 49
    MULT_OP  shift, and go to state 50
    LOG_OR   shift, and go to state 51
    LOG_AND  shift, and go to state 52

    REL_OP    [reduce using rule 26 (expression)]
    ADD_OP    [reduce using rule 26 (expression)]
    MULT_OP   [reduce using rule 26 (expression)]
    LOG_OR    [reduce using rule 26 (expression)]
    LOG_AND   [reduce using rule 26 (expression)]
    $default  reduce using rule 26 (expression)

    operator  go to state 54

我知道问题与优先级有关。例如,如果表达式是:

a + b * c

Bison 是在 a + 之后移动并希望找到一个表达式,还是将 a 简化为一个表达式?我感觉这是由于 Bison 1-token 前瞻限制造成的,但我不知道如何重写规则来解决冲突。

我的教授会因班次/减少冲突而扣分,所以我不能使用 %expect。我的教授还说我们不能使用 %left 或 %right 优先级值。

这是我在 Stack 上的第一篇文章,所以如果我发布的都是错误的,请告诉我。我已经搜索了现有的帖子,但这似乎是一个个案。如果我使用 Stack 中的任何代码,我会在我提交的项目中注明源代码。

谢谢!

【问题讨论】:

    标签: parsing grammar bison


    【解决方案1】:

    正如所写,你的语法是模棱两可的。所以肯定有冲突。

    没有绑定优先级的内在规则,显然你也不允许使用 bison 的优先级声明。如果允许,您将无法将operator 用作非终端,因为您需要区分

    expr1 + expr2 * expr3             expr1 * expr2 + expr3
      |       |       |                 |       |       |
      |       +---+---+                 +---+---+       |
      |           |                         |           |
      |          expr                      expr         |
      |           |                         |           |
      +-----+-----+                         +-----+-----+         
            |                                     |
           expr                                  expr
    

    如果将+* 替换为operator,您将无法区分它们。终端实际上​​必须是可见的。

    现在,这里有一个快速的线索:

    expr1 + expr2 + expr3    reduces expr1 + expr2 first
    expr1 * expr2 + expr3    reduces expr1 * expr2 first
    

    所以在non-terminal-1 + non-terminal-2non-terminal-1 不能产生x + yx * y。但是在non-terminal-1 * non-terminal-2non-terminal-1 可以产生`x + y

    【讨论】:

    • 谢谢!我在想我可以通过更改其中一个标记来解决问题,但我现在意识到表达式语法的整个结构导致了冲突。我想我可能已经解决了这些冲突。
    【解决方案2】:

    谢谢!我进行了更多故障排除,并通过重写 expressionoperator 规则修复了减少/冲突错误:

    expression:
      expression LOG_OR term1 |
      term1
      ;
    
    term1:
      term1 LOG_AND term2 |
      term2
      ;
    
    term2:
      term2 REL_OP term3 |
      term3
      ;
    
    term3:
      term3 ADD_OP term4 |
      term4
      ;
    
    term4:
      term4 MULT_OP factor |
      factor
      ;
    
    factor:
      IDENTIFIER |
      IDENTIFIER '('expressions')' |
      LIT_INT |
      LIT_REAL |
      BOOL_OP |
      LOG_NOT factor |
      '('expression')'
      ;
    
    expressions:
      expression |
      expressions ',' expression  
      ;
    

    我不得不重新安排什么是真正的表达式和什么是真正的因素。我制定了一个 factor 规则,其中包括所有具有最高优先级的因素(终端)。然后,我为每个表达式制定了 term# 规则,该规则还将它们设置为不同的优先级(term5 的优先级高于 term4,term4 的优先级高于 term3,等等)。

    这允许我在不使用任何内置 % 优先级函数的情况下将每个运算符设置为不同的优先级。

    我能够毫无错误地解析我的所有测试输入文件。对设计有什么想法吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多