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

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

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

例如

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)

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

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的转移/减少冲突:

>完成InstanciaFuncion的解析(减少)
>继续解析Sentencias(转变)

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

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

我们已经完成了b和c是前瞻,所以我们看不到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& 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;这并不难.

https://stackoverflow.com/questions/19335353/a-yacc-shift-reduce-conflict-on-an-unambiguous-grammar

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:yacc在明确的语法上转移/减少冲突