关于编译原理的一下小见解
编译原理(compiler construction),旨在介绍编译程序构造的一般原理和基本方法,内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。 它大致包括两个方面,俗称前端和后端。前端的正式名称其实是 language recognition,工程上也称为 parsing。这实际上是整个计算机理论的一个楔入点。比如说,比较基础的 computation theory,也就是研究四种基本计算模型的理论,就是以 language recognition 为起始工具的。而且这个理论讨论了很多有意思的东西:
计算机可以用什么方法有效地「记忆」多久的历史?
注意这里的记忆是状态式的,有遗忘的记忆。和数据结构不同,数据结构是无限期的记忆。
计算模型的「能力(strength)」的定量比较:LL(n), LR(n), LALR 等等。
在 parsing 中利用数据结构和避免 explicit 数据结构的 trade-off。
可以说,学习 parsing 之于学些计算理论就像学习 OS kernel 之于数据结构和算法。虽然理论并不严密,但是更接近 real world。非常有趣。
后端的 code generation,理论并不成熟,所以一两本初始的教材也就是勉强让你能写一个功能完整的 compiler 而已。说实话,即使你不看教材,在学会 parsing 之后摸黑写一个 target to C 的 compiler 也并不难。
编译原理学过之后的益处包括:
1、可以更加容易的理解在一个语言种哪些写法是等价的,哪些是有差异的;
2、可以更加客观的比较不同语言的差异;
3、更不容易被某个特定语言的宣扬者忽悠;
4、学习新的语言是效率也会更高;
5、其实从语言a转换到语言b是一个通用的需求,学好编译原理处理此类需求时会更加游刃有余。
除此之外,编译原理是一门真正与代码做斗争的课程,对于一个有至于追求技术的人是不容错过的课程,而且编译原理可以说是一个计算机科学的缩影。你学习它更多的是去追寻程序设计语言的本质,如它在寄存器分配中将会使用到贪心算法,死代码消除中将会使用到图论算法,数据流分析中使用到的Fixed-Point Algorithm,词法分析与语法分析中使用到有限状态机与递归下降这样的重要思想等等,也许你以后不会成为一个编译器开发工作者,但是编译原理的学习中所获,所思的东西足以让你终生获益。
关于编译原理的学习,我们要掌握以下几点:
词法分析方面,掌握正则表达式,了解dfa/nfa;
Parsing 方面,能读懂BNF,知道AST,会写简单的递归下降parser,会用antlr之类的parser generator;
优化方面,知道现代编译器的优化能力有多强,知道如何配合编译器写出高效易读的代码,避免试图outsmart编译器;
会实现简单的虚拟机(stack-based,不带GC),并把四则运算表达式翻译为虚拟机指令。
编译原理并非随随便便就能入门的,一定要正视这个问题。编译原理的学习和实践通常基于对计算机编译过程、计算机基本工作原理、甚至一定的数学知识有一定积累,这些知识分别分布并应用在了编译原理的不同阶段。基于此,我们有以下方法:a. 学习 C 语言, 不要求熟悉, 但至少要弄明白指针的思想;
b. 学习数据结构, 尤其是对字符串/树/图的相关基本处理手段要非常熟悉;
c. 学习离散数学, 对树和图的相关理论要比较心中有数;
d. 学习汇编语言, 不要求熟悉这门语言, 但至少要弄明白汇编指令、数据在CPU和存储器之间的交互机制;
e. 着手学习编译原理, 推荐先找一本国内高校普遍使用的教材(比如胡元义的一本编译原理教程, 很一般, 但很适合先入门), 入门后(搞明白编译原理到底是要干嘛, 解决什么样的需求)马上扔掉转龙书、虎书、鲸书。
最后,编译原理并不仅仅只是一门理论课程,实践也是其重要的部分,只有理论和实践结合在一起,才能真正学好它。