编译原理实战:从 0 手写编译器,并在真实云主机上跑通
编译原理实战系列 · 总览 / 开篇
为什么写这个系列
编译原理是计算机科学里最"硬核"、也最"实用"的基石之一。可现实里很多工程师对它的印象停留在:课本上抽象的正则文法、推得人头大的 First/Follow 集合、永远调不对的移进-规约冲突。
这个系列反其道而行——不堆理论,只动手。我用 Python 在真实云主机(华为云 4 台 FlexusX,Ubuntu 24.04,2vCPU/2GB)上,亲手把编译器从前端到后端、从玩具到业务场景,一行行写出来并真实跑通。所有贴出的输出,都是机器实测,没有一行是"想象"的。
参考主线是宫文学在极客时间的《编译原理》课程结构:先实现一门脚本语言(解释型),再实现一门编译型语言(生成目标代码 + LLVM + 优化),最后落到 SQL 解析、报表工具等真实业务。
你会读到什么
| 篇目 | 主题 | 云主机 | 核心产出 |
|---|---|---|---|
| 01 前端:手写脚本语言 | 词法分析 / 递归下降语法分析 / 作用域 / 闭包 / 面向对象 / 语义分析 | m1 | 一门可运行的脚本语言 PlayScript 解释器 |
| 02 后端:汇编与 LLVM | x86-64 汇编生成 / LLVM IR / 常量折叠 / 死代码消除 | m2 | 同一门语言编译到汇编与 LLVM IR 并运行 |
| 03 算法:正则引擎与 VM | Thompson NFA / 子集构造 / DFA 最小化 / 栈式字节码 VM | m3 | 一个正则引擎 + 一个字节码虚拟机 |
| 04 应用:SQL 与报表 | SQL 解析与分库分表透明路由 / 报表模板 DSL / 动态代理 | m4 | 两个可直接套进业务的编译技术应用 |
工作方式与实验环境
为了体现"多 agent 协同、真机实操",我把 4 个相对独立的主题分别部署到 4 台独立的云主机上并行推进,每台机器只跑自己那部分代码,互不干扰,也便于复现:
- m1
139.9.136.51— 前端脚本语言(纯 Python,无需安装) - m2
1.92.96.10— 后端代码生成(gcc 13.3 + clang 18 / llvm) - m3
117.78.4.177— 正则引擎与字节码 VM(纯 Python) - m4
124.70.85.75— SQL 解析与报表模板(纯 Python)
所有代码都通过run_all.sh在对应机器上一键运行,输出保存在output.txt,博客中全部原样引用。
一键复现
# 任选一台机器(以 m1 为例)sshroot@139.9.136.51# 密码见仓库/任务说明gitclone<本仓库>cdcompiler/front python3 run_all.sh# 运行全部示例,输出落在 output.txt四台机器对应目录:front/、back/、vm/、app/,结构完全一致。
关键结论(先剧透)
- 编译器前端难在"取舍":二元表达式的优先级、左/右结合、成员访问与函数调用的后缀解析,递归下降里用"分层函数"就能优雅解决,比死记文法更可靠。
- 闭包和多态一点都不神秘:闭包 = 函数 + 捕获的环境对象;多态 = 运行时按对象实际类型查方法表。几行 Python 就能让直觉落地。
- 后端真正卡人的是"约定":调用约定、栈帧布局、寄存器分配——生成的汇编能不能跑,往往取决于有没有遵守 ABI。LLVM IR 则把这一步从你手里接走了。
- 优化必须"保语义":常量折叠、死代码消除之所以安全,是因为它们只对"不影响可观测结果"的部分动手;正确性永远优先于性能。
逐篇点进去看代码和真实输出即可。建议按 01 → 02 → 03 → 04 的顺序阅读,难度与抽象层级逐级抬升。
本系列所有代码与博客均已在华为云 ECS 真实运行验证。仓库地址见文末。