【问题标题】:Why is this grammar conflicts?为什么会出现这种语法冲突?
【发布时间】:2012-08-03 20:54:44
【问题描述】:

它是用 Lemon 编译的,它是一个 LALR(1) 解析器生成器:

program ::= statement.

statement ::= ifstatement Newline.
statement ::= returnstatement Newline.

ifstatement ::= If Number A statement B.
ifstatement ::= If Number A statement B Newline Else A statement B.

returnstatement ::= Return Number.

错误信息是:

user@/tmp > lemon test.lm
test.lm:6: This rule can not be reduced.

1 parsing conflicts.

调试输出为:

State 0:
          program ::= * statement
          statement ::= * ifstatement Newline
          statement ::= * returnstatement Newline
          ifstatement ::= * If Number A statement B
          ifstatement ::= * If Number A statement B Newline Else A statement B
          returnstatement ::= * Return Number

                            If shift  10
                        Return shift  3
                       program accept
                     statement shift  13
                   ifstatement shift  12
               returnstatement shift  11

State 1:
          statement ::= * ifstatement Newline
          statement ::= * returnstatement Newline
          ifstatement ::= * If Number A statement B
          ifstatement ::= * If Number A statement B Newline Else A statement B
          ifstatement ::= If Number A statement B Newline Else A * statement B
          returnstatement ::= * Return Number

                            If shift  10
                        Return shift  3
                     statement shift  4
                   ifstatement shift  12
               returnstatement shift  11

State 2:
          statement ::= * ifstatement Newline
          statement ::= * returnstatement Newline
          ifstatement ::= * If Number A statement B
          ifstatement ::= If Number A * statement B
          ifstatement ::= * If Number A statement B Newline Else A statement B
          ifstatement ::= If Number A * statement B Newline Else A statement B
          returnstatement ::= * Return Number

                            If shift  10
                        Return shift  3
                     statement shift  8
                   ifstatement shift  12
               returnstatement shift  11

State 3:
          returnstatement ::= Return * Number

                        Number shift  14

State 4:
          ifstatement ::= If Number A statement B Newline Else A statement * B

                             B shift  15

State 5:
          ifstatement ::= If Number A statement B Newline Else * A statement B

                             A shift  1

State 6:
          ifstatement ::= If Number A statement B Newline * Else A statement B

                          Else shift  5

State 7:
      (3) ifstatement ::= If Number A statement B *
          ifstatement ::= If Number A statement B * Newline Else A statement B

                       Newline shift  6
                       Newline reduce 3   ** Parsing conflict **

State 8:
          ifstatement ::= If Number A statement * B
          ifstatement ::= If Number A statement * B Newline Else A statement B

                             B shift  7

State 9:
          ifstatement ::= If Number * A statement B
          ifstatement ::= If Number * A statement B Newline Else A statement B

                             A shift  2

State 10:
          ifstatement ::= If * Number A statement B
          ifstatement ::= If * Number A statement B Newline Else A statement B

                        Number shift  9

State 11:
          statement ::= returnstatement * Newline

                       Newline shift  16

State 12:
          statement ::= ifstatement * Newline

                       Newline shift  17

State 13:
      (0) program ::= statement *

                             $ reduce 0

State 14:
      (5) returnstatement ::= Return Number *

                     {default} reduce 5

State 15:
      (4) ifstatement ::= If Number A statement B Newline Else A statement B *

                     {default} reduce 4

State 16:
      (2) statement ::= returnstatement Newline *

                     {default} reduce 2

State 17:
      (1) statement ::= ifstatement Newline *

                     {default} reduce 1

----------------------------------------------------
Symbols:
    0: $:
    1: Newline
    2: If
    3: Number
    4: A
    5: B
    6: Else
    7: Return
    8: error:
    9: program: If Return
   10: statement: If Return
   11: ifstatement: If
   12: returnstatement: Return

【问题讨论】:

  • 在 ifstatement 和 returnstatement 规则之后添加换行符似乎有效。有人可以解释为什么需要它吗?

标签: grammar lalr lemon


【解决方案1】:

查看调试输出中的状态 7。它描述了解析器已经接受了下一组标记的情况:

    ifstatement ::= If Number A statement B *

在这种情况下,当出现换行符时,解析器可以选择以下两个选项:

  1. 记住它并切换到状态 6。这种转变由您的语法中的下一条规则规定:

    ifstatement ::= If Number A statement B Newline Else A statement B.
    
  2. 认为当前规则已完成并返回上一级规则。此归约是由您的语法中的此规则规定的:

    ifstatement ::= If Number A statement B.
    

LALR(1) 解析器在这种情况下没有其他选择会失败,因为它无法提前查看流中的下一个标记。它无法预测 Else 在 Newline 之后。

修改你的语法以避免这种冲突的情况。我只能补充一点,换行符通常不包含在语言语法中。 Tokenizer 通常将它们视为类似于其他空白字符的标记边界。

【讨论】:

  • 我正在解析一种上下文相关、基于缩进的语言。该问题已通过在每个“[if/return]statement”规则的末尾添加 Newline 标记并从“statement”规则中删除 Newline 标记来解决。我不确定它为什么起作用,也不应该推断出正确的分支? ..
  • 当你在 ifstatement 规则的末尾添加换行符时,解析器可以接受所有这些标记而不会发生冲突:ifstatement ::= If Number A statement B Newline * 然后新的Else 标记使解析器继续接受第二个 ifstatement 规则,否则 @ 987654327@ 根据第一条规则减少。您可以仅将换行符移动到 if 语句规则,效果相同,而 return 语句保持不变。
猜你喜欢
  • 2021-06-21
  • 1970-01-01
  • 2019-07-16
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多