野牛问题与减少/减少冲突

时间:2016-06-09 00:02:38

标签: bison yacc reduce-reduce-conflict

所以我是Bison的新手,我正在尝试制作一个简单的计算器。 当我做bison -d命令时,它说有7个减少/减少冲突,我不知道为什么会这样,我知道这是因为我的语法中有一些不好的逻辑,我就是找不到它。所以这是.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",$1);}
        |   exp     NEWLINE {printf("%d\n",$1);}
        |   QUIT        NEWLINE {exit(1);}
        ;

mixExp  :   DNUM                                                NEWLINE {$$ = $1;}
            |   SIN LPAREN mixExp RPAREN                    NEWLINE {$$ = sin($3);}
            |   COS LPAREN mixExp RPAREN                    NEWLINE {$$ = cos($3);}
            |   LOG LPAREN mixExp RPAREN                    NEWLINE {$$ = log($3);}
            |   SQRT LPAREN mixExp RPAREN                   NEWLINE {$$ = sqrt($3);}
            |   POW LPAREN mixExp "," mixExp RPAREN NEWLINE {$$ = pow($3,$5);}
            |   VARIABLE                                            NEWLINE {$$ = symbolVal($1);}
            |   MINUS mixExp    %prec   UMINUS              NEWLINE {$$ = -$2:}
            |   mixExp PLUS mixExp                              NEWLINE {$$ = $1 + $3;}
            |   mixExp MINUS mixExp                         NEWLINE {$$ = $1 - $3;}
            |   mixExp MULTIPLY mixExp                      NEWLINE {$$ = $1 * $3;}
            |   mixExp DIVIDE mixExp                            NEWLINE {$$ = $1 / $3;}
            |   LPAREN mixExp RPAREN                            NEWLINE {$$ = $2;}
            |   mixExp PLUS exp                                 NEWLINE {$$ = $1 + $3;}
            |   mixExp MINUS exp                                NEWLINE {$$ = $1 - $3;}
            |   mixExp MULTIPLY exp                         NEWLINE {$$ = $1 * $3;}
            |   mixExp DIVIDE exp                               NEWLINE {$$ = $1 / $3;}
            |   exp PLUS mixExp                                 NEWLINE {$$ = $1 + $3;}
            |   exp MINUS mixExp                                NEWLINE {$$ = $1 - $3;}
            |   exp MULTIPLY mixExp                         NEWLINE {$$ = $1 * $3;}
            |   exp DIVIDE mixExp                               NEWLINE {$$ = $1 / $3;}
            ;
exp     :   INUM                                                    NEWLINE {$$=$1;}
            |   SIN LPAREN exp RPAREN                       NEWLINE {$$=sin($3);}
            |   COS LPAREN exp RPAREN                       NEWLINE {$$=cos($3);}
            |   LOG LPAREN exp RPAREN                       NEWLINE {$$=log($3);}
            |   SQRT LPAREN exp RPAREN                      NEWLINE {$$=sqrt($3);}
            |   POW LPAREN exp "," exp RPAREN               NEWLINE {$$ = pow($3,$5);}
            |   VARIABLE                                            NEWLINE {$$ = symbolVal($1);}
            |   MINUS exp   %prec   UMINUS                  NEWLINE {$$ = -$2:}
            |   exp PLUS exp                                        NEWLINE {$$ = $1 + $3;}
            |   exp MINUS exp                                   NEWLINE {$$ = $1 - $3;}
            |   exp MULTIPLY exp                                NEWLINE {$$ = $1 * $3;}
            |   exp DIVIDE exp                                  NEWLINE {$$ = $1 / $3;}
            |   LPAREN exp RPAREN                               NEWLINE {$$ = $2;}
            ;
assign  :   VARIABLE EQUALS exp                         NEWLINE {updateSymbolTableI($1,$3);}
            |   VARIABLE EQUALS mixExp                      NEWLINE {updateSymbolTableD($1,$3);}
            ;
%%
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;}

非常感谢任何建议。

1 个答案:

答案 0 :(得分:0)

我通过简化语法来解决减少/减少冲突的主要问题,只是接受所有数字而不是在解析时使用整数和浮点数来区别,而是稍后将所有数字转换为在C代码中浮动。 @rici在评论中提到了一些更基本的问题,我也修了它们并在上面的评论区域解释了它(所以我不会在这里重复)。