【问题标题】:segmentation fault in my code in bison-generated parser野牛生成的解析器中我的代码中的分段错误
【发布时间】:2013-03-02 03:46:19
【问题描述】:

我正在尝试构建一个可以进行逐位运算的计算器。我的代码可以正确编译。但是当我运行它并输入任何值时,就会发生分段错误。我想知道你是否可以帮助我。

.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;
}

任何帮助将不胜感激!

【问题讨论】:

  • 你做了什么调试?
  • 除非 symlook() 返回指向新分配内存的指针(不是函数中的局部变量!)这可能会崩溃。仅查看程序的某些部分对调试没有帮助。找出它在哪里崩溃,以及为什么

标签: segmentation-fault bison flex-lexer


【解决方案1】:

您已将令牌 NAME 声明为具有 symp 类型,但在您的 flex 文件中,当您返回 NAME 时,您正在设置 yylval-&gt;dval。您在 sp 中创建了一个 symb 指针(我猜),但您从未将其分配给 yylval-&gt;sp

使用dval 既作为symbol 数据成员又作为yylval 的标签,您可能会感到困惑。 (至少,你那样混淆了我)。无论如何,我建议:

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

【讨论】:

  • 感谢您的帮助。实际上,此代码是基于其他代码构建的。在该代码中,这部分是 [A-Za-z][A-Za-z0-9]* { struct symtab *sp = symlook(yytext); yylval.symp = sp;返回名称;并且在原始 .c 文件中,其中一条规则是 expression:NAME { $$ = $1->value; }(%type 表达式) 首先我不太明白为什么这里返回值的类型和“表达式”的类型不同,但是原来的代码仍然有效。
  • @KuangLu:设置 yylval.symp 是正确的。设置 yylval.dval 不正确(会导致段错误)。 (在令牌被声明为symp 的情况下)。 %type 声明和 %token &lt;tag&gt; 声明实际上并不声明类型;他们在联合中声明一个标签(它具有关联的类型)。 bison 知道每个堆栈值是什么类型(标签),但 flex 不知道;所以flex 动作需要指定正确的联合成员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多