符号表的实现方法可以多种多样,只要通过了测试基本上就没啥问题了。在这里给出一个参考实现。
首先是符号表相关的结构体,这东西最好放到 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 这个值就直接决定(限制)了可以声明的变量的数量。
本文详细介绍了一种符号表的具体实现方式,包括符号表的结构体设计、变量单元的定义及符号表核心函数的实现,如变量注册、获取变量类型等。
3689

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



