我正在尝试解析像'x = 1;'这样的语句使用flex和bison。为此,我创建了一个符号表来存储'x'及其值1.因此,下次解析器看到类似'x = 2;'的语句时它会将符号表中x的值更新为2。 现在我的bison和flex代码适用于单字母变量(例如:x,y,a,b,c等)。但是,当我尝试将变量作为字符串(多个字符)时,程序会抛出分段错误。我不明白究竟出了什么问题,在哪里。下面是抛出Seg Fault的代码。
这是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);
}
%%
这是野牛代码.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;
}
答案 0 :(得分:1)
您的符号表的链接列表代码已完全混乱 - 此代码(显示多个位置)是无意义的:
SymTable *tmp = malloc(sizeof(SymTable));
tmp = Head;
因为它为对象分配空间,但随后立即覆盖返回的指针,因此内存泄漏。在符号表中搜索时,您不需要分配任何内存,Insert
只需要在表中尚未分配符号时进行分配。阅读C中链接列表的基本教程,例如this one
这句话也是无稽之谈:
sscanf(yylval.character,"%s",strdup(yytext));
它尝试从yylval.character
中读取尚未设置为任何内容的内容,并覆盖您尝试返回的符号。你可能只想:
yylval.character = strdup(yytext);
这里。