符号表的实现方法可以多种多样,只要通过了测试基本上就没啥问题了。在这里给出一个参考实现。
首先是符号表相关的结构体,这东西最好放到 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 这个值就直接决定(限制)了可以声明的变量的数量。
分享到:
相关推荐
总的来说,实现一个符号表涉及数据结构的选择、哈希函数的设计以及各种操作的实现。通过这个项目,你可以深入理解编译原理中的符号表管理,并巩固C语言的编程技巧。同时,这也将有助于你理解如何在实际的编译过程中...
- **数据结构选择**:符号表通常采用哈希表、平衡搜索树或者链表等数据结构实现,以达到快速查找和更新的目的。 - **字段设计**:符号表的每个条目应该包含但不限于标识符名称、类型、作用域、地址信息等。 - **接口...
在MATLAB中,符号变量和符号函数的使用是数学建模和符号计算的重要部分。本文将详细介绍如何在MATLAB中构造含符号变量的函数并进行求值。 首先,我们需要了解什么是符号变量。在MATLAB中,符号变量允许我们进行符号...
函数重载机制是通过函数符号生成规则来实现的。编译器会根据函数符号来选择正确的函数。 注意:仅仅函数返回值类型不同或仅仅默认实参不同都不能满足函数重载的条件。因为编译器只使用形参列表来区分重载的函数,...
符号表管理程序的设计和实现是编译原理实验的重要内容。 2. 编译原理:编译原理是计算机科学中研究编译器的设计和实现的理论基础。它涵盖了词法分析、语法分析、语义分析、代码生成等方面的内容。 3. 有限自动机:...
- 使用`syms`定义符号变量后,可以构造符号函数,例如`f=1/(1+x^2*y)`定义了一个符号函数f。 - 符号函数之间可以进行复合运算,如`compose(f,g)`和`compose(f,g,t)`展示了f和g的复合操作。 4. 特殊函数和操作: ...
很好很全的程序哦!栅格多翼蝴蝶混沌吸引子,直接用符号函数实现!
`symIndicator.m`可能是实现或使用`discretedelta`函数的一个示例脚本。在这个脚本中,可能会定义一个符号变量代表时间,然后通过该符号变量调用`discretedelta`函数。例如: ```matlab syms t % 定义符号变量t代表...
在词法分析阶段,符号表开始为空,随着分析的进行,每当遇到新的标识符,就会在表中添加相应条目。在后续的语法分析和代码生成阶段,符号表能帮助验证引用是否有效,避免未声明的变量等问题。 然而,描述中也指出这...
符号表的作用主要体现在两个方面:一是辅助进行语义正确性检查,如类型匹配、变量和函数是否已经声明等上下文相关的问题;二是辅助代码生成,编译器在生成目标代码时需要利用符号表中存储的地址信息等。 符号表的...
`string`函数实现主要涉及对文本字符串的各种操作,如创建、修改、查找、比较等。这里我们将深入探讨`string`函数的实现,尤其是`strlen`函数,它用于计算字符串的长度。 `strlen`函数是C语言标准库`<string.h>`中...
这种方式既隐藏了函数实现的细节,又保留了调用的灵活性。 总结一下,使用static关键字结合strip工具裁剪符号表是一种在编译阶段提高逆向门槛的有效方法。它通过限制函数的作用域和隐藏函数符号来增加逆向工程的...
符号表是用来存储源程序中所有标识符(如变量、函数、常量等)的名称、类型、属性和位置信息的数据结构。它在编译过程中被建立和维护,用于解决标识符的查找和解析问题。例如,在题目9.2和9.3中,可能涉及到如何构建...
5. **符号函数的可视化**:虽然符号函数不能直接在MATLAB图形窗口中绘制,但可以通过将它们转换为数值函数来实现。`fplot`或`ezplot`函数可以用来绘制已知范围内的符号函数的图形。 6. **符号表达式的代入**:用`...
在深入探讨如何使用MATLAB中的`fskmod`函数实现2FSK(二进制频移键控)调制之前,我们首先需要理解2FSK的基本概念及其在通信系统中的应用。2FSK是一种数字调制技术,它通过改变载波频率来表示二进制数据。通常,两个...
在MATLAB中实现势函数可以帮助我们进行各种数值计算和模拟,例如求解动力学问题、能量分析或者优化问题。下面将详细介绍如何在MATLAB中实现势函数,并探讨相关知识点。 一、势函数的基本概念 势函数U(x)是位置x的...
这个压缩包“符号计算篇:2matlab符号函数和符号方程.zip”显然包含了关于如何在MATLAB中进行符号计算的教程或示例。下面我们将深入探讨MATLAB的符号计算功能,包括符号函数和符号方程的处理。 1. **符号函数...
在标题“Variational-Level-Set.rar_level set_变分水平集_水平集_水平集 初始化_符号距离函数”中,核心概念是变分水平集方法,它涉及到对水平集函数的优化,以及符号距离函数的使用。 变分水平集是一种改进的水平...