yacc在明确的语法上转移/减少冲突

时间:2013-10-12 14:36:35

标签: grammar yacc bnf shift-reduce-conflict

我的gramamar的一段代码让我疯狂。

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

e.g。

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

它的问题就是这样的赋值语句

ID = Expresion。

在以下引文中,您可以看到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)

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

1 个答案:

答案 0 :(得分:3)

Bison为您提供至少一个提示。在State 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的转变/减少冲突,在可能性的背景下:

  1. 完成InstanciaFuncion(缩小)

  2. 的解析
  3. 继续解析Sentencias(轮班)

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

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

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

    是的,你的语法是明确的,所以不需要消除歧义。但它不是LR(1):你只能通过查看下一个一个符号来告诉你该怎么做。但是,它是LR(2),并且有一个证据比任何LR(2)语法都有相应的LR(1)语法。 (对于任何值2 :))。但是,不幸的是,实际上进行转型并不总是非常漂亮。它可以机械地完成,但结果语法很难阅读。 (参见下面的注释以供参考。)

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

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

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


    对于证据的优秀描述,LR(1)语法可以涵盖任何LR(k)语法,包括构造技术和如何恢复原始解析树的简要描述,在Sippu&amp; Sons,Inc。 Soisalon-Soininen,Parsing Theory,Vol。 II(Springer Verlag,1990)(Amazon)。这套两卷本书对于理论家来说是一个很好的参考,并且有很多有价值的实用信息,但是它的阅读量很大,也是一项严肃的投资。如果你有一个方便的大学图书馆,应该有一个可用的副本。所提出的算法归功于MD Mickunas,并于1976年在JACM 23:17-30(paywalled)出版,您也应该能够在一个好的大学图书馆中找到它。如果做不到这一点,我在Richard Marion Schell's thesis中找到了一个非常简短的描述。

    就个人而言,我不会为此烦恼。要么使用GLR解析器,要么使用相同的技巧bison用于相同的目的。或者在上面的答案中使用简单的语法,然后在AST中使用AST;这不是很难。