2013-03-02 53 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