0

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

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

任何帮助将不胜感激!

4

1 回答 1

1

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

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

[A-Za-z][A-Za-z0-9]*   {
                         yylval.symp = symlook(yytext);
                         return NAME;
                       }
于 2013-03-02T04:00:43.863 回答