编译器编写之旅
在这个 Github 仓库中,我记录了我编写一个自编译编译器的过程,该编译器用于 C 语言的一个子集。我还详细写出了过程,这样如果你想跟随学习,就能了解我做了什么、为什么这么做,以及一些编译器理论的参考。
但不会涉及太多理论,我希望这是一次实践性的旅程。
以下是我目前已完成的步骤:
- 第 0 部分: 旅程介绍
- 第 1 部分: 词法扫描简介
- 第 2 部分: 语法分析简介
- 第 3 部分: 运算符优先级
- 第 4 部分: 一个实际的编译器
- 第 5 部分: 语句
- 第 6 部分: 变量
- 第 7 部分: 比较运算符
- 第 8 部分: If 语句
- 第 9 部分: While 循环
- 第 10 部分: For 循环
- 第 11 部分:函数,第 1 部分
- 第 12 部分: 类型,第 1 部分
- 第 13 部分:函数,第 2 部分
- 第 14 部分: 生成 ARM 汇编代码
- 第 15 部分: 指针,第 1 部分
- 第 16 部分: 正确声明全局变量
- 第 17 部分:更好的类型检查和指针偏移
- 第 18 部分:重新审视左值和右值
- 第 19 部分: 数组,第 1 部分
- 第 20 部分:字符和字符串字面量
- 第 21 部分:更多运算符
- 第 22 部分:局部变量和函数调用的设计思路
- 第 23 部分:局部变量
- 第 24 部分:函数参数
- 第 25 部分:函数调用和参数
- 第 26 部分: 函数原型
- 第 27 部分:回归测试和一个惊喜
- 第 28 部分:添加更多运行时标志
- 第 29 部分: 小规模重构
- 第 30 部分:设计结构体、联合体和枚举
- 第 31 部分:实现结构体,第 1 部分
- 第 32 部分:访问结构体成员
- 第 33 部分: 实现联合体和成员访问
- 第 34 部分:枚举和类型定义
- 第 35 部分: C 预处理器
- 第 36 部分:
break
和continue
- 第 37 部分: Switch 语句
- 第 38 部分:悬垂 else 和更多内容
- 第 39 部分:变量初始化,第 1 部分
- 第 40 部分:全局变量初始化
- 第 41 部分:局部变量初始化
- 第 42 部分: 类型转换和 NULL
- 第 43 部分:bug 修复和更多运算符
- 第 44 部分:常量折叠
- 第 45 部分:重新审视全局变量声明
- 第 46 部分:void 函数参数和扫描变更
- 第 47 部分:
sizeof
的子集 - 第 48 部分:
static
的子集 - 第 49 部分: 三元运算符
- 第 50 部分: 收尾工作,第 1 部分
- 第 51 部分: 数组,第 2 部分
- 第 52 部分: 指针,第 2 部分
- 第 53 部分: 收尾工作,第 2 部分
- 第 54 部分: 寄存器溢出
- 第 55 部分:惰性求值
- 第 56 部分: 局部数组
- 第 57 部分: 收尾工作,第 3 部分
- 第 58 部分:修复指针增减
- 第 59 部分: 为什么它不工作,第 1 部分
- 第 60 部分: 通过三重测试
- 第 61 部分: 接下来做什么?
- 第 62 部分: 代码清理
- 第 63 部分: 使用 QBE 的新后端
- 第 64 部分: 6809 CPU 的后端
未来部分没有固定的时间表,请经常回来查看我是否写了更多内容。
版权
我借鉴了一些代码和很多想法,来自 Nils M Holm 编写的 SubC 编译器。他的代码属于公共领域。我认为我的代码有足够大的差异,可以使用不同的许可证。
除非另有说明,
- 所有源代码和脚本均为 Warren Toomey 所有,采用 GPL3 许可证。
- 所有非源代码文档(如英文文档、图像文件)均为 Warren Toomey 所有,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可证。