【问题标题】:A yacc shift/reduce conflict on an unambiguous grammar明确语法上的 yacc shift/reduce 冲突
【发布时间】:2013-10-12 14:36:34
【问题描述】:

我的一段语法代码让我发疯。

我必须编写一个允许编写具有多个输入的函数的语法

例如

function
  begin
    a:
       <statments>
    b:
       <statements>
  end

问题在于像这样赋值的语句

ID = 表达式。

在下面的引用中,您可以看到 yacc 产生的输出。

  0  $accept : InstanciasFuncion $end

  1  InstanciasFuncion : InstanciasFuncion InstanciaFuncion
  2                    | InstanciaFuncion

  3  InstanciaFuncion : PuntoEntrada Sentencias

  4  PuntoEntrada : ID ':'

  5  Sentencias : Sentencias Sentencia
  6             | Sentencia

  7  Sentencia : ID '=' ID

State 0

    0 $accept: . InstanciasFuncion $end

    ID  shift, and go to state 1

    InstanciasFuncion  go to state 2
    InstanciaFuncion   go to state 3
    PuntoEntrada       go to state 4

State 1

    4 PuntoEntrada: ID . ':'

    ':'  shift, and go to state 5

State 2

    0 $accept: InstanciasFuncion . $end
    1 InstanciasFuncion: InstanciasFuncion . InstanciaFuncion

    $end  shift, and go to state 6
    ID    shift, and go to state 1

    InstanciaFuncion  go to state 7
    PuntoEntrada      go to state 4

State 3

    2 InstanciasFuncion: InstanciaFuncion .

    $default  reduce using rule 2 (InstanciasFuncion)

State 4

    3 InstanciaFuncion: PuntoEntrada . Sentencias

    ID  shift, and go to state 8

    Sentencias  go to state 9
    Sentencia   go to state 10

State 5

    4 PuntoEntrada: ID ':' .

    $default  reduce using rule 4 (PuntoEntrada)

State 6

    0 $accept: InstanciasFuncion $end .

    $default  accept

State 7

    1 InstanciasFuncion: InstanciasFuncion InstanciaFuncion .

    $default  reduce using rule 1 (InstanciasFuncion)

State 8

    7 Sentencia: ID . '=' ID

    '='  shift, and go to state 11

State 9

    3 InstanciaFuncion: PuntoEntrada Sentencias .
    5 Sentencias: Sentencias . Sentencia

    ID  shift, and go to state 8

    ID        [reduce using rule 3 (InstanciaFuncion)]
    $default  reduce using rule 3 (InstanciaFuncion)

    Sentencia  go to state 12

State 10

    6 Sentencias: Sentencia .

    $default  reduce using rule 6 (Sentencias)

State 11

    7 Sentencia: ID '=' . ID

    ID  shift, and go to state 13

State 12

    5 Sentencias: Sentencias Sentencia .

    $default  reduce using rule 5 (Sentencias)

State 13

    7 Sentencia: ID '=' ID .

    $default  reduce using rule 7 (Sentencia)

也许有人可以帮我消除这个语法的歧义

【问题讨论】:

    标签: grammar yacc bnf shift-reduce-conflict


    【解决方案1】:

    Bison 至少为您提供了一个提示。在状态 9 中,除了语法本身之外,它实际上是输出中唯一相关的部分,我们看到:

    State 9
    
        3 InstanciaFuncion: PuntoEntrada Sentencias .
        5 Sentencias: Sentencias . Sentencia
    
        ID  shift, and go to state 8
    
        ID        [reduce using rule 3 (InstanciaFuncion)]
        $default  reduce using rule 3 (InstanciaFuncion)
    
        Sentencia  go to state 12
    

    与ID 存在 shift/reduce 冲突,在以下可能性的上下文中:

    1. 完成InstanciaFuncion的解析(减少)

    2. 继续解析Sentencias (shift)

    在这两种情况下,ID 都是可能的。构建一个例子很容易。考虑以下两种情况:

    f : a = b c = d ...
    f : a = b c : d = ...
    

    我们已经完成了b 和c 是前瞻,所以我们看不到c 后面的符号。现在,我们解析完函数f了吗?还是我们应该尝试更长的句子列表?没有se sabe。 (没人知道。)

    是的,您的语法是明确的,因此不需要消除歧义。但是,这不是 LR(1):您无法仅通过查看下一个 one 符号来判断该做什么。但是,它是 LR(2),并且有一个证明比任何 LR(2) 文法都有对应的 LR(1) 文法。 (对于 2 的任何值 :) )。但是,不幸的是,实际上进行转换并不总是很漂亮。它可以机械地完成,但产生的语法可能难以阅读。 (请参阅下面的注释以获取参考。)

    在您的情况下,很容易找到等效的语法,但需要调整解析树。这是一个例子:

    InstanciasFuncion : PuntoEntrada 
                      | InstanciasFuncion PuntoEntrada
                      | InstanciasFuncion Sentencia
    
    PuntoEntrada: ID ':' Sentencia
    
    Sentencia : ID '=' ID
    

    奇怪的事实是,这种精确的移位/减少冲突是 bison 语法本身的一个特征,因为 bison 接受上面写的语法(即没有分号)。 Posix 坚持 yacc 这样做,bison 试图模仿 yacc。 Bison 本身在扫描器中解决了这个问题,而不是在语法中:它的扫描器将“ID :”识别为单个标记(即使用任意空格分隔)。这也可能是您最好的选择。


    在 Sippu & Soisalon 中,对证明的描述比任何 LR(k) 文法都可以被 LR(1) 文法覆盖,包括构造技术和如何恢复原始解析树的简要描述-Soininen,解析理论,卷。二(施普林格出版社,1990 年)(Amazon)。这套两卷本对理论家来说是一个很好的参考,并且有很多有价值的实用信息,但它的阅读量很大,也是一种严重的投资。如果你手边有一个大学图书馆,应该有一个可用的副本。提出的算法归功于 MD Mickunas,并于 1976 年在JACM 23:17-30(付费专区)上发表,您也应该能够在一个好的大学图书馆中找到它。做不到这一点,我在Richard Marion Schell's thesis 中找到了一个非常简短的描述。

    不过,就我个人而言,我不会为这一切烦恼。要么使用 GLR 解析器,要么使用野牛用于相同目的的相同技巧。或者使用上面答案中的简单语法,然后摆弄AST;真的不难。

    【讨论】:

    • +1 用于诊断。关于在哪里可以找到与 LR(2) 语法等效的 LR(1) 语法的证据的任何提示?有关如何修改此语法以避免问题的任何提示(这可能只是一般解决方案的特例)?
    • @JonathanLeffler:你的咀嚼。
    • 大嚼;咀嚼; ... 谢谢。我得去挖出我的(古董)龙书;目前距离这里好几英里。 (我不能再给你 +1 了,抱歉!)
    • 这对我有帮助。谢谢
    • @JonathanLeffler 您的回答帮助我解决轮班减少冲突,但在我的项目的下一个实例中,此解决方案可能会产生问题。这是因为现在我需要使用反向波兰表示法构造一个中间代码。所以我需要像这样存储实例函数:a: b=3 -> [a, b, 3, =, :]。对于您在此处公开的示例,我无法识别何时完成实例,因此我不知道在哪里存储“:”令牌。你能忍受我吗?
    猜你喜欢
    • 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
    相关资源
    最近更新 更多