本系列的第一篇,我想概述一下编译器的构造,同时帮助大家了解编译器中各个组成部分的用途。想必大家看别的编译原理书籍,大都在第一章或者序言之类的地方,将编译器分成许多模块,然后每一个模块负责编译的特定阶段,最后串起来组成完整的编译器。比如下面这张图就是虎书(Modern Compiler by Andrew W. Appel)第一章中出现的编译器阶段示意图:
除了简化设计之外,将编译器的各个阶段模块化还有更大的价值。原先我们认为编译器只要把源文件编译成最终的目标代码就好了。但是随着各种各样的开发工具出现——编辑器、自动完成、调试器、重构工具、测试覆盖率检测、性能剖析器…… 人们发现编译器编译过程中,各个阶段产生的结果都可能是非常有价值的。将编译器内部结构和中间结果暴露给用户是必然的趋势。比如Visual Studio下一代产品中将提供的Compiler as a Service特性,其做法就是将编译器的内部模块暴露给用户成为一种服务。我举几个例子可以让大家看到编译器模块的输出有哪些可能的用途: