如何在Flex中扫描字符串,然后在bison中解析它

如何在Flex中扫描字符串,然后在bison中解析它,bison,flex-lexer,Bison,Flex Lexer,我试图解析一个类似“x=1;”的语句使用flex和bison。为此,我创建了一个符号表来存储“x”及其值1。因此,下次当解析器看到类似“x=2;”的语句时它会将符号表中x的值更新为2。 现在,我的bison和flex代码可以很好地处理单字母变量(例如:x、y、a、b、c等)。但是,当我尝试使用字符串(不止一个字符)作为变量时,程序会抛出一个分段错误。我不清楚到底哪里出了问题,哪里出了问题。下面是引发Seg故障的代码 这是flex.l文件: %{ #include <stdio.h>

我试图解析一个类似“x=1;”的语句使用flex和bison。为此,我创建了一个符号表来存储“x”及其值1。因此,下次当解析器看到类似“x=2;”的语句时它会将符号表中x的值更新为2。 现在,我的bison和flex代码可以很好地处理单字母变量(例如:x、y、a、b、c等)。但是,当我尝试使用字符串(不止一个字符)作为变量时,程序会抛出一个分段错误。我不清楚到底哪里出了问题,哪里出了问题。下面是引发Seg故障的代码

这是flex.l文件:

%{
#include <stdio.h>
#include "calc.tab.h"
%}

digit   ([0-9])
id      ([a-z])



%%

"print"       {       return(TOK_PRINTLN);}

"prints"    { return(TOK_PRINTSTR);}

"main()"    {return(TOK_MAIN);}
"{"         {return(TOK_LBRACE);}
"}"         {return(TOK_RBRACE);}

{digit}+    {
        sscanf(yytext, "%d", &yylval);
        return TOK_NUM;
        }
"("     { return(TOK_LPARAN);}
")"     { return(TOK_RPARAN);}
";" {   return(TOK_SEMICOLON);  }

"+" {   return(TOK_ADD);    }
"+="    {   return(TOK_ADDEQ);  }
"-" {   return(TOK_SUB);    }
"-="    {   return(TOK_SUBEQ);  }
"=" {   return(TOK_EQUAL);  }
{id}+   {
    sscanf(yylval.character,"%s",strdup(yytext));
    return (TOK_ID);
}
[ \n]   {}

.   {printf("Invalid character '%c', ignored\n", 
            yytext[0]);
            printf("Line Number %d\n", yylineno);
    }

%%
%{
#包括
#包括“计算表h”
%}
数字([0-9])
id([a-z])
%%
“打印”{return(TOK_PRINTLN);}
“prints”{return(TOK_PRINTSTR);}
“main()”{return(TOK_main);}
“{return(TOK_LBRACE);}
{return(TOK_RBRACE);}
{数字}+{
sscanf(yytext、%d、&yylval);
返回TOK_NUM;
}
“({return(TOK_LPARAN);}
“{return(TOK_RPARAN);}”
“;”{返回(TOK_分号);}
“+”{return(TOK_ADD);}
“+=”{return(TOK_ADDEQ);}
“-”{return(TOK_SUB);}
“-=”{return(TOK_SUBEQ);}
“=”{return(TOK_EQUAL);}
{id}+{
sscanf(yylval.character,“%s”,strdup(yytext));
返回(TOK_ID);
}
[\n]{}
.   {printf(“无效字符'%c',被忽略\n”,
yytext[0]);
printf(“行号%d\n”,yylineno);
}
%%
这是bison code.y文件:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node
{
    char *sym; //changed
    int val;
    struct Node *next;
}SymTable;

SymTable *Head;

int symExists(char *c) //changed
{
    SymTable *tmp = malloc(sizeof(SymTable));
    tmp = Head;
    while(tmp != NULL)
    {
        if(!(strcmp(tmp->sym,c))) //changed
        return 1;
        tmp = tmp->next;
    }
    return 0;
}

SymTable *getNodeOf(char *c)//changed
{
    SymTable *tmp = malloc(sizeof(SymTable));
    tmp = Head;
    while(tmp != NULL)
    {
        if(!strcmp(tmp->sym,c))//changed
        return tmp;
        tmp = tmp->next;
    }
    return NULL;
}


void Insert(char *sym,int val)//changed
{
    //printf("%s\n",sym);
    //int i = getstrlen(sym);

    SymTable *tmp =(SymTable*) malloc(sizeof(SymTable));
    //printf("Here 1\n");
    //tmp->sym = (char *) malloc(50*sizeof(char));
    //printf("Here 2\n");
    /*tmp->sym=sym;*/strcpy(tmp->sym,sym);//changed
    tmp->val = val;

    if(Head == NULL)
    {
        tmp->next = NULL;
        Head = tmp;
    }
    else
    {
        if(symExists(sym))//changed
        {
            tmp = getNodeOf(sym);//changed
            tmp->val = val;
        }
        else
        {
            tmp->next = Head;
            Head = tmp;
        }
    }
    fprintf(stdout,"val:%d sym: %s\n",tmp->val,tmp->sym); //changed

}

int getTokIdVal(char *sym) //changed
{
    SymTable *tmp = malloc(sizeof(SymTable));
    tmp = Head;
    while(tmp!=NULL)
    {
        if(!strcmp(tmp->sym,sym)) //changed
        return tmp->val;
        tmp= tmp->next;
    }
    return 0;
}

int eval(int a,int b,char c,char *sym) //changed
{

    switch(c)
    {
        case '+':
        return a+b;
        break;
        case '-':
        return a-b;
        break;
        case 'n':
        return a;
        break;
        case '=':
        Insert(sym,a);
        break;
        case 'm':
        return -a;
        break;

    }
    return 0;
}


%}

%token TOK_SEMICOLON TOK_ADD TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_PRINTLN TOK_EQUAL TOK_PRINTSTR TOK_QUOTE TOK_LPARAN TOK_RPARAN TOK_ADDEQ TOK_SUBEQ TOK_MAIN TOK_LBRACE TOK_RBRACE

%union{
        int int_val;
        char *character;//changed
}

%token <character> TOK_ID//changed


/*%type <int_val> expr TOK_NUM*/
%type <int_val> expr TOK_NUM



%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV

%%



stmt:
    |stmt expr_stmt
;

expr_stmt:
       expr TOK_SEMICOLON
       | TOK_PRINTLN expr TOK_SEMICOLON 
        {
            fprintf(stdout, "the value is %d\n", $2);
        }

;

expr:
    expr TOK_ADD expr
      {
          $$ = eval($1,$3,'+',NULL);
      }
    | TOK_ID TOK_ADDEQ expr
      {
          $$ = eval(getTokIdVal($1),$3,'+',NULL);
          Insert($1,$$);

      }
    | expr TOK_SUB expr
      {
          $$ = eval($1,$3,'-',NULL);
      }
    | TOK_ID TOK_SUBEQ expr
      {
          $$ = eval(getTokIdVal($1),$3,'-',NULL);
          Insert($1,$$);

      }
    | TOK_NUM
      {
        $$ = eval($1,0,'n',NULL);
      }
    | TOK_ID TOK_EQUAL expr
      {
          $$ = eval($3,0,'=',$1);

      }
    | TOK_ID
      {
         $$ = getTokIdVal($1);
      }
    | TOK_LPARAN TOK_SUB expr TOK_RPARAN
     {
         $$ = eval($3,0,'m',NULL);
     }

;



%%


int yyerror(char *s)
{
    printf("%s\n", s);

    return 0;
}

int main()
{
   yyparse();

   return 0;
}
%{
#包括
#包括
#包括
定义表结点
{
char*sym;//已更改
int-val;
结构节点*下一步;
}符号表;
符号*头;
int symExists(char*c)//已更改
{
SymTable*tmp=malloc(sizeof(SymTable));
tmp=头部;
while(tmp!=NULL)
{
如果(!(strcmp(tmp->sym,c))//更改
返回1;
tmp=tmp->next;
}
返回0;
}
SymTable*getNodeOf(char*c)//已更改
{
SymTable*tmp=malloc(sizeof(SymTable));
tmp=头部;
while(tmp!=NULL)
{
如果(!strcmp(tmp->sym,c))//已更改
返回tmp;
tmp=tmp->next;
}
返回NULL;
}
void Insert(char*sym,int val)//已更改
{
//printf(“%s\n”,符号);
//int i=getstrlen(sym);
SymTable*tmp=(SymTable*)malloc(sizeof(SymTable));
//printf(“此处为1\n”);
//tmp->sym=(char*)malloc(50*sizeof(char));
//printf(“此处为2\n”);
/*tmp->sym=sym;*/strcpy(tmp->sym,sym);//已更改
tmp->val=val;
if(Head==NULL)
{
tmp->next=NULL;
水头=tmp;
}
其他的
{
如果(symExists(sym))//已更改
{
tmp=getNodeOf(sym);//已更改
tmp->val=val;
}
其他的
{
tmp->next=头部;
水头=tmp;
}
}
fprintf(标准输出,“val:%d符号:%s\n”,tmp->val,tmp->sym);//已更改
}
int getTokIdVal(char*sym)//已更改
{
SymTable*tmp=malloc(sizeof(SymTable));
tmp=头部;
while(tmp!=NULL)
{
如果(!strcmp(tmp->sym,sym))//已更改
返回tmp->val;
tmp=tmp->next;
}
返回0;
}
int eval(int a,int b,char c,char*sym)//已更改
{
开关(c)
{
格“+”:
返回a+b;
打破
案例'-':
返回a-b;
打破
案例“n”:
返回a;
打破
案例“=”:
插入(sym,a);
打破
案例“m”:
返回-a;
打破
}
返回0;
}
%}
%TOK_分号TOK_ADD TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_PRINTLN TOK_等于TOK_PRINTSTR TOK_QUOTE TOK_LPARAN TOK_RPARAN TOK_addq TOK_SUBEQ TOK_MAIN TOK_LBRACE TOK_RBRACE
%联合{
国际价值;
char*character;//已更改
}
%令牌TOK_ID//已更改
/*%类型expr TOK_NUM*/
%类型expr TOK_NUM
%左TOK_添加TOK_接头
%左托库木尔托库分区
%%
stmt:
|stmt expr\u stmt
;
出口:
expr TOK_分号
|TOK_PRINTLN expr TOK_分号
{
fprintf(标准输出,“值为%d\n”,$2);
}
;
表达式:
expr TOK_添加expr
{
$$=eval($1,$3,'+',NULL);
}
|TOK_ID TOK_ADDEQ expr
{
$$=eval(getTokIdVal($1),$3,'+',NULL);
插入($1,$);
}
|出口托库分出口
{
$$=eval($1,$3,'-',空);
}
|TOK_ID TOK_SUBEQ expr
{
$$=eval(getTokIdVal($1),$3',-',NULL);
插入($1,$);
}
|托克努姆
{
$$=eval($1,0,'n',空);
}
|TOK_ID TOK_相等表达式
{
$$=eval($3,0,'=',$1);
}
|托库ID
{
$$=getTokIdVal($1);
}
|TOK_LPARAN TOK_SUB expr TOK_RPARAN
{
$$=eval($3,0,'m',空);
}
;
%%
int yyerror(字符*s)
{
printf(“%s\n”,s);
返回0;
}
int main()
{
yyparse();
返回0;
}

符号表的链表代码完全被置乱——此代码(出现在多个位置)毫无意义:

SymTable *tmp = malloc(sizeof(SymTable));
tmp = Head;
当它为对象分配空间时,会立即覆盖返回的指针,因此内存会泄漏。在符号表中搜索时,不需要分配任何内存,
Insert
仅当符号尚未在表中时才需要分配内存。阅读C语言中关于链表的基本教程,例如

这种说法也是胡说八道:

sscanf(yylval.character,"%s",strdup(yytext));
它尝试读取尚未设置为任何值的
yylval.character
,并覆盖您试图返回的符号。你可能只想:

yylval.character = strdup(yytext);
在这里