2013-03-02 31 views
0

我打算構建一個計算器,它可以執行咬合操作。我的代碼可以正確編譯。但是當我運行它並鍵入任何值時,就會發生Segementation Fault。我想知道你是否可以幫助我。我的代碼在野牛生成的解析器中的分段錯誤

.L文件

%} 

%option noyywrap 

%% 
[0-9]+ { 
      yylval.dval=atof(yytext); 
      return INTEGER; 
     } 


([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { 
               yylval.dval = atof(yytext); 
               return NUMBER; 
              } 

[ \t ] ; 



[A-Za-z][A-Za-z0-9]* { 
         struct symtab *sp = symlook(yytext); 
         yylval.dval = 0.0; 
         return NAME; 
        } 

"**" { 
    return POW; 
    } 

"<<" { 
    return LSHIFT; 
    } 

">>" { 
    return RSHIFT; 
    } 

"$"  { return 0; } 

\n | 
.  return yytext[0]; 
%% 

.h文件中

#define NSYMS 20 

struct symtab { 
    char *name; 
    double (*funcptr)(); 
    double dval; 
    enum constype {integer, floatingpoint} constype; 
} symtab[NSYMS]; 


struct symtab *symlook(); 

.Y文件

%{ 
#include "zcalc.h" 

#include <string.h> 
#include <math.h> 
#include <stdlib.h> 
#include <stdio.h> 


int flag = 0; 

void yyerror(char *mesg); /* yacc error checker */ 

%} 

%union { 
    double dval; 
    struct symtab *symp; 
} 

%token <symp> NAME 
%token <dval> NUMBER 
%token <dval> INTEGER 
%token POW 
%token LSHIFT 
%token RSHIFT 

%left '-' '+' 
%left '*' '/' 

%type <symp> expression 
%% 

statement_list: statement '\n' 
      | statement_list statement '\n' 

    statement: NAME '=' expression {$1->dval = $3->dval; 
          if($3-     >constype==integer) 
           $1-   >constype=integer; 
          else 
           $1-   >constype=floatingpoint;} 
      | expression { printf("= %g\n", $1->dval); } 

expression: '+' expression expression { $$->dval = $2->dval + $3->dval; 
            if($2->constype==integer && $3->constype) 
             $$->constype=integer; 
            else $$->constype=floatingpoint; 
            } 
     | '-' expression expression { $$->dval = $2->dval - $3->dval; 
             if($2->constype==integer && $3->constype) 
             $$->constype=integer; 
            else $$->constype=floatingpoint;} 
     | '*' expression expression { $$->dval = $2->dval * $3->dval; 
             if($2->constype==integer && $3->constype) 
             $$->constype=integer; 
            else $$->constype=floatingpoint;} 
     | '/' expression expression { $$->dval = $2->dval/$3->dval; 
             if($2->constype==integer && $3->constype) 
             $$->constype=integer; 
            else $$->constype=floatingpoint;} 
     | '(' expression ')' { $$->dval = $2->dval; 
             if($2->constype==integer) 
             $$->constype=integer; 
            else $$->constype=floatingpoint;} 
     | '&' expression expression { 
             if($2->constype!=integer||$3->constype!=integer) 
             $$->dval = (int)($2->dval) & (int)($3->dval); 
             else 
             printf("Error: bitewise operations cannot be done to floating point vals./n")} 
     | '|' expression expression { 
             if($2->constype!=integer||$3->constype!=integer) 
             $$->dval = (int)($2->dval) | (int)($3->dval); 
             else 
             printf("Error: bitewise operations cannot be done to floating point values./n")} 
     | '^' expression expression { 
             if($2->constype!=integer||$3->constype!=integer) 
             $$->dval = (int)($2->dval)^(int)($3->dval); 
             else 
             printf("Error: bitewise operations cannot be done to floating point values./n")} 
     | '~' expression { 
             if($2->constype!=integer) 
             $$->dval = ~(int)($2->dval); 
             else 
             printf("Error: bitewise operations cannot be done to floating point values./n")} 
     | LSHIFT expression expression { 
             if($2->constype!=integer||$3->constype!=integer) 
             $$->dval = (int)$2->dval << (int)$3->dval; 
             else 
             printf("Error: bitewise operations cannot be done to floating point values./n")} 
     | RSHIFT expression expression { 
             if($2->constype!=integer||$3->constype!=integer) 
             $$->dval = (int)$2->dval >> (int)$3->dval; 
             else 
             printf("Error: bitewise operations cannot be done to floating point values./n")}  
     | POW expression expression { $$->dval=pow($2->dval,$3->dval);} 
     | NUMBER {$$->dval=$<dval>1; 
       $$->constype=floatingpoint; 
       } 
     | INTEGER { 
       $$->dval=$<dval>1; 
        $$->constype=integer;} 
     | NAME { 
       $$->dval = $1->dval; 
       if($1->constype==integer) 
        $$->constype=integer; 
       else $$->constype=floatingpoint;} 
%% 

struct symtab * symlook(char *s) { 
    char *p; 
    struct symtab *sp; 

    for(sp = symtab; sp < &symtab[NSYMS]; sp++) { 
     /* is it already here? */ 
if (sp->name && !strcmp(sp->name, s)) 
    return sp; 

/* is it free */ 
if (!sp->name) { 
    sp->name = strdup(s); 
    return sp; 
} 
     /* otherwise continue to the next */ 
    } 
    yyerror("Too many symbols...\n"); 
    exit(1); 
} 

void addfunc(char *name, double (*func)()) { 
    struct symtab *sp = symlook(name); 
    sp->funcptr = func; 
} 


/* yacc error function */ 
void yyerror(char *mesg) { 
     flag = 1; 
     printf("%s \n" , mesg); 
    } 


int main() { 

    yyparse(); 

    return 0; 
} 

任何幫助將不勝感激!

+0

你做了什麼調試? – stark 2013-03-02 03:49:22

+0

除非symlook()返回一個指向新分配內存的指針(_not_不是函數中的局部變量!),否則這可能會崩潰。只是看到部分程序並沒有幫助調試。找出_where_它崩潰,_why_。 – vonbrand 2013-03-02 03:53:41

回答

1

聲明瞭令牌NAME具有類型symp但在Flex文件,當您返回NAME要設置yylval->dval。您在sp中創建了一個symb指針(我假設),但是您從未將其指定給yylval->sp

您可能會使用dval作爲symbol數據成員並將其作爲yylval的標記混淆自己。 (至少,你以這種方式困惑我)。無論如何,我會建議:

[A-Za-z][A-Za-z0-9]* { 
         yylval.symp = symlook(yytext); 
         return NAME; 
         } 
+0

感謝您的幫助。實際上,這個代碼是基於其他代碼構建的。在該代碼中,該部分是 [A-Za-z] [A-Za-z0-9] * { struct symtab * sp = symlook(yytext); yylval.symp = sp; return NAME; } 而在原始.c文件中,其中一條規則是 表達式:NAME {$$ = $ 1-> value; }(%type 表達式) 首先,我不太明白爲什麼這裏返回值的類型與「表達式」的類型不同,但原始代碼仍然有效。 – 2013-03-02 04:23:37

+1

@KuangLu:設置yylval.symp是正確的。設置yylval.dval是不正確的(並且會導致段錯誤)。 (在令牌被聲明爲'symp'的情況下)。 '%type'聲明和'%token '聲明實際上並不聲明類型;他們在union(它有一個關聯的類型)中聲明一個標籤。 'bison'知道每個堆棧值是什麼類型(標籤),但'flex'不是;所以'flex'動作需要指定正確的聯合成員。 – rici 2013-03-03 03:14:35