野牛问题 reduce/reduce 冲突
Bison issue with reduce/reduce conflict
所以我是 Bison 的新手,我正在尝试制作一个简单的计算器。
当我执行 bison -d 命令时,它说有 7 reduce/reduce 冲突,我不太确定为什么会这样,我知道这是因为我的语法中有一些错误的逻辑,我就是找不到它。所以这是 .y 文件的代码:
%{
#include <stdio.h>
#include <stdlib.h>
#include <Math.h>
char** nizVarijabliI;
int* nizVrijednostiVarijabliI;
int* nizIinfo;
char** nizVarijabliD;
float** nizVrijednostiVarijabliD;
int* nizDinfo;
int countD = 100;
int dountI = 100;
void updateSymbolTableI(char* s,int br);
void updateSymbolTableD(char* s,float br
float symbolVal(char* s)
%}
%union{
double var1;
int var2;
char* varName;
}
%token <var1> DNUM
%token <var2> INUM
%token <varName> VARIABLE;
%token QUIT PLUS MINUS DIVIDE MULTIPLY EQUALS EXPONENTIATION SIN COS LOG POW SQRT LPAREN RPAREN NEWLINE
%right EQUALS
%left PLUS MINUS
%left DIVIDE MULTIPLY
%right EXPONENTIATION
%nonassoc UMINUS
%type <var1> mixExp
%type <var2> exp
%type <varName> assign
%start pocetak
%%
pocetak :
| pocetak line;
line : NEWLINE
| assign NEWLINE {;}
| mixExp NEWLINE {printf("%f\n",);}
| exp NEWLINE {printf("%d\n",);}
| QUIT NEWLINE {exit(1);}
;
mixExp : DNUM NEWLINE {$$ = ;}
| SIN LPAREN mixExp RPAREN NEWLINE {$$ = sin();}
| COS LPAREN mixExp RPAREN NEWLINE {$$ = cos();}
| LOG LPAREN mixExp RPAREN NEWLINE {$$ = log();}
| SQRT LPAREN mixExp RPAREN NEWLINE {$$ = sqrt();}
| POW LPAREN mixExp "," mixExp RPAREN NEWLINE {$$ = pow(,);}
| VARIABLE NEWLINE {$$ = symbolVal();}
| MINUS mixExp %prec UMINUS NEWLINE {$$ = -:}
| mixExp PLUS mixExp NEWLINE {$$ = + ;}
| mixExp MINUS mixExp NEWLINE {$$ = - ;}
| mixExp MULTIPLY mixExp NEWLINE {$$ = * ;}
| mixExp DIVIDE mixExp NEWLINE {$$ = / ;}
| LPAREN mixExp RPAREN NEWLINE {$$ = ;}
| mixExp PLUS exp NEWLINE {$$ = + ;}
| mixExp MINUS exp NEWLINE {$$ = - ;}
| mixExp MULTIPLY exp NEWLINE {$$ = * ;}
| mixExp DIVIDE exp NEWLINE {$$ = / ;}
| exp PLUS mixExp NEWLINE {$$ = + ;}
| exp MINUS mixExp NEWLINE {$$ = - ;}
| exp MULTIPLY mixExp NEWLINE {$$ = * ;}
| exp DIVIDE mixExp NEWLINE {$$ = / ;}
;
exp : INUM NEWLINE {$$=;}
| SIN LPAREN exp RPAREN NEWLINE {$$=sin();}
| COS LPAREN exp RPAREN NEWLINE {$$=cos();}
| LOG LPAREN exp RPAREN NEWLINE {$$=log();}
| SQRT LPAREN exp RPAREN NEWLINE {$$=sqrt();}
| POW LPAREN exp "," exp RPAREN NEWLINE {$$ = pow(,);}
| VARIABLE NEWLINE {$$ = symbolVal();}
| MINUS exp %prec UMINUS NEWLINE {$$ = -:}
| exp PLUS exp NEWLINE {$$ = + ;}
| exp MINUS exp NEWLINE {$$ = - ;}
| exp MULTIPLY exp NEWLINE {$$ = * ;}
| exp DIVIDE exp NEWLINE {$$ = / ;}
| LPAREN exp RPAREN NEWLINE {$$ = ;}
;
assign : VARIABLE EQUALS exp NEWLINE {updateSymbolTableI(,);}
| VARIABLE EQUALS mixExp NEWLINE {updateSymbolTableD(,);}
;
%%
int main() {
int i;
nizVrijednostiVarijabliI = malloc(100*sizeof(int));
nizVrijednostiVarijabliD = malloc(100*sizeof(float));
nizIinfo = malloc(100*sizeof(int));
nizDinfo = malloc(100*sizeof(int));
for(i=0;i<100;i++) {nizIinfo[i] = 0; nizDinfo[i] = 0;}
nizVarijabliI = malloc(100*sizeof(char*));
for(i=0;i<100;i++) nizVarijabliI[i] = malloc(100*sizeof(char));
nizVarijabliD = malloc(100*sizeof(char*));
for(i=0;i<100;i++) nizVarijabliD[i] = malloc(100*sizeof(char));
yyparse();
return;
}
void updateSymbolTableI(char* s,int br)
{
int freeInd = -1;
int i;
for(i=0;i<countI;i++)
{
if(nizIinfo[i] == 0)
{
freeInd = i;
break;
}
}
if(freeInd == -1)
{
freeInd = i;
countI = countI * 2;
nizVrijednostiVarijabliI = realloc(nizVrijednostiVarijabliI,count*sizeof(int));
nizIinfo = realloc(nizIinfo,count*sizeof(int));
nizVarijabliI = realloc(nizVarijabliI,count*sizeof(char*));
}
nizVrijednostiVarijabliI[freeInd] = br;
nizIinfo[freeInd] = 1;
nizVarijabliI[freeInd] = s;
}
void updateSymbolTableD(char* s, float br)
{
int freeInd = -1;
int i;
for(i=0;i<countD;i++)
{
if(nizDinfo[i] == 0)
{
freeInd = i;
break;
}
}
if(freeInd == -1)
{
freeInd = i;
countD = countD * 2;
nizVrijednostiVarijabliD = realloc(nizVrijednostiVarijabliD,count*sizeof(float));
nizDinfo = realloc(nizDinfo,count*sizeof(int));
nizVarijabliD = realloc(nizVarijabliD,count*sizeof(char*));
}
nizVrijednostiVarijabliD[freeInd] = br;
nizDinfo[freeInd] = 1;
nizVarijabliD[freeInd] = s;
}
float symbolVal(char* s)
{
int ind = -1;
int i;
for(i=0;i<countI;i++)
{
if(strcmp(s,nizVarijabliI[i]) == 0)
{
ind = i;
return (float)nizVrijednostiVarijabliI[ind];
}
}
if(ind == -1)
{
for(i=0;i<countD;i++)
{
if(strcmp(s,nizVarijabliD[i]) == 0)
{
ind = i;
return nizVrijednostiVarijabliD[ind];
}
}
}
if(ind == -1) return 0;
}
还有我为此制作的 lex 文件:
%{
#include "ultcalc.tab.h";
%}
%%
"quit" {return QUIT;}
"sin" {return SIN;}
"cos" {return COS;}
"pow" {return EXPONENTIATION;}
"log" {return LOG;}
"sqrt" {return SQRT;}
[0-9]+"."[0-9]+ {yylval.var1 = atof(yytext); return DNUM;}
[a-z][a-zA-Z0-9]* {yylval.varName = yytext; return VARIABLE;}
[0-9]+ {yylval.var2 = atoi(yytext); return INUM;}
"=" {return EQUALS;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULTIPLY;}
"/" {return DIVIDE;}
"(" {return LPAREN;}
")" {return RPAREN;}
"," {return yytext;}
[ \t] {;}
[\n] {return NEWLINE;}
. {yyerror("Neocekivani karakteri!");}
%%
yywrap() {return 1;}
如有任何建议,我们将不胜感激。
我通过简化语法以仅接受所有数字而不在解析时区分整数和浮点数来修复 reduce/reduce 冲突的主要问题,而我稍后将所有数字转换为浮点数在 C 代码中.
@rici在评论中提到了一些更底层的问题,我也修复了它们并在上面的评论区中解释了(所以我不再重复)。
所以我是 Bison 的新手,我正在尝试制作一个简单的计算器。 当我执行 bison -d 命令时,它说有 7 reduce/reduce 冲突,我不太确定为什么会这样,我知道这是因为我的语法中有一些错误的逻辑,我就是找不到它。所以这是 .y 文件的代码:
%{
#include <stdio.h>
#include <stdlib.h>
#include <Math.h>
char** nizVarijabliI;
int* nizVrijednostiVarijabliI;
int* nizIinfo;
char** nizVarijabliD;
float** nizVrijednostiVarijabliD;
int* nizDinfo;
int countD = 100;
int dountI = 100;
void updateSymbolTableI(char* s,int br);
void updateSymbolTableD(char* s,float br
float symbolVal(char* s)
%}
%union{
double var1;
int var2;
char* varName;
}
%token <var1> DNUM
%token <var2> INUM
%token <varName> VARIABLE;
%token QUIT PLUS MINUS DIVIDE MULTIPLY EQUALS EXPONENTIATION SIN COS LOG POW SQRT LPAREN RPAREN NEWLINE
%right EQUALS
%left PLUS MINUS
%left DIVIDE MULTIPLY
%right EXPONENTIATION
%nonassoc UMINUS
%type <var1> mixExp
%type <var2> exp
%type <varName> assign
%start pocetak
%%
pocetak :
| pocetak line;
line : NEWLINE
| assign NEWLINE {;}
| mixExp NEWLINE {printf("%f\n",);}
| exp NEWLINE {printf("%d\n",);}
| QUIT NEWLINE {exit(1);}
;
mixExp : DNUM NEWLINE {$$ = ;}
| SIN LPAREN mixExp RPAREN NEWLINE {$$ = sin();}
| COS LPAREN mixExp RPAREN NEWLINE {$$ = cos();}
| LOG LPAREN mixExp RPAREN NEWLINE {$$ = log();}
| SQRT LPAREN mixExp RPAREN NEWLINE {$$ = sqrt();}
| POW LPAREN mixExp "," mixExp RPAREN NEWLINE {$$ = pow(,);}
| VARIABLE NEWLINE {$$ = symbolVal();}
| MINUS mixExp %prec UMINUS NEWLINE {$$ = -:}
| mixExp PLUS mixExp NEWLINE {$$ = + ;}
| mixExp MINUS mixExp NEWLINE {$$ = - ;}
| mixExp MULTIPLY mixExp NEWLINE {$$ = * ;}
| mixExp DIVIDE mixExp NEWLINE {$$ = / ;}
| LPAREN mixExp RPAREN NEWLINE {$$ = ;}
| mixExp PLUS exp NEWLINE {$$ = + ;}
| mixExp MINUS exp NEWLINE {$$ = - ;}
| mixExp MULTIPLY exp NEWLINE {$$ = * ;}
| mixExp DIVIDE exp NEWLINE {$$ = / ;}
| exp PLUS mixExp NEWLINE {$$ = + ;}
| exp MINUS mixExp NEWLINE {$$ = - ;}
| exp MULTIPLY mixExp NEWLINE {$$ = * ;}
| exp DIVIDE mixExp NEWLINE {$$ = / ;}
;
exp : INUM NEWLINE {$$=;}
| SIN LPAREN exp RPAREN NEWLINE {$$=sin();}
| COS LPAREN exp RPAREN NEWLINE {$$=cos();}
| LOG LPAREN exp RPAREN NEWLINE {$$=log();}
| SQRT LPAREN exp RPAREN NEWLINE {$$=sqrt();}
| POW LPAREN exp "," exp RPAREN NEWLINE {$$ = pow(,);}
| VARIABLE NEWLINE {$$ = symbolVal();}
| MINUS exp %prec UMINUS NEWLINE {$$ = -:}
| exp PLUS exp NEWLINE {$$ = + ;}
| exp MINUS exp NEWLINE {$$ = - ;}
| exp MULTIPLY exp NEWLINE {$$ = * ;}
| exp DIVIDE exp NEWLINE {$$ = / ;}
| LPAREN exp RPAREN NEWLINE {$$ = ;}
;
assign : VARIABLE EQUALS exp NEWLINE {updateSymbolTableI(,);}
| VARIABLE EQUALS mixExp NEWLINE {updateSymbolTableD(,);}
;
%%
int main() {
int i;
nizVrijednostiVarijabliI = malloc(100*sizeof(int));
nizVrijednostiVarijabliD = malloc(100*sizeof(float));
nizIinfo = malloc(100*sizeof(int));
nizDinfo = malloc(100*sizeof(int));
for(i=0;i<100;i++) {nizIinfo[i] = 0; nizDinfo[i] = 0;}
nizVarijabliI = malloc(100*sizeof(char*));
for(i=0;i<100;i++) nizVarijabliI[i] = malloc(100*sizeof(char));
nizVarijabliD = malloc(100*sizeof(char*));
for(i=0;i<100;i++) nizVarijabliD[i] = malloc(100*sizeof(char));
yyparse();
return;
}
void updateSymbolTableI(char* s,int br)
{
int freeInd = -1;
int i;
for(i=0;i<countI;i++)
{
if(nizIinfo[i] == 0)
{
freeInd = i;
break;
}
}
if(freeInd == -1)
{
freeInd = i;
countI = countI * 2;
nizVrijednostiVarijabliI = realloc(nizVrijednostiVarijabliI,count*sizeof(int));
nizIinfo = realloc(nizIinfo,count*sizeof(int));
nizVarijabliI = realloc(nizVarijabliI,count*sizeof(char*));
}
nizVrijednostiVarijabliI[freeInd] = br;
nizIinfo[freeInd] = 1;
nizVarijabliI[freeInd] = s;
}
void updateSymbolTableD(char* s, float br)
{
int freeInd = -1;
int i;
for(i=0;i<countD;i++)
{
if(nizDinfo[i] == 0)
{
freeInd = i;
break;
}
}
if(freeInd == -1)
{
freeInd = i;
countD = countD * 2;
nizVrijednostiVarijabliD = realloc(nizVrijednostiVarijabliD,count*sizeof(float));
nizDinfo = realloc(nizDinfo,count*sizeof(int));
nizVarijabliD = realloc(nizVarijabliD,count*sizeof(char*));
}
nizVrijednostiVarijabliD[freeInd] = br;
nizDinfo[freeInd] = 1;
nizVarijabliD[freeInd] = s;
}
float symbolVal(char* s)
{
int ind = -1;
int i;
for(i=0;i<countI;i++)
{
if(strcmp(s,nizVarijabliI[i]) == 0)
{
ind = i;
return (float)nizVrijednostiVarijabliI[ind];
}
}
if(ind == -1)
{
for(i=0;i<countD;i++)
{
if(strcmp(s,nizVarijabliD[i]) == 0)
{
ind = i;
return nizVrijednostiVarijabliD[ind];
}
}
}
if(ind == -1) return 0;
}
还有我为此制作的 lex 文件:
%{
#include "ultcalc.tab.h";
%}
%%
"quit" {return QUIT;}
"sin" {return SIN;}
"cos" {return COS;}
"pow" {return EXPONENTIATION;}
"log" {return LOG;}
"sqrt" {return SQRT;}
[0-9]+"."[0-9]+ {yylval.var1 = atof(yytext); return DNUM;}
[a-z][a-zA-Z0-9]* {yylval.varName = yytext; return VARIABLE;}
[0-9]+ {yylval.var2 = atoi(yytext); return INUM;}
"=" {return EQUALS;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULTIPLY;}
"/" {return DIVIDE;}
"(" {return LPAREN;}
")" {return RPAREN;}
"," {return yytext;}
[ \t] {;}
[\n] {return NEWLINE;}
. {yyerror("Neocekivani karakteri!");}
%%
yywrap() {return 1;}
如有任何建议,我们将不胜感激。
我通过简化语法以仅接受所有数字而不在解析时区分整数和浮点数来修复 reduce/reduce 冲突的主要问题,而我稍后将所有数字转换为浮点数在 C 代码中. @rici在评论中提到了一些更底层的问题,我也修复了它们并在上面的评论区中解释了(所以我不再重复)。