Hello Compiler

Posted 十木禾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hello Compiler相关的知识,希望对你有一定的参考价值。

源语言 : 加法表达式语言,支持形如 1+11+2+3 …… 的运算
目标机器:栈式计算机,支持push(n)add() 两种操作(使用C++模拟)

构造一个栈式计算机

#include<iostream>

#define ERROR -9999;

using namespace std;

class StackComputer
	private:
		int stack_arr[100]; // 操作数栈 
		int head = 0; 	 	// 栈顶指针 
		
		int pop()  
			if(this->head < 1) return ERROR;
			
			this->head--;
			
			return this->stack_arr[this->head];
		
	public:
		StackComputer() = default;
		void push(int n) 
			this->stack_arr[this->head] = n;
			
			this->head ++;
		
		int add() 
			if(this->head < 2) return ERROR;
			
			int result = this->pop() + this->pop();
			
			this->push(result);
			
			return result;
		
		void print()    	// 打印结果 
			 if(this->head == 1) cout<<this->pop()<<endl;
		
;

main函数如下

int main() 
	StackComputer c;
	
	c.push(1);
	c.push(10);
	c.add();
	c.push(100);
	c.add();
	
	c.print();  // 输出111 

现在我们编写一个编译器将1+10+100编译成:

	c.push(1);
	c.push(10);
	c.add();
	c.push(100);
	c.add();
	
	c.print(); 

编写编译器

步骤说明

首先将1+10+100生成如下的抽象语法树

然后对该二叉树进行后续遍历,按照如下的规则生成代码

  1. 遇到整数n,则生成c.push(n)
  2. 遇到操作符+,则生成c.add()
  3. 遍历完成整棵树以后,生成c.print()
构造抽象语法树
#define MODE_NUM 0
#define MODE_CHAR 1

typedef struct AbsTree* BinTree;
struct AbsTree 
	int mode;
	int data;
	bool isRoot; // 标记当前节点是否为根节点 
	BinTree left, right;
; // 一棵二叉树

BinTree genTree(int mode, int data)  // 生成二叉树结点的工具
	BinTree tree = (BinTree)malloc(sizeof(AbsTree));
	
	tree->left = NULL;
	tree->right = NULL;
	tree->isRoot = false;
	
	if(mode == MODE_NUM) tree->data = data;
	
	tree->mode = mode;
	
	return tree;


BinTree genAbsTree(char* lang)  // 生成抽象语法树并返回根节点
	BinTree root = NULL, left = NULL, right = NULL;
	 
	for(int i=0; i<strlen(lang); i++) 
		char elem = lang[i];
		
		bool isNum = isdigit(elem);
		
		if(isNum)  // 扫描到数字
			int num = elem - 48;

			 // 将字符串数字转化为数字[如 '123' -> 123]
			while(i+1 < strlen(lang) 
					&& isdigit(lang[i+1])) 
						
				num = num*10 + (lang[++i] - 48);	
			
			
			
			if(left == NULL) 
				left = genTree(MODE_NUM, num);
			
			else 
				right = genTree(MODE_NUM, num);
				root->right = right;
				root->left = left;
				left = root;
			
		
		else  // 扫描到非数字
			if (elem == ' ') continue;
			
			root = genTree(MODE_CHAR, -1);
			root->left = left;
		
	
	
	if (root!=NULL) root->isRoot = true; // 标记当前结点为根节点 

	return root; 
 
生成目标代码
// 树的后序遍历生成目标代码
void genTargetCode(BinTree node) 
	if(node == NULL) return;
	genTargetCode(node->left);
	genTargetCode(node->right);
	
	if (node->mode == MODE_NUM) 
		printf("c.push(%d);\\n", node->data);
	
	else 
		printf("c.add();\\n");
	
	
	if(node->isRoot) printf("c.print();\\n");

测试
int main() 
	char sum_exp[100] = "1 + 10 + 100";
	
	BinTree root = genAbsTree(sum_exp);
	
	genTargetCode(root);
 

运行之后生成目标代码正确。

以上是关于Hello Compiler的主要内容,如果未能解决你的问题,请参考以下文章

[An Introduction to GCC 学习笔记] 15 How the compiler works, Identifying files

[An Introduction to GCC 学习笔记] 15 How the compiler works, Identifying files

Vue 环境搭建之Hello World

gcc 中-lfoo表示啥意思。 这个中gcc foo.c -L /home/lib -lfoo -o hello

CS:APP CH01.A Tour of Computer Systems

Android Hello-World 编译错误:Intellij 找不到 aapt