[CS@Nets][编译原理]一个栈式计算机的加法语言编译器
2015-05-18 20:39
661 查看
题目:(本题目是一个动手实践类题目,需要具备C语言和数据结构基础。)
在课程中,我们讨论一个小型的从表达式语言Sum到栈计算机Stack的编译器,
在附件中,你能找到对该编译器的一个C语言实现,但这个实现是不完整的,请你 把缺少的代码补充完整(不超过10行代码)。
加分题:实现常量折叠优化。
源代码详见:
http://mooc.study.163.com/learn/USTC-1000002001#/learn/content?type=detail&id=1000140056&cid=1000125134
由题目要求,Sum语言只有两种“符号”,整数和+,栈计算机Stack只支持两种指令push和add,例如3+4+5转换为
思路分析
编译器分为前端和后端,前端负责将输入语言进行分析,并保存在语法树种;后端将其翻译为指令。
源代码分析与补全
本代码中的前端部分直接以程序的形式给出,
然后进入compile(exp)函数,这里使用了链表,链表负责顺序存储指令并打印出来,另有一个Stack系列的结构体存放指令。
需要填写的代码有两处
a. 一个是在compile( )中利用递归,后序遍历语法树,并保存到链表中。
b. 是把链表逆序打印出来;因为这个链表是顶端插入,所以必须逆序打印。本来写了一个数组,先顺序把结果保存到数组中,再把数组输出。后来在讨论区得到了提示,用递归的方法输出。所以,最后递归逆序输出链表的代码如下
结论
1. 后序遍历4行+倒序输出6行,共10行代码完成了任务;
2. 数据结构很重要;
3. 算法很重要,不仅要知道更要会应用;
4. 要善于搜索和交流;树的递归遍历算法我已经忘了,是百度出来的;单向链表的逆向输出,其实很早就碰到过这个问题,一直使用很笨的方法解决的,没想过用了递归如此简洁明了。
在课程中,我们讨论一个小型的从表达式语言Sum到栈计算机Stack的编译器,
在附件中,你能找到对该编译器的一个C语言实现,但这个实现是不完整的,请你 把缺少的代码补充完整(不超过10行代码)。
加分题:实现常量折叠优化。
源代码详见:
http://mooc.study.163.com/learn/USTC-1000002001#/learn/content?type=detail&id=1000140056&cid=1000125134
由题目要求,Sum语言只有两种“符号”,整数和+,栈计算机Stack只支持两种指令push和add,例如3+4+5转换为
push 3 push 4 add push 5 add
思路分析
编译器分为前端和后端,前端负责将输入语言进行分析,并保存在语法树种;后端将其翻译为指令。
源代码分析与补全
本代码中的前端部分直接以程序的形式给出,
struct Exp_t *exp = Exp_Sum_new (Exp_Sum_new(Exp_Int_new (2), Exp_Int_new (3)), Exp_Int_new (4)); printf ("the expression is:\n"); Exp_print (exp);
Exp_Sum_new()函数即直接构造了一个二叉树,
Exp_print (exp)采用中序遍历将二叉树打印出来,
然后进入compile(exp)函数,这里使用了链表,链表负责顺序存储指令并打印出来,另有一个Stack系列的结构体存放指令。
需要填写的代码有两处
a. 一个是在compile( )中利用递归,后序遍历语法树,并保存到链表中。
void compile(struct Exp_t *exp) { switch (exp->kind){ ... case EXP_SUM:{ struct Exp_Sum *p = (struct Exp_Sum *)exp; if(p->left != NULL) compile(p->left); if(p->right != NULL) compile(p->right); emit(Stack_Add_new()); break; } ... }
b. 是把链表逆序打印出来;因为这个链表是顶端插入,所以必须逆序打印。本来写了一个数组,先顺序把结果保存到数组中,再把数组输出。后来在讨论区得到了提示,用递归的方法输出。所以,最后递归逆序输出链表的代码如下
void List_reverse_print (struct List_t *list) { if(list->next != NULL) List_reverse_print(list->next); if(list->instr->kind == STACK_ADD) printf("\nADD"); else printf("\nPUSH %d",((struct Stack_Push *)(list->instr))->i); }
结论
1. 后序遍历4行+倒序输出6行,共10行代码完成了任务;
2. 数据结构很重要;
3. 算法很重要,不仅要知道更要会应用;
4. 要善于搜索和交流;树的递归遍历算法我已经忘了,是百度出来的;单向链表的逆向输出,其实很早就碰到过这个问题,一直使用很笨的方法解决的,没想过用了递归如此简洁明了。
相关文章推荐
- PL/0语言编译器扩展 编译原理课程实践(1)
- 编译原理实验一:为PL/0语言编写一个词法分析程序
- 编译器实践一 之 加法栈式计算机
- 编译器实践一 之 加法栈式计算机
- 深入浅出编译原理-6-一个完整的编译器前端的代码实现
- 编译原理动手实操,用java实现一个简易编译器-语法解析
- [编译原理]用BDD方式开发lisp解释器(编译器)|开发语言java|Groovy|Spock
- 编译器实践五 之 构造一个支持加减乘除的栈式计算机
- 编译原理动手实操,用java实现一个简易编译器1-词法解析入门
- 一个编译器的实现3——用编译原理自动化制作文本解析器
- 如何写一个解释器(1):编译原理
- 如何知道一个exe或者dll是用什么语言编译的
- 编译原理课设——《TINY编译器》,用lex生成词法扫描实现编译器
- 编译原理中四种文法语言的基本概念
- VC编译下对一个超简单的缓冲区溢出程序的原理解析以及c程序的汇编分析
- 【编译原理龙书笔记】(二)一个简单的语法制导翻译器(仍未完成)
- 用java语言编译内存中java小程序,并将生成的.class文件保存在一个文件夹下。
- 从编译原理看一个解释器的实现
- 编译原理Tiny语言的定义
- 【计算机组成原理】高级语言>>汇编语言>>机器语言