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