Skip to content
Snippets Groups Projects
semantic.c 28.6 KiB
Newer Older
zhaochaoyi's avatar
zhaochaoyi committed
#include "data.h"
#include "debug.h"

zhaochaoyi's avatar
zhaochaoyi committed
static char * empty = "";
zhaochaoyi's avatar
zhaochaoyi committed
/*
 * 代码要求:
 *      所有unit_t的实例在VarDec中创建,在stack.pop()中free,里面的type指针也同样
 *      所有的VarList在 xxxfList中创建,在VarListHandling中释放
 *      gettype中获得是符号表的指针,在VarDec赋值时需要复制
 *      所有Node_t节点中,inh是继承属性,syn是综合属性,都是指针,不是实例,通过gettype指向符号表中实例,赋值时需要复制
 *
 * Type_ops.field_alloc_init(char *name,int line,Type * type)
 * 传入field 的name,line,以及Type,type会复制一份


zhaochaoyi's avatar
zhaochaoyi committed
 * 遍历语法分析树,遇到ExtDef和Def时构建类型,加入symbol table中
 *              遇到Exp检查是否有语义错误
 */

zhaochaoyi's avatar
zhaochaoyi committed

//临时的返回链表
zhaochaoyi's avatar
zhaochaoyi committed
typedef struct VarList_t {
    unit_t * node;
    struct VarList_t * next;
    int assign;
}VarList_t;
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static void ErrorHandling(int type,int line,char * msg) {
    switch (type) {
        case 1:
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Undefined variable \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Undefined function \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Redefined variable \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Redefined function \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Type mismatched for assignment \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: The left-hand side of an assignment must be a variable \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Type mismatched for operands \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Type mismatched for return \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Function is not applicable for arguments \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Variable is not an array \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Not a function \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Not an integer \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Illegal use of \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Non-existent field \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Struct redefined field \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Duplicated name struct \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: None Defined Struct \"%s\"", type, line,msg);
            break;
        case 18:
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Undefined function \"%s\"", type, line,msg);
            break;
        case 19:
zhaochaoyi's avatar
zhaochaoyi committed
            Log("Error type %d at Line %d: Inconsistent declaration of function \"%s\"", type, line,msg);
zhaochaoyi's avatar
zhaochaoyi committed

        default:
            panic("Wrong error type");
    }
}
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_init();
zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_Program(Node_t * root);
zhaochaoyi's avatar
zhaochaoyi committed
static Type * Semantic_Check_Specifier(Node_t * root);
zhaochaoyi's avatar
zhaochaoyi committed
static unit_t * Semantic_Check_Creat_Node(char *,Type *,int,int);
static int Semantic_Check_Insert_Node(unit_t *);
static void * Semantic_Handle_VarList(VarList_t *,int );
zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_Func_Implement();
zhaochaoyi's avatar
zhaochaoyi committed

static void Semantic_Check_ExtDefList(Node_t * root);
static void Semantic_Check_ExtDef(Node_t * root);
zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_ExtDecList(Node_t * root);
static unit_t * Semantic_Check_FunDec(Node_t *);

static VarList_t * Semantic_Check_VarList(Node_t * root);
static VarList_t * Semantic_Check_ParamDec(Node_t * root);
zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_DefList(Node_t * root);
static VarList_t * Semantic_Check_Def(Node_t * root);
static VarList_t * Semantic_Check_DecList(Node_t * root);
static VarList_t * Semantic_Check_Dec(Node_t * root);
static unit_t * Semantic_Check_VarDec(Node_t * root);
static Type * Semantic_Check_StructSpecifier(Node_t * root);
zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_CompSt(Node_t * root);
static void Semantic_Check_StmtList(Node_t * root);
static void Semantic_Check_Stmt(Node_t * root);
static void Semantic_Check_Exp(Node_t * root);
static void Semantic_Check_Args(Node_t * root);

zhaochaoyi's avatar
zhaochaoyi committed

static Semantic_Check_t Semantic_Check = {
zhaochaoyi's avatar
zhaochaoyi committed
        .init = Semantic_Check_init,
zhaochaoyi's avatar
zhaochaoyi committed
        .main = Semantic_Check_Program,
zhaochaoyi's avatar
zhaochaoyi committed
};

zhaochaoyi's avatar
zhaochaoyi committed
Semantic_Check_t * semantic_check = &Semantic_Check;
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_init() {
zhaochaoyi's avatar
zhaochaoyi committed
    symbol_table->init(0x3ff);
    symbol_stack->init();
    symbol_stack->push(symbol_stack->node_alloc(GLOB_FIELD));
zhaochaoyi's avatar
zhaochaoyi committed
}

static unit_t * Semantic_Check_Creat_Node(char * name,Type * type,int deep,int line) {
    unit_t * node = symbol_table->node_alloc();
    symbol_table->node_init(node,name);
    if(deep != 0) {
        node->deep = deep;
    }
    node->line = line;
    node->type = type;
}

static int Semantic_Check_Insert_Node(unit_t * cur) {
    unit_t * find = symbol_table->find(cur->name);
    if(find && find->deep == symbol_stack->stack_size) {
        switch (symbol_stack->top()->field_type) {
            case GLOB_FIELD:
                if(cur->type->kind == FUNC_IMPL || cur->type->kind == FUNC_DECL) {
                    if(find->type->kind != FUNC_IMPL || cur->type->kind != FUNC_IMPL) {
                        if(nodeop->equal(find,cur)) {
                            find->type->kind = cur->type->kind;
                        } else {
zhaochaoyi's avatar
zhaochaoyi committed
                            ErrorHandling(19,cur->line,cur->name);
                        }
                    } else {
zhaochaoyi's avatar
zhaochaoyi committed
                        ErrorHandling(4,cur->line,cur->name);
                    }
                } else {
zhaochaoyi's avatar
zhaochaoyi committed
                    if(cur->type->kind == STRUCTURE) {
zhaochaoyi's avatar
zhaochaoyi committed
                        ErrorHandling(16,cur->line,cur->name);
zhaochaoyi's avatar
zhaochaoyi committed
                    } else {
zhaochaoyi's avatar
zhaochaoyi committed
                        ErrorHandling(3,cur->line,cur->name);
zhaochaoyi's avatar
zhaochaoyi committed
                break;
            case STRUCT_FIELD:
zhaochaoyi's avatar
zhaochaoyi committed
                ErrorHandling(15,cur->line,cur->name);
zhaochaoyi's avatar
zhaochaoyi committed
                break;
            case FUNC_FIELD:
zhaochaoyi's avatar
zhaochaoyi committed
                ErrorHandling(3,cur->line,cur->name);
zhaochaoyi's avatar
zhaochaoyi committed
                break;
            default:
                panic("Wrong Field");
        }
        nodeop->delete(cur,cur->node_type);
        return 0;
    } else {
        panic_on("Insert Fail",symbol_table->insert(cur) != 1);
        return 1;
    }
}
zhaochaoyi's avatar
zhaochaoyi committed
static void * Semantic_Handle_VarList(VarList_t * head,int kind) {
zhaochaoyi's avatar
zhaochaoyi committed
    if(!head) return NULL;
zhaochaoyi's avatar
zhaochaoyi committed
    void * ret = NULL;
    FieldList * field, * temp;
    VarList_t newlist = {
            .next = NULL,.node = NULL,.assign = 0,
    };
    VarList_t * cur = head, * prev = &newlist, * temp_node;
    switch (kind) {
        case STRUCT_FIELD://返回FieldList *
            while (cur) {
                if(!symbol_table->insert(cur->node)) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(15,cur->node->line,cur->node->name);
zhaochaoyi's avatar
zhaochaoyi committed
                    temp_node = cur->next;
                    nodeop->delete(cur->node,INFONODE);
                    free(cur);
                    cur = temp_node;
                    continue;
                }
                if(cur->assign) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(15,cur->node->line,cur->node->name);
zhaochaoyi's avatar
zhaochaoyi committed
                }
                prev->next = cur;
                prev= prev->next;
                cur = cur->next;
            }
zhaochaoyi's avatar
zhaochaoyi committed
            prev->next = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
            cur = newlist.next;
            field = type_ops->field_alloc_init("struct",0,NULL);
            field->type = type_ops->type_alloc_init(STRUCTURE);
            field->type->u.structure = type_ops->field_alloc_init(cur->node->name,cur->node->line,cur->node->type);
            temp = field->type->u.structure;
            cur = cur->next;
            while (cur) {
                temp->tail = type_ops->field_alloc_init(cur->node->name,cur->node->line,cur->node->type);
                temp = temp->tail;
                cur = cur->next;
            }
            ret = field;
            break;
        case GLOB_FIELD: //仅做检查和插入符号表,返回NULL
            while (cur) {
                if(!symbol_table->insert(cur->node)) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(3,cur->node->line,cur->node->name);
zhaochaoyi's avatar
zhaochaoyi committed
                    temp_node = cur->next;
                    nodeop->delete(cur->node,INFONODE);
                    free(cur);
                    cur = temp_node;
                    continue;
                }
                prev->next = cur;
                prev= cur;
                cur = cur->next;
            }
zhaochaoyi's avatar
zhaochaoyi committed
            prev->next = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
            break;
        case FUNC_FIELD: //返回FieldList构成的函数的参数链表
            while (cur) {
                if(!symbol_table->insert(cur->node)) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(3,cur->node->line,cur->node->name);
zhaochaoyi's avatar
zhaochaoyi committed
                    temp_node = cur->next;
                    nodeop->delete(cur->node,INFONODE);
                    free(cur);
                    cur = temp_node;
                    continue;
                }
                prev->next = cur;
                prev = cur;
                cur = cur->next;
            }
zhaochaoyi's avatar
zhaochaoyi committed
            prev->next = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
            cur = newlist.next;
            field = type_ops->field_alloc_init(cur->node->name,cur->node->line,cur->node->type);
            cur = cur->next;
            temp = field;
            while (cur) {
                temp->tail = type_ops->field_alloc_init(cur->node->name,cur->node->line,cur->node->type);
                temp = temp->tail;
                cur = cur->next;
            }
            ret = field;
            break;
zhaochaoyi's avatar
zhaochaoyi committed
        case COMPST_FIELD://仅做检查和插入符号表,返回NULL
            while (cur) {
                if(!symbol_table->insert(cur->node)) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(3,cur->node->line,cur->node->name);
zhaochaoyi's avatar
zhaochaoyi committed
                    temp_node = cur->next;
                    nodeop->delete(cur->node,INFONODE);
                    free(cur);
                    cur = temp_node;
                    continue;
                }
                prev->next = cur;
                prev= cur;
                cur = cur->next;
            }
            prev->next = NULL;
            break;
zhaochaoyi's avatar
zhaochaoyi committed
        default:
            panic("Wrong Field");
    }
    cur = newlist.next;
zhaochaoyi's avatar
zhaochaoyi committed
    while (cur) {
        prev = cur->next;
        free(cur);
        cur = prev;
    }
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed
}

zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_Func_Implement() {
    panic_on("Wrong check or stack",symbol_stack->stack_size != 1);
    panic_on("Not Glob field",symbol_stack->top()->field_type != GLOB_FIELD);
    unit_t * cur = symbol_stack->top()->head.scope_next;
    while (cur != &symbol_stack->top()->tail) {
        if(cur->type->kind == FUNC_DECL) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(18,cur->line,cur->name);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        cur = cur->scope_next;
    }
}
zhaochaoyi's avatar
zhaochaoyi committed
/*
Specifier : TYPE
     | StructSpecifier
     ;
StructSpecifier : STRUCT OptTag LC DefList RC
    | STRUCT Tag
    ;
OptTag : ID
    |
    ;
Tag : ID
*/
zhaochaoyi's avatar
zhaochaoyi committed
//gettype返回的都是符号表中实例的一个指针,要再次使用,需要使用type copy
zhaochaoyi's avatar
zhaochaoyi committed
static Type * Semantic_Check_Specifier(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    Type * ret;
    if(type(root->lchild,"TYPE")) {
        if(strcmp(root->lchild->text,"int") == 0) {
            ret = & Int_Type;
        } else if(strcmp(root->lchild->text,"float") == 0) {
            ret = & Float_Type;
zhaochaoyi's avatar
zhaochaoyi committed
    } else if(type(root->lchild->lchild,"STRUCT")) {
        if(type(root->lchild->rchild,"RC")) {
            //是结构体的定义
            ret = Semantic_Check_StructSpecifier(root->lchild);
zhaochaoyi's avatar
zhaochaoyi committed
            panic_on("Wrong struct",ret != NULL && ret->kind != STRUCTURE);
zhaochaoyi's avatar
zhaochaoyi committed
        } else {
zhaochaoyi's avatar
zhaochaoyi committed
            unit_t * temp = symbol_table->find(root->lchild->lchild->right->lchild->text);
            if(temp != NULL && temp->type->kind == STRUCTURE && strcmp(temp->name,temp->type->u.structure->name) == 0 ) {
                ret = temp->type;
zhaochaoyi's avatar
zhaochaoyi committed
                ret = &Wrong_Type;
zhaochaoyi's avatar
zhaochaoyi committed
                if(temp == NULL || temp->type->kind != STRUCTURE) {
zhaochaoyi's avatar
zhaochaoyi committed
                    ErrorHandling(17,root->lchild->lchild->line,root->lchild->lchild->right->lchild->text);
zhaochaoyi's avatar
zhaochaoyi committed
                }  else {
                    panic("Wrong Error");
                }
zhaochaoyi's avatar
zhaochaoyi committed
        }
    } else {
        panic("Wrong type");
    }
    return ret;
}

zhaochaoyi's avatar
zhaochaoyi committed
static void Semantic_Check_Program(Node_t * root) {
    panic_on("Wrong",!type(root,"Program"));
    if(root->lchild && type(root->lchild,"ExtDefList")) {
zhaochaoyi's avatar
zhaochaoyi committed
        Semantic_Check_ExtDefList(root->lchild);
zhaochaoyi's avatar
zhaochaoyi committed
        Semantic_Check_Func_Implement();
zhaochaoyi's avatar
zhaochaoyi committed
    } else {
zhaochaoyi's avatar
zhaochaoyi committed
        return;
zhaochaoyi's avatar
zhaochaoyi committed
    }
}

static void Semantic_Check_ExtDefList(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"ExtDefList"));
zhaochaoyi's avatar
zhaochaoyi committed
    Semantic_Check_ExtDef(root->lchild);
    if(root->lchild->right) {
        Semantic_Check_ExtDefList(root->rchild);
    }
}

static void Semantic_Check_ExtDef(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"ExtDef"));
zhaochaoyi's avatar
zhaochaoyi committed
    Node_t * cur = root->lchild->right;
    Node_t * specifier = root->lchild;
zhaochaoyi's avatar
zhaochaoyi committed
    Type * type = Semantic_Check_Specifier(specifier);
    if(!type) type = &Wrong_Type;
    cur->inh = type;
zhaochaoyi's avatar
zhaochaoyi committed
    if(type(cur,"ExtDecList")) {//Ext Var Dec list
        VarList_t * head = Semantic_Check_ExtDecList(cur);
        Semantic_Handle_VarList(head,GLOB_FIELD);
    } else if(type(cur,"SEMI")) {//struct Definition
        return;
zhaochaoyi's avatar
zhaochaoyi committed
    } else if(type(cur,"FunDec")) {
zhaochaoyi's avatar
zhaochaoyi committed
        unit_t * func;
zhaochaoyi's avatar
zhaochaoyi committed
        char name[32];
zhaochaoyi's avatar
zhaochaoyi committed
        if(type(cur->right,"SEMI")) {
            func = Semantic_Check_FunDec(cur);
            func->type->kind = FUNC_DECL;
            Semantic_Check_Insert_Node(func);
zhaochaoyi's avatar
zhaochaoyi committed
        } else {
zhaochaoyi's avatar
zhaochaoyi committed
            func = Semantic_Check_FunDec(cur);
zhaochaoyi's avatar
zhaochaoyi committed
            strcpy(name,func->name);
zhaochaoyi's avatar
zhaochaoyi committed
            func->type->kind = FUNC_IMPL;
zhaochaoyi's avatar
zhaochaoyi committed
            Semantic_Check_Insert_Node(func);//将函数插入符号表,注意失败的情况
            func = symbol_table->find(name);
            symbol_stack->push(symbol_stack->node_alloc(FUNC_FIELD));//进入函数体
            symbol_stack->top()->head.type = func->type;//在函数中的stack节点中head的type指针指向一个,但是不会删除
zhaochaoyi's avatar
zhaochaoyi committed
            FieldList * temp = func->type->u.func.var_list;
            while (temp) {
                unit_t * var = Semantic_Check_Creat_Node(temp->name,type_ops->type_copy(temp->type),0,temp->line);
                Semantic_Check_Insert_Node(var);
                temp = temp->tail;
zhaochaoyi's avatar
zhaochaoyi committed
            }//将函数参数加入符号表
zhaochaoyi's avatar
zhaochaoyi committed
            Semantic_Check_CompSt(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
            symbol_stack->pop();//处理结束退栈
zhaochaoyi's avatar
zhaochaoyi committed
        }
    } else {
        panic("Wrong");
    }
}

zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_ExtDecList(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"ExtDecList"));
zhaochaoyi's avatar
zhaochaoyi committed
    VarList_t * ret = new(VarList_t);
    ret->assign = 0;
    ret->next = NULL;
    root->lchild->inh = root->rchild->inh = root->inh;
    ret->node = Semantic_Check_VarDec(root->lchild);
zhaochaoyi's avatar
zhaochaoyi committed
    if(root->rchild != root->lchild) {
zhaochaoyi's avatar
zhaochaoyi committed
        ret->next = Semantic_Check_ExtDecList(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
    }
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed
}

zhaochaoyi's avatar
zhaochaoyi committed
static unit_t * Semantic_Check_FunDec(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"FunDec"));
zhaochaoyi's avatar
zhaochaoyi committed
    Type * type = type_ops->type_alloc_init(REMAINED);;
    type->u.func.ret_type = type_ops->type_copy(root->inh);
    if(type(root->rchild->left,"VarList")) {
zhaochaoyi's avatar
zhaochaoyi committed
        symbol_stack->push(symbol_stack->node_alloc(FUNC_FIELD));
        VarList_t * head = Semantic_Check_VarList(root->rchild->left);
        type->u.func.var_list = Semantic_Handle_VarList(head,FUNC_FIELD);
        symbol_stack->pop();
zhaochaoyi's avatar
zhaochaoyi committed
        type->u.func.var_list = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
    unit_t * ret = Semantic_Check_Creat_Node(root->lchild->text,type,0,root->lchild->line);
zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_VarList(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"VarList"));
zhaochaoyi's avatar
zhaochaoyi committed
    VarList_t * ret = Semantic_Check_ParamDec(root->lchild);
    if(root->lchild != root->rchild) {
zhaochaoyi's avatar
zhaochaoyi committed
        ret->next = Semantic_Check_VarList(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_ParamDec(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"ParamDec"));
zhaochaoyi's avatar
zhaochaoyi committed
    VarList_t * ret = new(VarList_t);
zhaochaoyi's avatar
zhaochaoyi committed
    root->rchild->inh = Semantic_Check_Specifier(root->lchild);
zhaochaoyi's avatar
zhaochaoyi committed
    ret->next = NULL;
    ret->assign = 0;
    ret->node = Semantic_Check_VarDec(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
/*
DefList : Def DefList
    |
    :
Def : Specifier DecList SEMI
    ;
DecList : Dec
    | Dec COMMA DecList
    ;
Dec : VarDec
    | VarDec ASSIGNOP Exp
    ;
 */
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_DefList(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"DefList"));
zhaochaoyi's avatar
zhaochaoyi committed
    VarList_t * ret = Semantic_Check_Def(root->lchild);
    VarList_t * temp = ret;
    while (temp->next) {
        temp = temp->next;
    }
    if(root->rchild != root->lchild) {
        temp->next = Semantic_Check_DefList(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
    }
    return ret;
}
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_Def(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"Def"));
    root->inh = Semantic_Check_Specifier(root->lchild);
zhaochaoyi's avatar
zhaochaoyi committed
    root->lchild->right->inh = root->inh;
    return Semantic_Check_DecList(root->lchild->right);
zhaochaoyi's avatar
zhaochaoyi committed
}

zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_DecList(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"DecList"));
zhaochaoyi's avatar
zhaochaoyi committed
    root->lchild->inh = root->rchild->inh = root->inh;
    VarList_t * ret = Semantic_Check_Dec(root->lchild);
    if(root->lchild != root->rchild) {
        ret->next = Semantic_Check_DecList(root->rchild);
zhaochaoyi's avatar
zhaochaoyi committed
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed
}
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
static VarList_t * Semantic_Check_Dec(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"Dec"));
zhaochaoyi's avatar
zhaochaoyi committed
    root->lchild->inh = root->inh;
    VarList_t * ret = new(VarList_t);
    ret->next = NULL;
    ret->node = Semantic_Check_VarDec(root->lchild);
    ret->assign = (root->lchild != root->rchild);
    if(ret->assign) {
        Semantic_Check_Exp(root->rchild);
        if(!type_ops->type_equal(root->inh,root->rchild->syn)) {
            ErrorHandling(5,root->rchild->left->line,"=");
        }
    }
zhaochaoyi's avatar
zhaochaoyi committed
    return ret;
}
zhaochaoyi's avatar
zhaochaoyi committed

zhaochaoyi's avatar
zhaochaoyi committed
/*
VarDec : ID
    | VarDec LB INT RB
*/
zhaochaoyi's avatar
zhaochaoyi committed
static unit_t * Semantic_Check_VarDec(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"VarDec"));
zhaochaoyi's avatar
zhaochaoyi committed
    int cnt = 0,nums[10] = {0};
    char * s;
zhaochaoyi's avatar
zhaochaoyi committed
    Node_t * cur;
    for(cur = root->lchild;cur->lchild != NULL;cur = cur->lchild) {
        nums[cnt++] = (int)strtol(cur->right->right->text,&s,0);
zhaochaoyi's avatar
zhaochaoyi committed
    }
zhaochaoyi's avatar
zhaochaoyi committed
    Type * var_type = new(Type), * type_head = var_type;
zhaochaoyi's avatar
zhaochaoyi committed
    int i = 0;
    do {
zhaochaoyi's avatar
zhaochaoyi committed
        if(i == cnt) {
zhaochaoyi's avatar
zhaochaoyi committed
            if(root->inh->kind == BASIC) {
zhaochaoyi's avatar
zhaochaoyi committed
                var_type->kind = BASIC;
zhaochaoyi's avatar
zhaochaoyi committed
                var_type->u.basic = root->inh->u.basic;
zhaochaoyi's avatar
zhaochaoyi committed
            } else {
                var_type->kind = root->inh->kind;
zhaochaoyi's avatar
zhaochaoyi committed
                var_type->u.structure = type_ops->field_copy(root->inh->u.structure);
zhaochaoyi's avatar
zhaochaoyi committed
            }
        } else {
            var_type->kind = ARRAY;
zhaochaoyi's avatar
zhaochaoyi committed
            var_type->u.array.size = nums[cnt - i - 1];
zhaochaoyi's avatar
zhaochaoyi committed
            var_type->u.array.elem = new(Type);
            var_type = var_type->u.array.elem;
        }
        i++;
zhaochaoyi's avatar
zhaochaoyi committed
    } while (i <= cnt);
zhaochaoyi's avatar
zhaochaoyi committed
    unit_t * ret = Semantic_Check_Creat_Node(cur->text,type_head,0,cur->line);
zhaochaoyi's avatar
zhaochaoyi committed
    return ret;
zhaochaoyi's avatar
zhaochaoyi committed
}

zhaochaoyi's avatar
zhaochaoyi committed
/*
zhaochaoyi's avatar
zhaochaoyi committed
StructSpecifier : STRUCT OptTag LC DefList RC
*/
zhaochaoyi's avatar
zhaochaoyi committed
static Type * Semantic_Check_StructSpecifier(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"StructSpecifier"));
zhaochaoyi's avatar
zhaochaoyi committed
    root->rchild->left->inh = root->inh;
zhaochaoyi's avatar
zhaochaoyi committed
    static int anonymous = 1;
zhaochaoyi's avatar
zhaochaoyi committed
    assert(type(root->lchild,"STRUCT") && type(root->rchild,"RC"));
zhaochaoyi's avatar
zhaochaoyi committed
    symbol_stack->push(symbol_stack->node_alloc(STRUCT_FIELD));
zhaochaoyi's avatar
zhaochaoyi committed
    VarList_t * head = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
    Type * type = type_ops->type_alloc_init(STRUCTURE);
zhaochaoyi's avatar
zhaochaoyi committed
    if(type(root->rchild->left,"DefList")) {
        head = Semantic_Check_DefList(root->rchild->left);
    }
zhaochaoyi's avatar
zhaochaoyi committed
    type->u.structure =  Semantic_Handle_VarList(head,STRUCT_FIELD);
    symbol_stack->pop();
zhaochaoyi's avatar
zhaochaoyi committed
    unit_t * node = Semantic_Check_Creat_Node("struct",type,0,root->lchild->line);
zhaochaoyi's avatar
zhaochaoyi committed
    if(type(root->lchild->right,"LC")) {
zhaochaoyi's avatar
zhaochaoyi committed
        sprintf(node->name,"-%d-",anonymous);
        sprintf(node->type->u.structure->name,"-%d-",anonymous++);
zhaochaoyi's avatar
zhaochaoyi committed
    } else {
zhaochaoyi's avatar
zhaochaoyi committed
        strcpy(node->name,root->lchild->right->lchild->text);
        strcpy(node->type->u.structure->name,root->lchild->right->lchild->text);
zhaochaoyi's avatar
zhaochaoyi committed
    }
zhaochaoyi's avatar
zhaochaoyi committed
    if(Semantic_Check_Insert_Node(node)) {
        return type;
    } else {
        return NULL;
    }
zhaochaoyi's avatar
zhaochaoyi committed
//definition finished
static void Semantic_Check_CompSt(Node_t * root) {//在调用前,需要先push stack
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong",!type(root,"CompSt"));
    if(type(root->lchild->right,"DefList")) {
        VarList_t * head = Semantic_Check_DefList(root->lchild->right);
        Semantic_Handle_VarList(head,COMPST_FIELD);
    }
    if(type(root->rchild->left,"StmtList")) {
        Semantic_Check_StmtList(root->rchild->left);
    }
}

static void Semantic_Check_StmtList(Node_t * root) {
    panic_on("Wrong",!type(root,"StmtList"));
    Semantic_Check_Stmt(root->lchild);
    if(root->lchild != root->rchild) {
        Semantic_Check_StmtList(root->rchild);
    }
}

static void Semantic_Check_Stmt(Node_t * root) {
    panic_on("Wrong",!type(root,"Stmt"));
    if(type(root->lchild,"Exp")) {
        Semantic_Check_Exp(root->lchild);
    } else if(type(root->lchild,"CompSt")) {
        symbol_stack->push(symbol_stack->node_alloc(COMPST_FIELD));
zhaochaoyi's avatar
zhaochaoyi committed
        Semantic_Check_CompSt(root->lchild);
        symbol_stack->pop();
zhaochaoyi's avatar
zhaochaoyi committed
    } else if(type(root->lchild,"RETURN")) {
        Semantic_Check_Exp(root->lchild->right);
        const Type * ret_type = root->lchild->right->syn;
        if(!type_ops->type_equal(ret_type,symbol_stack->top()->head.type->u.func.ret_type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(8,root->lchild->line,root->lchild->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
    } else if(type(root->lchild,"IF")) {
        Semantic_Check_Exp(root->lchild->right->right);
        const Type * exp_type = root->lchild->right->right->syn;
        if(!type_ops->type_equal(exp_type,&Int_Type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,root->lchild->right->right->line,root->lchild->right->right->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
zhaochaoyi's avatar
zhaochaoyi committed
        if(root->lchild->right->right->right->right) {
            Semantic_Check_Stmt(root->lchild->right->right->right->right);
        }
zhaochaoyi's avatar
zhaochaoyi committed
        if(type(root->rchild->left,"ELSE")) {
            Semantic_Check_Stmt(root->rchild);
        }
    } if(type(root->lchild,"WHILE")) {
        Semantic_Check_Exp(root->lchild->right->right);
        const Type * exp_type = root->lchild->right->right->syn;
        if(!type_ops->type_equal(exp_type,&Int_Type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,root->lchild->right->right->line,root->lchild->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
zhaochaoyi's avatar
zhaochaoyi committed
        Semantic_Check_Stmt(root->lchild->right->right->right->right);
zhaochaoyi's avatar
zhaochaoyi committed
    }
}

static void Semantic_Check_Exp(Node_t * root) {
zhaochaoyi's avatar
zhaochaoyi committed
    panic_on("Wrong Exp", !type(root,"Exp"));
    Node_t * mid = root->lchild->right, * left = root->lchild,* right = root->rchild;
    const Type * ret = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
    const Type * left_type = NULL, * right_type = NULL, * mid_type = NULL;
zhaochaoyi's avatar
zhaochaoyi committed
    if(type(left,"ID") && mid == NULL) {
        unit_t * find = symbol_table->find(left->text);
        if(!find) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(1,left->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
            ret = &Wrong_Type;
        } else {
            ret = find->type;
        }
    } else if(type(left,"INT") && mid == NULL) {
        ret = &Int_Type;
    } else if(type(left,"FLOAT") && mid == NULL) {
        ret = &Float_Type;
    } else if(type(mid,"ASSIGNOP")) {
        Semantic_Check_Exp(left);
        Semantic_Check_Exp(right);
        left_type = left->syn;
        right_type = right->syn;
        if(!type_ops->type_equal(left_type,right_type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(5,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
zhaochaoyi's avatar
zhaochaoyi committed
        if(!type(left->lchild,"ID") && !type(left->rchild,"RB") && !(left->lchild->right && type(left->lchild->right,"DOT"))) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(6,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        ret = left_type;
    } else if(type(mid,"AND") || type(mid,"OR")) {
        Semantic_Check_Exp(left);
        Semantic_Check_Exp(right);
        left_type = left->syn;
        right_type = right->syn;
        if(!type_ops->type_equal(left_type,&Int_Type) || !type_ops->type_equal(right_type,&Int_Type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        ret = &Int_Type;
    }  else if(type(mid,"RELOP")) {
        Semantic_Check_Exp(left);
        Semantic_Check_Exp(right);
        left_type = left->syn;
        right_type = right->syn;
        if((!type_ops->type_equal(left_type,&Int_Type) && !type_ops->type_equal(left_type,&Float_Type))
            || (!type_ops->type_equal(right_type,&Int_Type) && !type_ops->type_equal(right_type,&Float_Type))) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        if(!type_ops->type_equal(right_type,left_type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        ret = &Int_Type;
    } else if(type(mid,"PLUS") || type(mid,"MINUS") || type(mid,"STAR") || type(mid,"DIV")) {
        Semantic_Check_Exp(left);
        Semantic_Check_Exp(right);
        left_type = left->syn;
        right_type = right->syn;
        if((!type_ops->type_equal(left_type,&Int_Type) && !type_ops->type_equal(left_type,&Float_Type))
           || (!type_ops->type_equal(right_type,&Int_Type) && !type_ops->type_equal(right_type,&Float_Type))) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,empty);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        if(!type_ops->type_equal(right_type,left_type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,empty);
zhaochaoyi's avatar
zhaochaoyi committed
        }
        ret = left_type;
    } else if(type(left,"LP")) {
        Semantic_Check_Exp(mid);
        ret = mid->syn;
    } else if(type(left,"MINUS")) {
        Semantic_Check_Exp(mid);
        ret = mid->syn;
    } else if(type(left,"NOT")) {
        Semantic_Check_Exp(mid);
        mid_type = mid->syn;
        if(!type_ops->type_equal(mid_type,&Int_Type)) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(7,mid->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
        }
zhaochaoyi's avatar
zhaochaoyi committed
        ret = &Int_Type;
zhaochaoyi's avatar
zhaochaoyi committed
    } else if(type(mid,"LP")) {
        unit_t * find = symbol_table->find(left->text);
        if(!find) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(2,left->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
            ret = &Wrong_Type;
        } else if(find->type->kind != FUNC_DECL && find->type->kind != FUNC_IMPL) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(11,left->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
            ret = find->type;
        } else {
            if(type(mid->right,"RP") && find->type->u.func.var_list != NULL) {
zhaochaoyi's avatar
zhaochaoyi committed
                ErrorHandling(9,left->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
            } else if(type(mid->right,"Args") && find->type->u.func.var_list == NULL) {
zhaochaoyi's avatar
zhaochaoyi committed
                ErrorHandling(9,left->line,left->text);
zhaochaoyi's avatar
zhaochaoyi committed
            } else {
                if(type(mid->right,"Args")) {
                    mid->right->inh = find->type;
                    Semantic_Check_Args(mid->right);
                }
            }
            ret = find->type->u.func.ret_type;
        }
    } else if(type(mid,"LB")) {
        Semantic_Check_Exp(left);
        Semantic_Check_Exp(mid->right);
        left_type = left->syn;
        mid_type = mid->right->syn;
        if(left_type->kind != ARRAY) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(10,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
            ret = left_type;
        } else {
            if(!type_ops->type_equal(mid_type,&Int_Type)) {
zhaochaoyi's avatar
zhaochaoyi committed
                ErrorHandling(12,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
            }
            ret = left_type->u.array.elem;
        }
    } else if(type(mid,"DOT")) {
        Semantic_Check_Exp(left);
        left_type = left->syn;
        if(left_type->kind != STRUCTURE) {
zhaochaoyi's avatar
zhaochaoyi committed
            ErrorHandling(13,mid->line,mid->text);
zhaochaoyi's avatar
zhaochaoyi committed
            ret = left_type;
        } else {
            const FieldList * temp = left_type->u.structure->type->u.structure;
zhaochaoyi's avatar
zhaochaoyi committed
            while (temp) {
                if(strcmp(temp->name,right->text) == 0) {
                    break;
                }
                temp = temp->tail;
            }
            if(temp) {
                ret = temp->type;
            } else {
                ErrorHandling(14,mid->line,right->text);
zhaochaoyi's avatar
zhaochaoyi committed
                ret = left_type;
            }
        }
    }
    root->syn = ret;
    panic_on("Wrong Exp",ret == NULL);
}

static void Semantic_Check_Args(Node_t * root) {
    panic_on("Wrong",!type(root,"Args"));
    FieldList * list, * head;
    Node_t * cur = root;
    Semantic_Check_Exp(root->lchild);
    list = type_ops->field_alloc_init("Exp",0,root->lchild->syn);
    head = list;
    if(root->lchild != root->rchild) {
        cur = cur->rchild;
zhaochaoyi's avatar
zhaochaoyi committed
    } else {
        cur = cur->lchild;
zhaochaoyi's avatar
zhaochaoyi committed
    }
zhaochaoyi's avatar
zhaochaoyi committed
    while (type(cur,"Args")) {
        Semantic_Check_Exp(cur->lchild);
        list->tail = type_ops->field_alloc_init("Exp",0,cur->lchild->syn);
zhaochaoyi's avatar
zhaochaoyi committed
        cur = cur->rchild;
        list = list->tail;
zhaochaoyi's avatar
zhaochaoyi committed
    }
    if(!type_ops->field_equal(root->inh->u.func.var_list,head)) {
zhaochaoyi's avatar
zhaochaoyi committed
        ErrorHandling(9,root->lchild->line,root->lchild->text);
zhaochaoyi's avatar
zhaochaoyi committed
    }
    type_ops->field_delete(head);
zhaochaoyi's avatar
zhaochaoyi committed