从今天开始研究开发自己的编程语言Ocelot,从《自制编译器》出发,然后再自己不断完善功能并优化。

编译器前端简单,就不深入研究了,直接用现成的一款工具叫JavaCC,它可以生成抽象语法树,抽象语法树是生成中间代码的关键,而中间代码又是生成后端代码的关键。

整个编译器代码采用java语言编写,主要功能是对JavaCC生成的抽象语法树进行语义分析、优化,最后生成优化后的汇编代码,然后再用汇编器对汇编代码汇编生成机器码,最后再用命令链接生成Linux可执行文件,就可以直接在Linux上运行了。

整个编译器采用的语法基本上都是C语言的语法,去除掉一些语法成C语言简化版,而且原项目并无优化。我想做的是在原项目的基础上对其各种优化并使其支持垃圾回收。- -!有的玩了。

抽象语法树和其节点都是继承自Node类。介绍一下Node 类群的继承层次:

再来通过一个简单的helloworld小demo来查看抽象语法树的结构,demo如下所示:

int main(int argc, char **argv)
{
int i, j = 5;
if (i) {
return (j * 1 - j);
}
else {
exit(1);
}
}

编译器项目运行后生成的抽象语法树如下所示:

<<AST>> (G:\编译原理\自制编译器\源码\test\hello.cb:1)
variables:
functions:
<<DefinedFunction>> (G:\编译原理\自制编译器\源码\test\hello.cb:1)
name: "main"
isPrivate: false
params:
parameters:
<<Parameter>> (G:\编译原理\自制编译器\源码\test\hello.cb:1)
name: "argc"
typeNode: int
<<Parameter>> (G:\编译原理\自制编译器\源码\test\hello.cb:1)
name: "argv"
typeNode: char**
body:
<<BlockNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:2)
variables:
<<DefinedVariable>> (G:\编译原理\自制编译器\源码\test\hello.cb:3)
name: "i"
isPrivate: false
typeNode: int
initializer: null
<<DefinedVariable>> (G:\编译原理\自制编译器\源码\test\hello.cb:3)
name: "j"
isPrivate: false
typeNode: int
initializer:
<<IntegerLiteralNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:3)
typeNode: int
value: 5
stmts:
<<IfNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:4)
cond:
<<VariableNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:4)
name: "i"
thenBody:
<<BlockNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:4)
variables:
stmts:
<<ReturnNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
expr:
<<BinaryOpNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
operator: "-"
left:
<<BinaryOpNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
operator: "*"
left:
<<VariableNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
name: "j"
right:
<<IntegerLiteralNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
typeNode: int
value: 1
right:
<<VariableNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:5)
name: "j"
elseBody:
<<BlockNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:7)
variables:
stmts:
<<ExprStmtNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:8)
expr:
<<FuncallNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:8)
expr:
<<VariableNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:8)
name: "exit"
args:
<<IntegerLiteralNode>> (G:\编译原理\自制编译器\源码\test\hello.cb:8)
typeNode: int
value: 1

1.<<AST>> 和<<DefinedFunction>> 表示节点的类名。

2.右侧所显示的(G:\编译原理\自制编译器\源码\test\hello.cb:1) 是该节点对应的语法所记载的文件名和行号。

3.缩进表示该节点被前一个节点引用。

编译器开发系列--Ocelot语言1.抽象语法树的更多相关文章

  1. 编译器开发系列--Ocelot语言3.类型名称的消解

    "类型名称的消解"即类型的消解.类型名称由TypeRef 对象表示,类型由Type 对象表示.类型名称的消解就是将TypeRef 对象转换为Type 对象. TypeResolve ...

  2. 编译器开发系列--Ocelot语言2.变量引用的消解

    "变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...

  3. 编译器开发系列--Ocelot语言7.中间代码

    Ocelot的中间代码是仿照国外编译器相关图书Modern Compiler Implementation 中所使用的名为Tree 的中间代码设计的.顾名思义,Tree 是一种树形结构,其特征是简单, ...

  4. 编译器开发系列--Ocelot语言6.静态类型检查

    关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...

  5. 编译器开发系列--Ocelot语言5.表达式的有效性检查

    本篇将对"1=3""&5"这样无法求值的不正确的表达式进行检查. 将检查如下这些问题.●为无法赋值的表达式赋值(例:1 = 2 + 2)●使用非法的函数 ...

  6. 编译器开发系列--Ocelot语言4.类型定义的检查

    这里主要介绍一下检查循环定义的结构体.联合体.是对成员中包含自己本身的结构体.联合体进行检查.所谓"成员中包含自己本身",举例来说,就是指下面这样的定义. struct point ...

  7. javascript编写一个简单的编译器(理解抽象语法树AST)

    javascript编写一个简单的编译器(理解抽象语法树AST) 编译器 是一种接收一段代码,然后把它转成一些其他一种机制.我们现在来做一个在一张纸上画出一条线,那么我们画出一条线需要定义的条件如下: ...

  8. 从零写一个编译器(九):语义分析之构造抽象语法树(AST)

    项目的完整代码在 C2j-Compiler 前言 在上一篇完成了符号表的构建,下一步就是输出抽象语法树(Abstract Syntax Tree,AST) 抽象语法树(abstract syntax ...

  9. JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧

    这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...

随机推荐

  1. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  2. 从源码看Azkaban作业流下发过程

    上一篇零散地罗列了看源码时记录的一些类的信息,这篇完整介绍一个作业流在Azkaban中的执行过程,希望可以帮助刚刚接手Azkaban相关工作的开发.测试. 一.Azkaban简介 Azkaban作为开 ...

  3. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  4. 【Web动画】SVG 实现复杂线条动画

    在上一篇文章中,我们初步实现了一些利用基本图形就能完成的线条动画: [Web动画]SVG 线条动画入门 当然,事物都是朝着熵增焓减的方向发展的,复杂线条也肯定比有序线条要多. 很多时候,我们无法人工去 ...

  5. iOS开发之App间账号共享与SDK封装

    上篇博客<iOS逆向工程之KeyChain与Snoop-it>中已经提到了,App间的数据共享可以使用KeyChian来实现.本篇博客就实战一下呢.开门见山,本篇博客会封装一个登录用的SD ...

  6. 读python源码--对象模型

    学python的人都知道,python中一切皆是对象,如class生成的对象是对象,class本身也是对象,int是对象,str是对象,dict是对象....所以,我很好奇,python是怎样实现这些 ...

  7. Entity Framework 手动使用migration里面的up 和down方法。

    add-migration -IgnoreChanges 201606100717405_201606100645298_InitialCreate 执行这一句后 ,清空使用map生成的代码,个人不太 ...

  8. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  9. Java虚拟机 JVM

    finalize();(不建议使用,代价高,不确定性大) 如果你在一个类中覆写了finalize()方法, 那么你可以在第一次被GC的时候,挽救一个你想挽救的对象,让其不被回收,但只能挽救一次. GC ...

  10. Android 指纹认证

    安卓指纹认证使用智能手机触摸传感器对用户进行身份验证.Android Marshmallow(棉花糖)提供了一套API,使用户很容易使用触摸传感器.在Android Marshmallow之前访问触摸 ...