编译器之旅
在这个 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 部分:Lvalues 和 Rvalues 重新审视
- 第 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 部分:错误修复和更多运算符
- 第 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 的新后端
未来部分没有安排或时间表,所以请继续查看这里,看看我是否已经写了更多。
版权
我借用了一些代码和很多想法,来自 Nils M Holm 编写的 SubC 编译器。他的代码是公有领域的。我认为我的代码有着足够大的不同,可以对我的代码应用不同的许可证。
除非另有说明,
- 所有源代码和脚本均为 Warren Toomey 在 GPL3 许可下的版权所有。
- 所有非源代码文档(例如英文文档、图像文件)均为 Warren Toomey 在 Creative Commons BY-NC-SA 4.0 许可下的版权所有。