LLVM平台,短短几年间,改变了众多编程语言的走向,也催生了一大批具有特色的编程语言的出现,不愧为编译器架构的王者,也荣获2012年ACM软件系统奖 —— 题记
版权声明:本文为 西风逍遥游 原创文章,转载请注明出处 西风世界 http://blog.csdn.net/xfxyy_sxfancy
语法树模型的基本结构
上次我们看了Lex和Yacc的翻译文件,可能一些朋友并不了解其中的执行部分,而且,对这个抽象语法树是怎么构建起来的还不清楚。今天我们就再详细介绍一下如果方便的构建一棵抽象语法树(AST)
Node节点链接的左孩子,右兄弟二叉树
AST语法树,由于是一棵多叉树,直接表示不大好弄,所以我们采用计算机树中的一个经典转换,将多叉树转换为左孩子右兄弟的二叉树。
其实思路很简单,每一层其实就是一个链表,将兄弟节点串起来,这样就可以了。
class Node
{
public:
Node();
Node(Node* n);
~Node();
// 构建列表部分
void addChildren(Node* n);
void addBrother (Node* n);
static Node* make_list(int num, ...);
static Node* getList(Node* node);
Node* getNext() { return next; }
Node* getChild() { return child; }
protected:
Node* next;
Node* child;
};
于是我们构建一个Node类,这就是上次我们脚本中看到的那个节点类。是不是很简单呢?
另外我们在写个make_list,方便我们构造一个链表,至于怎么写,我们一会儿再谈。
类型支持
我们发现,我们的语法树还不能保存任何数据,我们写AST,是为了在每个节点上存储数据的,有字符串、字符、整数、浮点数、标识符等等。
而且不但有这个要求,更重要的是语法树能够方便的构造LLVM语句,所以方便的一个设计就是利用多态,虽然效率或内存占用不像用union那么实在,但确实比较方便。
于是我们建立了一堆类,分别从Node派生,当然Node也需要添加一些功能来判断当前的节点类型。
Node.h
enum NodeType // 类型枚举
{
node_t = 0, int_node_t, float_node_t, char_node_t, id_node_t, string_node_t
};
class CodeGenContext;
class Node
{
public:
Node();
Node(Node* n); // 直接将n作为孩子加入这个节点下
~Node();
// 构建列表部分
void addChildren(Node* n);
void addBrother (Node* n);
bool isSingle();
static Node* make_list(int num, ...);
static Node* getList(Node* node);
void print(int k); // 打印当前节点
Node* getNext() { return next; }
Node* getChild() { return child; }
virtual Value* codeGen(CodeGenContext* context); LLVM的代码生成
// 这里负责获