转变减少YACC计划中的冲突

时间:2017-10-05 13:53:15

标签: yacc shift-reduce-conflict

我已经为验证字符串w.r.t语法{ckanbm: n ≠ m ∧ k,m,n > 0}编写了这个YACC程序。 NL用于换行。并且令牌由已经存在的lex传递。但是给出了这个错误。我认为生产规则还可以,但我收到了这条消息:

[waliullah.mtcs17@cseresearch wali1]$ yacc -d assign1.y
yacc: 2 shift/reduce conflicts, 1 reduce/reduce conflict.

这是我的语法文件:

%{
#include<stdio.h>
%}
%token NL A B C
%%
stmt : C stmt
 | X NL
 | Y NL
 ;
X    : A X B
 | X B
 | B
 ;
Y    : A Y B
 | A Y
 | A
 ;
%%
int yyerror(char *msg)
{
printf("Invalid String!\n");
exit(0);
}

1 个答案:

答案 0 :(得分:2)

据我所见,你的语法准确而且毫不含糊。但它不是有限的前瞻,更不用说LR(1)。

LR(k)解析器必须能够仅根据对下一个 k 标记的检查来预测非终端完成的输入点的减少。

现在考虑输入由A代币的大量(相对于 k )组成,后跟B。如果输入最终将匹配Y,则解析器现在必须减少Y → A,然后可能减少Y → A Y的一个或多个实例,并且LR解析的从左到右的性质意味着这些减少必须立即进行。

但是没有办法知道减少了多少个实例而没有看到整个输入的其余部分并计算B的数量。此外,输入完全可能与X匹配,在这种情况下,B必须移位,因为减少到Y是不正确的。同样,在达到输入结束之前,没有足够的信息来做出这个决定。

通过将-v选项传递给yacc / bison生成的状态表中显示了这些困境。例如,我们可以看到:

State 1

    4 X: A . X B
    7 Y: A . Y B
    8  | A . Y
    9  | A .

    A  shift, and go to state 1
    B  shift, and go to state 2

    B         [reduce using rule 9 (Y)]
    $default  reduce using rule 9 (Y)

    X  go to state 7
    Y  go to state 8

表示在假设A s比Y s更多的情况下是否将最后A减少到B的问题,或者是首先B准备将其减少到X,假设B s比A更多。

(前瞻B存在两种不同的行动表明冲突。减少行动包含在括号内([reduce using rule 9 (Y)]),表明野牛通过选择总是转移来解决冲突当然,这并不总是正确的解决方案,因此您的解析器无法正确识别需要执行缩减操作的输入。)

这种语言确实有LR(1)语法。诀窍是首先识别A s和B的内部平衡序列,而不强迫解析器决定遇到哪种类型的句子。如果遇到与B不匹配的A,或者找到句子末尾但某些A尚无法匹配的情况,则可以做出该决定。

此处,ABA s和B s的平衡序列。 AAB一个或多个A后跟AB;虽然ABB是一个AB,后跟一个或多个B

stmt: tail NL
    | C tail NL
tail: AAB
    | ABB
AAB : A AB
    | A AAB
ABB : AB B
    | ABB B
AB  : /* empty */
    | A AB B

写作

很诱人
AAB : AA AB
AA  : A
    | A AA

但它不会起作用,因为它需要解析器在A看到AA之前确定B是否属于A。上面写的方式,ABB总是转移到堆栈上,并在解析器堆栈展开时做出决定。

另一方面,可以用这种方式(ABB: AB BB; BB: B | BB B)编写B的作品,因为当解析器到达第一个不匹配的{{1}}时所有相关决定都已经做出。我选择如上所述进行对称。