符号表的构造

时间:2021-07-05 06:06:38
/**符号表的构造过程**/


/**
解析外部声明
l:存储类型,局部的还是全局的
**/
void external_decartion(int l)
{
    Type btype,type;
    int v,has_init,r,addr;
    Symbol *sym;
    if(!type_specifier(&btype))     /**修改btype的t成员**/
    {
        expect("<类型区别符>");
    }
    if(btype.t==T_STRUCT&&token==TK_SEMICOLON)/**只有结构体类型定义的结尾加分号是合法的**/
    {
        get_token();
        return;
    }
    while(1)        /*逐个分析声明或函数定义*/
    {
        type=btype;
        declarator(&type,&v,NULL);       /**经过这个函数,v会变成token,如果是函数或数组,则type会发生变化,不然type还是原来的btype值,最后一个参数跟对齐有关**/
        if(token==TK_BEGIN)              /**函数定义**/
        {
            if(l==SC_LOCAL)
                error("不支持函数嵌套定义");
            if(type.t&T_BTYPE!=T_FUNC)
                expect("<函数定义>");
            sym=sym_search(v);
            if(sym)                     /**函数前面声明过,现在给出函数定义**/
            {
                if((sym->type.t&T_BTYPE)!=T_FUNC)/**标识符声明的时候不是函数类型,就会显示重定义错误**/
                    error("'%s'重定义",get_tkstr(v));
                sym->type=type;         /**type和sym->type的区别在于ref,type.ref经过declarator函数后有了值,sym->type.ref并没有赋值**/
            }
            else
            {
                sym=func_sym_push(v,&type);/**如果单词的identifier值还没有,就把插进去sym**/
            }
            sym->r=SC_SYM|SC_GLOBAL;        /**函数符号的r值设置为符号和全局**/
            funcbody(sym);
            break;
        }
        else                                /**声明**/
        {
            if((type.t&T_BTYPE)==T_FUNC)    //函数声明
            {
                if(sym_search(v)==NULL)
                {
                    sym=sym_push(v,&type,SC_GLOBAL|SC_SYM,0); /**函数符号的r值设置为符号和全局**/
                }
            }
            else                            //变量声明
            {
                r=0;
                if(!(type.t&T_ARRAY))       /**数组类型不能做左值**/
                    r|=SC_LVAL;
                r|=l;                       /**l表示是全局类型还是局部类型**/
                has_init=(token==TK_ASSIGN);

                if(has_init)
                {
                    get_token();
                    initializer(&type);
                }
                sym=var_sym_put(&type,r,v,addr);/**局部变量 经过这函数r不变,全局变量,r|SC_SYM**/
            }
            if(token==TK_COMMA)
            {
                get_token();
            }
            else
            {
                syntax_state=SNTX_LF_HT;
                skip(TK_SEMICOLON);
                break;
            }
        }
    }

}
/**
功能:解析类型区分符
返回值:是否发现合法的类型区分符
<type_specifier>::=<KW_INT>
    |<KW_CHAR>
    |<KW_SHORT>
    |<KW_VOID>
    |<struct_specifier>
**/
int type_specifier(Type *type)
{
    int t,type_found;
    Type type1;
    t=0;
    int type_found=0;
    switch(token)
    {
    case KW_CHAR:
        t=T_CHAR;
        type_found=1;
        syntax_state=SNTX_SP;   /**空格**/
        get_token();
        break;
    case KW_SHORT:
        t=T_SHORT;
        type_found=1;
        syntax_state=SNTX_SP;
        get_token();
        break;
    case KW_VOID:
        t=T_VOID;
        type_found=1;
        syntax_state=SNTX_SP;
        get_token();
        break;
    case KW_INT:
        t=T_INT;
        type_found=1;
        syntax_state=SNTX_SP;
        get_token();
        break;
    case KW_STRUCT:
        struct_specifier(&type1);
        type->ref=type1.ref;            /**ref改变**/
        t=T_STRUCT;
        type_found=1;
        syntax_state=SNTX_SP;
        break;
    default:
        break;

    }
    type->t=t;
    return type_found;
}

/**
结构区分符:
<struct_specifier>::=
<KW_STRUCT><IDENTIFIER><TK_BEGIN><struct_declaration_list><TK_END>
    |<KW_STRUCT><IDENTIFIER>
**/
void struct_specifier(Type *type)
{
    int v;
    Symbol *s;
    Type type1;

    get_token();
    v=token;

    syntax_state=SNTX_DELAY;        /**延迟到取出下个单词后确定输出格式**/

    get_token();
    if(token==TK_BEGIN)     /*适用于结构体定义*/
    syntax_state=SNTX_LF_HT;
    else if(token==TK_CLOSEPA)  /*适用于sizeof(struct struct_name)*/
    syntax_state=SNTX_NUL;
    else                        /*适用于结构变量声明*/
        syntax_state=SNTX_SP;
    syntax_indent();
    if(v<TK_IDENT)          /**关键字不能作为结构名称**/
        expect("结构体名");
    s=struct_search(v);     /**查找结构是否定义**/
    if(!s)
    {
        type1.t=KW_STRUCT;  /**是KW_STRUCT 不是T_STRUCT**/
        //-1赋值给s->c,标识结构体尚未定义
        s=sym_push(v|SC_STRUCT,&type1,0,-1);
        s->r=0;

    }
    type->ref=s;            /**ref引用**/
    if(token==TK_BEGIN)
    {
        struct_declaration_list(type);
    }
}
/**
结构声明符表
<struct_declaration_list>::=<struct_declaration>{<struct_declaration>}
**/
void struct_declaration_list(Type *type)
{
    int maxalign,offset;
    syntax_state=SNTX_LF_HT;    /**第一个结构体成员与{不写在同一行**/
    syntax_level++;             /**结构体成员变量声明,缩进增加一级**/
    Symbol *s,**ps;
    s=type->ref;
    get_token();
    if(s->c!=-1)                /**s->c记录结构体尺寸**/
        error("结构体已定义");
    maxalign=1;
    ps=&s->next;
    offset=0;
    while(token!=TK_END)
    {
        struct_declaration(&maxalign,&offset,&ps);
    }
    skip(TK_END);
    syntax_state=SNTX_LF_HT;
    s->c=calc_align(offset,maxalign);   /**结构体大小**/
    s->r=maxalgin;                      /**结构体对齐**/
}
/**
结构声明
<struct_declaration::=
    <type_specifier><declarator>{<TK_COMMA><declarator>}<TK_SEMICOLON>

maxalign(输入,输出):成员最大对齐粒度
offset(输入,输出):  偏移量
ps(输出):            结构定义符号
**/
void struct_declaration(int* maxalign,int *offset,Symbol ***ps)
{
    int v,size,align;
    Symbol *ss;
    Type type1,btype;
    int force_align;
    type_specifier(&btype);
    while(1)        /**while循环很精妙呀**/
    {
        v=0;
        type1=btype;
        declarator(&type1,&v,&force_align);    /**force_align这个参数用来观察是否有强制对齐**/
        size=type_size(&type1,&align);

        if(force_align&ALIGN_SET)               /**如果有强制对齐就按强制对齐**/
            align=force_align&~ALIGN_SET;       /** #define ALIGN_SET 0x100**/

        *offset=calc_align(*offset,align);

        if(align>*maxalign)
            *maxalign=align;
        ss=sym_push(v|SC_MEMBER,&type1,0,*offset);
        *offset+=size;
        **ps=ss;
        *ps=&ss->next;                          /**next**/
        if(token==TK_SEMICOLON)
            break;
        skip(TK_COMMA);
    }
    syntax_state=SNTX_LF_HT;/**又来了这不明所以的东西**/
    skip(TK_SEMICOLON);
}
/**
函数调用约定
<function_calling_convention>::=<KW_CDECL>|<KW_STDCALL>
用于函数声明上,用在数据声明上忽略掉

fc(输出):调用约定
**/
void function_calling_convention(int *fc)
{
    *fc=KW_CDECL;
    if(token==KW_CDECL||token==KW_STDCALL)
    {
        syntax_state=SNTX_SP;
        *fc=token;
        get_token();
    }
}
/**
结构成员对齐
<struct_member_alignment>::=<KW_ALIGN><TK_OPENPA><TK_CINT><TK_CLOSEPA>
force_align(输出):强制对齐粒度
**/
void struct_member_alignment(int *force_align)
{
    int align=1;
    if(token==KW_ALIGN)             /**如果有强制对齐**/
    {
        get_token();
        skip(TK_OPENPA);
        if(token==TK_CINT)
        {
            get_token();
            align=tkvalue;          /**align值为()里的数字值**/
        }
        else expect("整数常量");
        skip(TK_CLOSEPA);
        if(align!=1&&align!=2&&align!=4)
            align=1;
        align|=ALIGN_SET;           /**|=ALIGN_SET 说明要强制对齐**/
        *force_align=align;
    }
    else
        *force_align=1;
}
/**
声明符
<declarator>::={<pointer>}[<function_calling_convention>]
    [<struct_member_alignment>]<direct_declarator>
<pointer>::=<TK_STAR>

type:   数据类型
v(输出): 单词编号
force_align(输出): 强制对齐粒度
**/
void declarator(Type *type,int *v,int *force_align)
{
    int fc;
    while(token==TK_STAR)
    {
        mk_pointer(type);
        get_token();
    }
    function_calling_convention(&fc);
    if(force_align)
        struct_member_alignment(force_align);
    direct_declarator(type,v,fc);
}
/**
功能:	生成指针类型
t:		原数据类型
**/
void mk_pointer(Type *t)
{
	Symbol *s;
    s = sym_push(SC_ANOM, t, 0, -1);
    t->t = T_PTR ;
    t->ref = s;
}

/**
直接声明符
<direct_declarator>::=<IDENTIFIER><direct_declarator_postfix>

type(输入,输出):数据类型
v(输出):单词编号
func_call:函数调用约定
**/
void direct_declarator(Type *type,int *v,int func_call)
{
    if(token>=TK_IDENT)
    {
        *v=token;
        get_token();
    }
    else
    {
        expect("标识符");
    }
    direct_declarator_postfix(type,func_call);
}
/**
直接声明符后缀
<direct_declarator_postfix>::={<TK_OPENBR><TK_CINT><TK_CLOSEBR>
    |<TK_OPENBR><TK_CLOSEBR>
    |<TK_OPENPA><parameter_type_list><TK_CLOSEPA>
    |<TK_OPENPA><TK_CLOSEPA>
}
type(输入,输出):数据类型
func_call:函数调用约定
**/
void direct_declarator_postfix(Type*type,int func_call)
{
    int n;
    Symbol *s;
    if(token==TK_OPENPA)
    {
        parameter_type_list(type,func_call);/**函数需要func_call参数,变量不用**/
    }
    else if(token==TK_OPENBR)
    {
        get_token();
        n=-1;
        if(token==TK_CINT)
        {
            get_token();
            n=tkvalue;
        }
        skip(TK_CLOSEBR);
        direct_declarator_postfix(type,func_call);
        s=sym_push(SC_ANOM,type,0,n);
        type->t=T_ARRAY|T_PTR;
        type->ref=s;
    }
}
/**
形参类型表
功能:解析形参类型表
func_call:函数调用约定

<parameter_type_list>::=<parameter_list>
    |<parameter_list><TK_COMMA><TK_ELLIPSIS>
<parameter_list>::=<parameter_declaration>
    {<TK_COMMA><parameter_declaration}
<parameter_declaration>::=<type_specifier>{<declarator>}

等价转换后文法:
<parameter_type_list>::=<type_specifier>{<declarator>}
    {<TK_COMMA><type_specifier>{<declarator>}}<TK_COMMA><TK_ELLIPSIS>
**/
void parameter_type_list(Type *type,int func_call)
{
    int n;
    Symbol **plast,*s,*first;
    Type pt;
    get_token();
    first=NULL;
    plast=&first;
    while(token!=TK_CLOSEPA)
    {
        if(!type_specifier(&pt))
        {
            error("无效类型标识符");
        }
        declarator(&pt,&n,NULL);
        s=sym_push(n|SC_PARAMS,&pt,0,0);/**SC_PARAMS表函数参数**/
        *plast=s;
        plast=&s->next;                 /**next显示作用**/
        if(token==TK_CLOSEPA)
            break;
        skip(TK_COMMA);
        if(token==TK_ELLIPSIS)
        {
            func_call=KW_CDECL;
            get_token();
            break;
        }
    }
    syntax_state=SNTX_DELAY;
    skip(TK_CLOSEPA);
    if(token==TK_BEGIN)     //函数定义
        syntax_state=SNTX_LF_HT;
    else                    //函数声明
        syntax_state=SNTX_NUL;
    syntax_indent();
    /**此处将函数返回类型存储,然后指向参数,最后将type设为函数类型,引用相关信息,放在ref中**/
    s=sym_push(SC_ANOM,type,func_call,0);
    s->next=first;
    type->t=T_FUNC;
    type->ref=s;
}
/**
函数体
<funcbody>::=<compound_statement>
sym:函数符号
**/
void funcbody(Symbol *sym)
{
    /**放一匿名符号在局部符号表**/
    sym_direct_push(&local_sym_stack,SC_ANOM,&int_type,0);
    compound_statement(NULL,NULL);
    /**清空局部符号栈**/
    sym_pop(&local_sym_stack,NULL);
}
/**
初值符
<initializer>::=<assignment_expression>
**/
void initializer(Type *type)
{
    if(type->t&T_ARRAY)
        get_token();
    else
        assignment_expression();
}

/**
复合语句
<compound_statement>::=<TK_BEGIN>{<declaration>}{<statement>}<TK_END>

bsym:break跳转位置
csym:continue跳转位置
**/
void compound_statement(int *bsym,int *csym)
{
    syntax_state=SNTX_LF_HT;
    syntax_level++;         //复合语句,缩进加一级

    Symbol *s;
    s=(Symbol*)stack_get_top(&local_sym_stack);/**去局部栈顶元素为坐标**/

    get_token();
    while(is_type_specifier(token))             /**判断是否是声明**/
    {
        external_decartion(SC_LOCAL);
    }
    while(token!=TK_END)
    {
        statement(bsym,csym);
    }
    sym_pop(&local_sym_stack,s);              /**根据这个坐标把复合语句的符号清空**/
    syntax_state=SNTX_LF_HT;
    get_token();
}

/**
<sizeof_expression>::=
    <KW_SIZEOF><TK_OPENPA><type_specifier><TK_CLOSEPA>
**/
void sizeof_expression()
{
    int align,size;
    Type type;

    get_token();
    skip(TK_OPENPA);
    type_specifier(&type);
    skip(TK_CLOSEPA);

    size=type_size(&type,&align);
    if(size<0)
        error("sizeof计算类型尺寸失败")
}
/**
返回类型长度
t:数据类型指针
a:对齐值
**/
int type_size(Type *t,int *a)
{
    Symbol *s;
    int bt;
    //指针类型长度4字节
    int PTR_SIZE=4;

    bt=t->t&T_BTYPE;
    switch(bt)
    {
    case T_STRUCT:
        s=t->ref;
        *a=s->r;            /**结构体的r纪录对齐粒度**/
        return s->c;        /**结构体的c纪录结构体大小**/
    case T_PTR:             /**指针类型**/
        if(t->t&T_ARRAY)    /**数组**/
        {
            s=t->ref;
            return type_size(&s->type,a)*s->c;/**引用的大小*数量**/
        }
        else
        {
            *a=PTR_SIZE;
            return PTR_SIZE;
        }
    case T_INT:
        *a=4;
        return 4;
    case T_SHORT:
        *a=2;
        return 2;

    default:        //char ,void ,function
        *a=1;
        return 1;
    }

}
/**
初值表达式
<primary_expression>::=<IDENTIFIER>
    |<TK_CINT>
    |<TK_CSTR>
    |<TK_CCHAR>
    |<TK_OPENPA><expression><TK_CLOSEPA>
***/
void primary_expression()
{
    int t,addr;
    Type type;
    Symbol *s;
    switch(token)
    {
    case TK_CINT:
    case TK_CCHAR:
        get_token();
        break;
    case TK_CSTR:
        t=T_CHAR;
        type.t=t;
        mk_pointer(&type);                  /**常量字符串设置为一个指针类型**/
        type.t|=T_ARRAY;
        var_sym_put(&type,SC_GLOBAL,0,addr);
        initializer(&type);
        break;
    case TK_OPENPA:
        get_token();
        expression();
        skip(TK_CLOSEPA);
        break;
    default:
        t=token;
        get_token();
        if(t<TK_IDENT)
            expect("标识符或常量");
        s=sym_search(t);
        if(!s)
        {
            if(token!=TK_OPENPA)
                error("'%s'未声明\n",get_tkstr(t));

            s=func_sym_push(t,&default_func_type); //允许函数不声明,直接引用
            s->r=SC_GLOBAL|SC_SYM;
        }
        break;
    }
}