这是慕课的一门编译原理的网课的第一次实践作业
github 地址如下
sumlanguage
首先我们将文法翻译成数据结构
将目标机器上的指令也翻译成数据结构
如下是对sumlanguage的文法的翻译
该语言有两种具体表达式,一种是 一个int表达式 另一种是sum表达式 以及一种抽象的表达式
其中 kind 域用于区别是哪一种具体表达式
enum Exp_Kind_t {EXP_INT, EXP_SUM}; struct Exp_t{ enum Exp_Kind_t kind; }; struct Exp_Int{ enum Exp_Kind_t kind; int i; }; struct Exp_Sum{ enum Exp_Kind_t kind; struct Exp_t *left; struct Exp_t *right; };
以及他们的构造器
用malloc创建对应大小的块给这个表达式并初始化
struct Exp_t *Exp_Int_new (int i){ struct Exp_Int *p = malloc (sizeof(*p)); p->kind = EXP_INT; p->i = i; return (struct Exp_t *)p; } struct Exp_t *Exp_Sum_new (struct Exp_t *left, struct Exp_t *right){ struct Exp_Sum *p = malloc (sizeof(*p)); p->kind = EXP_SUM; p->left = left; p->right = right; return (struct Exp_t *)p; }
下面是机器指令的数据结构,这是一个栈式计算机
也是一个抽象数据结构和两个具体数据结构
enum Stack_Kind_t {STACK_ADD, STACK_PUSH}; struct Stack_t{ enum Stack_Kind_t kind; }; struct Stack_Add{ enum Stack_Kind_t kind; }; struct Stack_Push{ enum Stack_Kind_t kind; int i; };
以及它的构造器
对比表达式的数据结构,这里对栈式计算机的实现有点相似,不过不清楚这是不是一般性的套路,还要继续学习才能知道
struct Stack_t *Stack_Add_new (){ struct Stack_Add *p = malloc (sizeof(*p)); p->kind = STACK_ADD; return (struct Stack_t *)p; } struct Stack_t *Stack_Push_new (int i){ struct Stack_Push *p = malloc (sizeof(*p)); p->kind = STACK_PUSH; p->i = i; return (struct Stack_t *)p; }
然后是核心编译部分
这里用switch语句对表达式的类型进行判断
如果是int 表达式则直接产生栈式计算机的PUSH这条指令,如果是sum表达式则
需要递归的对左表达式进行compile然后对右表达式进行compile然后产生栈式计算机的Add指令
void compile (struct Exp_t *exp){ switch (exp->kind){ case EXP_INT:{ struct Exp_Int *p = (struct Exp_Int *)exp; emit (Stack_Push_new (p->i)); break; } case EXP_SUM:{ //TODO(); struct Exp_Sum *p=(struct Exp_Sum *)exp; compile(p->left); compile(p->right); emit (Stack_Add_new ()); break; } default: break; } }
这样一个简单的sum语言编译到栈式计算机的编译器就实现了
学到的知识点是
1.将文法翻译成数据结构
2.c中使用一个抽象数据结构实现抽象
3.目标机器的指令也用数据结构先保存
4.如何使用git的push和pull操作同步github的仓库
转载于:https://www.cnblogs.com/tclan126/p/8615213.html