编译器开发系列--Ocelot语言1.抽象语法树
从今天开始研究开发自己的编程语言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.抽象语法树的更多相关文章
- 编译器开发系列--Ocelot语言3.类型名称的消解
"类型名称的消解"即类型的消解.类型名称由TypeRef 对象表示,类型由Type 对象表示.类型名称的消解就是将TypeRef 对象转换为Type 对象. TypeResolve ...
- 编译器开发系列--Ocelot语言2.变量引用的消解
"变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...
- 编译器开发系列--Ocelot语言7.中间代码
Ocelot的中间代码是仿照国外编译器相关图书Modern Compiler Implementation 中所使用的名为Tree 的中间代码设计的.顾名思义,Tree 是一种树形结构,其特征是简单, ...
- 编译器开发系列--Ocelot语言6.静态类型检查
关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...
- 编译器开发系列--Ocelot语言5.表达式的有效性检查
本篇将对"1=3""&5"这样无法求值的不正确的表达式进行检查. 将检查如下这些问题.●为无法赋值的表达式赋值(例:1 = 2 + 2)●使用非法的函数 ...
- 编译器开发系列--Ocelot语言4.类型定义的检查
这里主要介绍一下检查循环定义的结构体.联合体.是对成员中包含自己本身的结构体.联合体进行检查.所谓"成员中包含自己本身",举例来说,就是指下面这样的定义. struct point ...
- javascript编写一个简单的编译器(理解抽象语法树AST)
javascript编写一个简单的编译器(理解抽象语法树AST) 编译器 是一种接收一段代码,然后把它转成一些其他一种机制.我们现在来做一个在一张纸上画出一条线,那么我们画出一条线需要定义的条件如下: ...
- 从零写一个编译器(九):语义分析之构造抽象语法树(AST)
项目的完整代码在 C2j-Compiler 前言 在上一篇完成了符号表的构建,下一步就是输出抽象语法树(Abstract Syntax Tree,AST) 抽象语法树(abstract syntax ...
- JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
随机推荐
- Jquery的点击事件,三句代码完成全选事件
先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- ABP文档 - 目录
ABP框架 概览 介绍 多层结构 模块系统 启动配置 多租户 集成OWIN 共同结构 依赖注入 会话 缓存 日志 设置管理 时间 领域层 实体 值对象(新) 仓储 领域服务 工作单元 领域事件(Eve ...
- 异常处理汇总 ~ 修正果带着你的Net飞奔吧!
经验库开源地址:https://github.com/dunitian/LoTDotNet 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983 ...
- xpath提取多个标签下的text
title: xpath提取多个标签下的text author: 青南 date: 2015-01-17 16:01:07 categories: [Python] tags: [xpath,Pyth ...
- 在 SAE 上部署 ThinkPHP 5.0 RC4
缘起 SAE 和其他的平台有些不同,不能在服务器上运行 Composer 来安装各种包,必须把源码都提交上去.一般的做法,可能是直接把源码的所有文件复制到目录中,添加到版本库.不过,这样就失去了与上游 ...
- 在Windows上编译和调试CoreCLR
生成CoreCLR - Windows篇 本文的唯一目的就是让你运行Hello World 运行环境 Window 7+ Visual studio 2015 确保C++ 工具已经被安装,默认是不安装 ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
- 【干货分享】流程DEMO-合同会审表
流程名: 合同会审表 业务描述: 合同的审批及签订 流程相关文件: 流程包.xml 事务呈批表业务服务.xml 事务呈批表主数据.xml 流程说明: 1.此流程必须先进行事务呈批表流程的配置才可 ...
- 在Ubuntu下搭建Spark群集
在前一篇文章中,我们已经搭建好了Hadoop的群集,接下来,我们就是需要基于这个Hadoop群集,搭建Spark的群集.由于前面已经做了大量的工作,所以接下来搭建Spark会简单很多. 首先打开三个虚 ...
- Java
2016-12-17 21:10:28 吉祥物:Duke(公爵) Logo:咖啡(爪哇岛盛产咖啡) An overview of the software development proce ...