/**符号存储结构定义**/
typedef struct Symbol
{
int v; //符号的单词编码
int r; //符号关联的寄存器
int c; //符号关联值
Type type; //符号数据类型
struct Symbol*next; //关联的其他符号
struct Symbol*prev_tok; //指向前一定义的同名符号
}Symbol;
/**类型结构定义**/
typedef struct typedef
{
int t; //数据类型
struct Symbol *ref; //引用符号
}Type;
/**数据类型编码**/
enum e_TypeCode
{
T_INT =0, //整型
T_CHAR =1, //字符型
T_SHORT =2, //短整型
T_VOID =3, //空类型
T_PTR =4, //指针
T_FUNC =5, //函数
T_STRUCT=6, //结构体
T_BTYPE =0x000f, //基本类型掩码
T_ARRAY =0x0010, //数组
};
/**存储类型**/
enum e_StorageClass
{
SC_GLOBAL =0x00f0, //包括整型常量,字符常量,字符串常量,全局变量,函数定义
SC_LOCAL =0x00f1, //栈中变量
SC_LLOCAL =0x00f2, //寄存器溢出存放栈中
SC_CMP =0x00f3, //使用标志寄存器
SC_VALMASK =0x00ff, //存储类型掩码
SC_LVAL =0x0100, //左值
SC_SYM =0x0200, //符号
SC_ANOM =0x10000000,//匿名符号
SC_STRUCT =0x20000000,//结构体符号
SC_MEMBER =0x40000000,//结构成员变量
SC_PARAMS =0x80000000,//函数参数
};
Type char_pointer_type, //字符串指针
int_type, //int类型
default_func_type; //缺省函数类型
Stack global_sym_stack, //全局符号栈
local_sym_stack; //局部符号栈
/**符号的登录**/
/**
将符号放在符号栈里
v: 符号编号
type: 符号数据类型
c: 符号关联值
**/
Symbol *sym_direct_push(Stack*ss,int v,Type *type,int c)
{
Symbol s,*p;
s.v=v;
s.type.t=type->t;
s.type.ref=type->ref;
s.c=c;
s.next=NULL;
p=(Symbol*)stack_push(ss,&s,sizeof(Symbol));
return p;
}
/**
将符号放在符号栈中,动态判断是放入全局符号栈还是局部符号栈
v: 符号编号
type: 符号数据类型
r: 符号存储类型
c: 符号关联值
**/
Symbol *sym_push(int v,Type *type,int r,int c)
{
Symbol *ps,**pps;
TkWord *ts;
Stack *ss;
if(stack_is_empty(&local_sym_stack)==0) /**只有当局部符号栈非空的时候是局部符号栈**/
ss=&local_sym_stack;
else
ss=&global_sym_stack;
ps=sym_direct_push(ss,v,type,c);
ps->r=r;
/**不记录结构体成员及匿名符号**/
if((v&SC_STRUCT)||v<SC_ANOM) /**结构体v 是v|SC_STRUCT,结构体成员是v|SC_MEMBER,匿名符号设置为v=SC_ANOM**/
{
/**更新单词sym_struct或sym_identifier字段**/
ts=(TkWord*)tktable.data[(v&~SC_STRUCT)];/**得到在tktable中编号为v的单词**/
if(v&SC_STRUCT) /**v是结构体**/
pps=&ts->sym_struct;
else
pps=&ts->sym_identifier;
ps->prev_tok=*pps; /**更新ps的prev_tok成员**/
*pps=ps; /**结构体类型更新sym_struct 其他类型更新sym_identifier字段**/
}
return ps;
}
/**
将函数符号放入全局符号表中
v: 符号编号
type: 符号数据类型
**/
Symbol *func_sym_push(int v,Type *type)
{
Symbol *s,**ps;
s=sym_direct_push(&global_sym_stack,v,type,0);/**函数符号都是放入全局符号表**/
ps=&((TkWord*)tktable.data[v])->sym_identifier;
/**同名符号,函数符号放在最后->->...s**/
while(*ps!=NULL)
ps=&(*ps)->prev_tok;
s->prev_tok=NULL;
*ps=s;
return s;
}
/**
变量符号插入
**/
Symbol *var_sym_put(Type *type,int r,int v,int addr)
{
Symbol *sym=NULL;
if((r&SC_VALMASK)==SC_LOCAL) //局部变量,SC_VALMASK是基本类型掩码
{
sym=sym_push(v,type,r,addr);
}
else if(v&&(r&SC_VALMASK)==SC_GLOBAL) //全局变量
{
sym=sym_search(v);
if(sym) //如果标识符已经定义,就会显示重定义错误
error("%s重定义\n",((TkWord*)tktable.data[v])->spelling);
else
sym=sym_push(v,type,r|SC_SYM,0); /**SC_SYM表符号**/
}
//字符串常量符号
return sym;
}
/**
将节名称放入全局符号表
sec:节名称
c: 符号关联值
**/
Symbol *sec_sym_put(char *sec ,int c)
{
TkWord *tp;
Symbol *s;
Type type;
type.t=T_INT;
tp=tkword_insert(sec);
token=tp->tkcode;
s=sym_push(token,&type,SC_GLOBAL,c);
return s;
}
/**
符号的删除
弹出栈中符号直到栈顶符号为'b'
ptop:符号栈栈顶
b: 符号指针
**/
void sym_pop(Stack *ptop,Symbol *b)
{
Symbol *s,**ps;
TkWord *ts;
int v;
s=(Symbol *)stack_get_top(ptop);
while(s!=b)
{
v=s->v; /**根据符号的v值找到单词表中单词**/
/**更新单词表中sym_struct sym_identifier**/
if((v&SC_STRUCT)||v<SC_ANOM) /**不记录结构体成员及匿名符号**/
{
ts=(TkWord *)tktable.data[(v&~SC_STRUCT)];
if(v&SC_STRUCT)
ps=&ts->sym_struct;
else
ps=&ts->sym_identifier;
*ps=s->prev_tok; /**相当于把s删除,然后连接上s->prev_tok**/
}
stack_pop(ptop);
s=(Symbol *)stack_get_top(ptop);
}
}
/**
符号的查找
**/
/**
查找结构定义
v:符号编号
**/
Symbol *struct_search(int v)
{
if(v>=tktable.count)
return NULL;
else
return ((TkWord*)tktable.data[v])->sym_struct;
}
/**
查找标识符
v:符号编号
**/
Symbol *sym_search(int v)
{
if(v>=tktable.count)
return NULL;
else
return ((TkWord*)tktable.data[v])->sym_identifier;
}
符号表的基本操作
最新推荐文章于 2025-03-09 17:00:33 发布
这段内容描述了如何在C语言中实现符号表的基本操作,包括符号存储结构的定义,如`Symbol`和`Type`结构体,以及数据类型和存储类的枚举。还提供了诸如`sym_direct_push`、`sym_push`、`func_sym_push`等用于添加符号到全局或局部符号栈的函数,以及`sym_pop`和`sym_search`用于查找和删除符号的函数。
8303

被折叠的 条评论
为什么被折叠?



