您的位置:首页 > 理论基础

[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只支持两种指令pushadd,例如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. 要善于搜索和交流;树的递归遍历算法我已经忘了,是百度出来的;单向链表的逆向输出,其实很早就碰到过这个问题,一直使用很笨的方法解决的,没想过用了递归如此简洁明了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: