重写Bison语法以修复转换/减少冲突

时间:2013-09-14 04:28:10

标签: parsing grammar bison

以下是我的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令牌前瞻限制,但我无法弄清楚如何重写规则以解决冲突。

我的教授会因为转移/减少冲突而取消分数,所以我不能使用%expect。我的教授还说我们不能使用%left或%right优先级值。

这是我在Stack上发表的第一篇文章,所以如果我发错,请告诉我。我搜索过现有的帖子,但这看起来似乎是个案。如果我使用Stack中的任何代码,我会在提交的项目中记下源代码。

谢谢!

2 个答案:

答案 0 :(得分:4)

如上所述,你的语法含糊不清。所以它必须有冲突。

没有固有的绑定优先级规则,显然你也不允许使用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-2中,non-terminal-1无法生成x + yx * y。但在non-terminal-1 * non-terminal-2中,non-terminal-1可以生成`x + y

答案 1 :(得分:2)

谢谢!我做了更多的故障排除,并通过重写表达式运算符规则修复了减少/冲突错误:

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  
  ;

我不得不重新排列实际上是表达式的内容,实际上是因子。我制定了一个因子规则,其中包含所有具有最高优先级的因素(终端)。然后我为每个表达式制定了一个术语#规则,它也将它们设置在不同的优先级别(term5的优先级高于term4,term4的优先级高于term3,等等。)

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

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