如何修复yacc错误:(冲突:3班/减少)

时间:2011-11-22 21:26:05

标签: bison yacc

如何解决yacc错误:(冲突:3班/减少)


%{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *scat2(char *a1,char *a2) {
char *t;
t = malloc( strlen(a1) + strlen(a2) + 1 );
strcat( t, a1 );
strcat( t, a2 );
return t;
}
char *scat3(char *a1,char *a2,char *a3) {
return scat2(scat2(a1,a2),a3);
}
char *scat4(char *a1,char *a2,char *a3,char *a4) {
return scat2(scat3(a1,a2,a3),a4);
}
char *scat5(char *a1,char *a2,char *a3,char *a4,char *a5) {
return scat2(scat4(a1,a2,a3,a4),a5);
}
char *scat6(char *a1,char *a2,char *a3,char *a4,char *a5, char *a6) {
return scat2(scat5(a1,a2,a3,a4,a5),a6);
}
char *scat7(char *a1,char *a2,char *a3,char *a4,char *a5, char *a6, char *a7) {
return scat2(scat6(a1,a2,a3,a4,a5,a6),a7);
}
%}
%union {
char *name;
}
%start program
%token ASSIGN NEG IF THEN ELSE TRUE FALSE EQ AND LE WHILE DO SKIP
%token <name> ID INTdenotation
%type <name> stmnt_list stmnt a_expr b_expr b_exp
%type <name> sum term primary
%%
program : stmnt_list
{ printf("%s\n", $1); }
;
stmnt_list : stmnt
{ $$ = $1; }
| stmnt_list ';' stmnt
{ $$ = scat5("Comp (",$1,") (",$3,")"); }
| '(' stmnt_list ')'
{ $$ = $2; }
;
stmnt : SKIP
{ $$ = "Skip"; }
| IF b_expr THEN stmnt_list ELSE stmnt_list
{ $$ = scat7("If (",$2,") (",$4,") (",$6,")"); }
| WHILE b_expr DO stmnt_list
{ $$ = scat5("While (",$2,") (",$4,")"); }
| ID ASSIGN a_expr
{ $$ = scat5("Ass \"", $1, "\" (",$3,")"); }
;
b_expr : b_expr AND b_exp
{ $$ = scat5("And (",$1,") (",$3,")"); }
| b_exp
{ $$ = $1; }
;
b_exp : TRUE
{ $$ = "TRUE"; }
| FALSE
{ $$ = "FALSE"; }
| a_expr EQ a_expr
{ $$ = scat5("Eq (",$1,") (",$3,")"); }
| a_expr LE a_expr
{ $$ = scat5("Le (",$1,") (",$3,")"); }
| NEG b_expr
{ $$ = scat3("Neg (",$2,")"); }
| '(' b_expr ')'
{ $$ = $2; }
;
a_expr : sum
{ $$ = $1; }
;
sum : term
{ $$ = $1; }
| sum '+' term
{ $$ = scat5("Add (",$1,") (",$3,")"); }
| sum '-' term
{ $$ = scat5("Sub (",$1,") (",$3,")"); }
;
term : primary
{ $$ = $1; }
| term '*' primary
{ $$ = scat5("Mult (",$1,") (",$3,")"); }
;
primary : INTdenotation
{ $$ = scat2("N ", $1); }
| ID
{ $$ = scat3("V \"", $1,"\""); }
| '(' a_expr ')'
{ $$ = $2; }
;
%%
#include "lex.yy.c"
main()
{
yyparse();
}

1 个答案:

答案 0 :(得分:4)

使用-v选项生成y.output文件,提供有关语法和冲突的更多详细信息。在你的情况下,你有三个冲突源于语法中的两个含糊不清。

首先,规则bexpr : NEG b_expr表示可以将NEG a AND b之类的输入解析为NEG ( a AND b )(NEG a) AND b。如果您想要后者,则应将NEG制作移至primary为(例如primary : NEG primary

在y.output文件中,这显示为在缩小NEG规则和转移AND规则之间的状态中的冲突,如:

state 26

    9 b_expr: b_expr . AND b_exp
   15 b_exp: NEG b_expr .

    AND  shift, and go to state 30

    AND       [reduce using rule 15 (b_exp)]
    $default  reduce using rule 15 (b_exp)

你可以看到它如何直接映射到我上面给出的例子。

其次,你的IF和WHILE规则都存在'悬空声明'问题。对于看起来像WHILE x DO a; b的输入,它无法判断两个语句是否应该在循环中,或者是否应该在循环之后(例如,这是(WHILE x DO a); b还是WHILE x DO (a; b);。解决此问题,您可能希望在stmntDO之后只有一个ELSE而不是stmnt_list

如果你在其他两个冲突状态下查看y.output文件,你会再次看到这个