[符号表]函数实现

    符号表的实现方法可以多种多样,只要通过了测试基本上就没啥问题了。在这里给出一个参考实现。

    首先是符号表相关的结构体,这东西最好放到 datastruct.h 中

/* 变量单元,存放符号表中注册的变量信息 */
struct VarCell {
    char* ident;        // 标识符
    int addr;           // 基地址
    AcceptType type;    // 类型
    int nrDim;          // 维数
    int* dims;          // 每一维偏移
};

/*
 * varList: 存放变量的链表,表中每一项是一个 VarCell*
 *
 * baseAddr: 符号表中首项的地址偏移值
 *
 * used: 符号表中所有变量总大小
 */
struct SymbolTable {
    struct LinkedList varList;
    int baseAddr;
    int used;
};

    然后是函数实现

#include<string.h>

struct SymbolTable* newSymbolTable(int base)
{
    struct SymbolTable* table = (struct SymbolTable*)
                                allocate(sizeof(struct SymbolTable));
    table->baseAddr = base;
    table->used = 0;
    initLinkedList(&(table->varList));
    return table;
}

void finalizeSymbolTable(struct SymbolTable* table)
{
    struct Iterator* i;
    struct VarCell* v;
    // 释放全部变量单元
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        revert(v->ident);
        if (0 != v->nrDim) {
            revert(v->dims);
        }
        revert(v);
    }
    table->varList.finalize(&(table->varList));
    revert(table);
}

SymbolTableError regVar(struct SymbolTable* table, char* ident,
                        AcceptType type, int nrDim, int* dims)
{
    struct Iterator* i;
    struct VarCell* v;
    // 查找是否当前符号表中已经有该符号了
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        if (0 == strcmp(v->ident, ident)) {
            i->terminate(i);
            return SymTab_MultiDef;
        }
    }

    struct VarCell* toAdd = (struct VarCell*)allocate(sizeof(struct VarCell));
    toAdd->addr = table->baseAddr + table->used;
    toAdd->type = type;
    int varSize = INTEGER == type ? INT_SIZE : REAL_SIZE, used = varSize;
    // INT_SIZE 和 REAL_SIZE 表示两类变量所占的内存大小,为了方便可以就定义为 sizeof(int) 和 sizeof(double)
    toAdd->nrDim = nrDim;
    if (0 != toAdd->nrDim) {
        toAdd->dims = (int*)allocate(sizeof(int) * nrDim);
        int j, k,* ptr;
        // 传入的 dims 是每一维大小,这里根据它计算每一维的偏移
        for (j = 0; j < toAdd->nrDim; ++j) {
            toAdd->dims[j] = varSize;
            used *= dims[j];
            for (k = 0; k < j; ++k) {
                toAdd->dims[j] *= dims[k];
            }
        }
    } else {
        toAdd->dims = NULL;
    }

    toAdd->ident = (char*)allocate(sizeof(char) * (1 + strlen(ident)));
    strcpy(toAdd->ident, ident);

    // 加入符号表,并计算符号表中现在总大小
    table->varList.add(&(table->varList), toAdd);
    table->used += used;
    // MAX_VAR_IN_STACK 常量表示栈内最大允许的变量总大小
    if (MAX_VAR_IN_STACK <= table->used + table->baseAddr) {
        table->used -= varSize;
        int j;
        for (j = 0; j < toAdd->nrDim; ++j) {
            toAdd->dims[j] = 1;
        }
        return SymTab_SizeExceeded;
    }
    return SymTab_OK;
}

SymbolTableError getVarType(struct SymbolTable* table,
                            char* ident, AcceptType* ret)
{
    struct Iterator* i;
    struct VarCell* v;
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        if (0 == strcmp(v->ident, ident)) {
            *ret = v->type;
            i->terminate(i);
            return SymTab_OK;
        }
    }
    return SymTab_NotDef;
}

SymbolTableError getVarAddr(struct SymbolTable* table, char* ident, int* ret)
{
    struct Iterator* i;
    struct VarCell* v;
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        if (0 == strcmp(v->ident, ident)) {
            *ret = v->addr;
            i->terminate(i);
            return SymTab_OK;
        }
    }
    return SymTab_NotDef;
}

SymbolTableError getVarNrDim(struct SymbolTable* table, char* ident, int* ret)
{
    struct Iterator* i;
    struct VarCell* v;
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        if (0 == strcmp(v->ident, ident)) {
            *ret = v->nrDim;
            i->terminate(i);
            return SymTab_OK;
        }
    }
    return SymTab_NotDef;
}

SymbolTableError getVarDimSize(struct SymbolTable* table,
                               char* ident, int* ret, int index)
{
    struct Iterator* i;
    struct VarCell* v;
    for_each (i, &(table->varList)) {
        v = (struct VarCell*)(i->current(i));
        if (0 == strcmp(v->ident, ident)) {
            i->terminate(i);
            if (0 <= index && index < v->nrDim) {
                *ret = v->dims[index];
                return SymTab_OK;
            } else {
                *ret = -1;
                return SymTab_ArrDimOutOfRange;
            }
        }
    }
    return SymTab_NotDef;
}

MAX_VAR_IN_STACK 可以设计成一个宏,放在 const.h 中,不要太小就行了。Jerry是没有数据段的,所有声明的变量都在栈内,MAX_VAR_IN_STACK 这个值就直接决定(限制)了可以声明的变量的数量。

你可能感兴趣的:(数据结构,单元测试,J#)