2016-06-09 13 views
0

그래서 나는 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; 
} 

또한 여기에 내가이 목적을 위해 만든 렉스 파일입니다 :

%{ 
#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

나는 그 코드를 통해 많은 도움을받을 수 있기 때문에 그렇게하지 않았다. 그러나, 당신이 구문 적으로 유형 (정수 또는 이중)을 감지하려고 시도하는 것으로 나타났습니다. 그건 좋은 생각이 아니야. 구문 분석 후에 형식 검사를 수행하십시오. 변수가 있고 이름에서 변수의 유형을 알 수 없으므로 모호한 구문 분석으로 끝나고 r/r 충돌로보고됩니다 – rici

+1

또한 'yylval.varName = yytext;'는 정말 나쁜 생각, 그리고','에 대한 액션은'return yytext'보다는'return * yytext; '이어야합니다. 개인적으로, 다른 단일 문자 토큰 유형 (.operators 및 괄호)에 대해 해당 동작을 사용합니다. – rici

+0

그래, 그게 내가했던 것, 문법을 단순화하고 모든 숫자를 같은 방식으로 받아 들였지만 C 코드에서 부동 캐스팅. ','와 같이 지금은'return yytext [0]'로 바꿨다. 또한이 옵션을 'yylval.varName = yytext;'에서 제거하는 더 좋은 방법을 알려주시겠습니까? 왜냐하면 $ somenumber를 사용하여 들소에서 VARIABLE 변수를 선택했을 때보 다 더 많은 문자를 가져오고 이것이 가능할 수 있기 때문입니다. 방금 지적한 것 중? @rici –

답변

0

구문 분석을 단순화하여 문법을 단순화하여 구문 분석시 정수와 부동 소수점을 구별하지 않고 모든 숫자를 나중에 C 코드로 부동 상태로 변환하여 줄이기/줄이기 충돌의 주요 문제를 해결했습니다. 댓글에 @rici가 언급 한 몇 가지 근본적인 문제가 있었지만, 문제를 해결하고 위의 댓글 영역에서 설명했습니다. 그래서 여기에서 반복하지 않을 것입니다.