符号表的基本操作

这段内容描述了如何在C语言中实现符号表的基本操作,包括符号存储结构的定义,如`Symbol`和`Type`结构体,以及数据类型和存储类的枚举。还提供了诸如`sym_direct_push`、`sym_push`、`func_sym_push`等用于添加符号到全局或局部符号栈的函数,以及`sym_pop`和`sym_search`用于查找和删除符号的函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**符号存储结构定义**/
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值