如何解决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();
}
答案 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);
。解决此问题,您可能希望在stmnt
或DO
之后只有一个ELSE
而不是stmnt_list
如果你在其他两个冲突状态下查看y.output文件,你会再次看到这个