没有合适的资源?快使用搜索试试~ 我知道了~
首页C语言编译器符号表与错误处理设计
在吕鹏泽同学的CS1601课程实验报告中,关于符号表结构和错误类型的描述是核心知识点。符号表在编译器设计中扮演着至关重要的角色,它用于存储程序中的各种符号,如变量、函数、类型等信息,以便在后续的语义分析阶段进行管理和检索。符号表通常是一个由symbol结构体组成的数组,这些结构体包含了符号的名称、类型、地址等信息,这对于确保程序的正确性和代码的可维护性至关重要。 描述中提到的错误类型码包括两种主要错误:ERROR 1是变量重复定义,即编译器检测到同一个变量在程序的不同位置被多次声明;ERROR 2可能是函数或变量未正确声明或定义。这些错误类型在编译器的错误处理部分进行编码,并在解析阶段通过检查符号表来识别,以确保程序符合语法规则。 此外,报告还详细定义了实验所使用的语言的语法和词法,如单词文法和语句文法。单词包括关键字(如int、float、if等),运算符(算术、逻辑、比较和赋值等),界符(分号、括号等),以及常量(整型、浮点型和字符)。语句文法定义了程序的基本结构,如函数定义、变量声明和程序主体等,这些都是编译器设计中的基础,决定了程序如何被解析和转换成目标代码。 整个实验旨在通过构建一个简单的C语言编译器,让学生深入理解编译原理中的关键概念,如词法分析、语法分析、语义分析和代码生成等过程。通过实践,学生不仅可以巩固课堂学习的知识,还能提升对系统软件开发的兴趣和能力。在这个过程中,符号表的设计和错误处理机制的实现是不可或缺的部分,反映了编译器设计的复杂性和精细度。
资源详情
资源推荐
12
union{
char type_id[33];//由标识符生成的叶结点
int type_int;//由整常数生成的叶结点
float type_float;//由浮点常数生成的叶结点
double type_double;//由双精度浮点数生成的叶节点
char type_char;//由字符生成的叶节点
int array_size[2];//数组大小
};
struct node *ptr[3];//子树指针,由 kind 确定有多少棵子树
int level;//层号
int place;//表示结点对应的变量或运算结果符号表的位置序号
char Etrue[15],Efalse[15];//对布尔表达式的翻译时,真假转移目标的标号
char Snext[15];//该结点对饮语句执行后的下一条语句位置标号
struct codenode *code;//该结点中间代码链表头指针
char op[10];
int type;//结点对应值的类型
int pos;//语法单位所在位置行号
int offset;//偏移量
int width;//占数据字节数
int num;//参数个数
};
3.4 语义分析(实验二)
构建符号表的主要工作是正确地添加符号、删除符号和明确符号的作用域。
当遇到函数定义、形参定义和变量定义时需要添加符号,这些标识符在使用时不
必处理,只需在定义时添加一次即可。
假设全局作用域为 0,那么函数的作用域自然为 0,因为它定义在全局范围
内。函数的形参有一个单独的作用域,在函数作用域的基础上加一,那么形参作
用域的数值就为 1。函数体内的代码与形参应该不属于同一个域,故作用域需要
再加一。每次进入一个 if-else 块或者 while 块中作用域也需要再当前基础上加一。
例如在处理一个函数结点时,会添加一个符号,类型为函数,然后继续处理
它的形参和代码部分,作用域 level 也分别增加。以赋值语句的左值检测为例,
代码实现如下:
13
case ASSIGNOP:
if (T->ptr[0]->kind != ID)
{
semantic_error(T->pos, "", "ERROR 8:赋值语句必须为左值");
}
else
{
Exp(T->ptr[0]); //处理左值,例中仅为变量
T->ptr[1]->offset = T->offset;
Exp(T->ptr[1]);
T->type = T->ptr[0]->type;
T->width = T->ptr[1]->width;
T->code = merge(2, T->ptr[0]->code, T->ptr[1]->code);
opn1.kind = ID;
strcpy(opn1.id, symbolTable.symbols[T->ptr[1]->place].alias); //右值一定是
个变量或临时变量
opn1.offset = symbolTable.symbols[T->ptr[1]->place].offset;
result.kind = ID;
strcpy(result.id, symbolTable.symbols[T->ptr[0]->place].alias);
result.offset = symbolTable.symbols[T->ptr[0]->place].offset;
T->code = merge(2, T->code, genIR(ASSIGNOP, opn1, opn2, result));
}
break;
3.5 中间代码生成功能(实验三)
三地址中间代码 TAC 是一个 4 元组,逻辑上包含(op、opn1、opn2、
result),其中 op 表示操作类型说明,opn1 和 opn2 表示 2 个操作数,result 表示
运算结果。后续还需要根据个 TAC 序列生成目标代码,所以设计其存储结构时,
每一部分要考虑目标代码生成是所需要的信息。
(1)运算符:表示这条指令需要完成的运算,可以用枚举常量表示,如 PLUS
表示双目加,JLE 表示小于等于,PARAM 表示形参,ARG 表示实参等。
(2)操作数与运算结果:这些部分包含的数据类型有多种,整常量,实常
量,还有使用标识符的情况,如变量的别名、变量在其数据区的偏移量和层号、
转移语句中的标号等。类型不同,所以考虑使用联合。为了明确联合中的有效成
14
员,将操作数与运算结果设计成结构类型,包含 kind,联合等几个成员,kind 说
明联合中的有效,联合成员是整常量,实常量或标识符表示的别名或标号或函数
名等。
(3)为了配合后续的 TAC 代码序列的生成,将 TAC 代码作为数据元素,
用双向循环链表表示 TAC 代码序列。
15
4 系统测试与评价
4.1 测试用例
test_error.c
int fun(int a, int b)
{
return 0;
}
int test(int input)
{
int a;
int a;
float b;
fun(b,1);
fun(1, 2);
fun(1, 2, 3);
fun = 3;
if(1.0 < a)
b = 3;
b++;
a = t;
b = a;
a = 1/0;
a + b = 3;
fun1();
a = b();
a = fun(1,2);
}
int fun()
剩余80页未读,继续阅读
yxldr
- 粉丝: 22
- 资源: 326
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C语言快速排序算法的实现与应用
- KityFormula 编辑器压缩包功能解析
- 离线搭建Kubernetes 1.17.0集群教程与资源包分享
- Java毕业设计教学平台完整教程与源码
- 综合数据集汇总:浏览记录与市场研究分析
- STM32智能家居控制系统:创新设计与无线通讯
- 深入浅出C++20标准:四大新特性解析
- Real-ESRGAN: 开源项目提升图像超分辨率技术
- 植物大战僵尸杂交版v2.0.88:新元素新挑战
- 掌握数据分析核心模型,预测未来不是梦
- Android平台蓝牙HC-06/08模块数据交互技巧
- Python源码分享:计算100至200之间的所有素数
- 免费视频修复利器:Digital Video Repair
- Chrome浏览器新版本Adblock Plus插件发布
- GifSplitter:Linux下GIF转BMP的核心工具
- Vue.js开发教程:全面学习资源指南
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功