提起软件工程中最复杂的一类软件,编译器绝对名列前矛。除了最传统的编译之外,下面这些功能的实现也和编译密切相关:
- 很多语言都已经具备的REPL环境;
- 编辑器中的代码高亮、各种Lint工具以及智能提示;
因此,可以说,无论你使用什么编程语言工作,这门源自计算机上古时代的技术都在和你产生着关联。然而,一门编程语言究竟是如何设计出来的?计算机究竟是如何把文本变成执行程序的?如何让编译器支持各种不同的硬件架构?为什么编译器可以生成比手工汇编更优秀的执行代码?可以说,在编译器背后,蕴藏着一座巨大的知识宝库,一旦你打开它,那些数据结构、那些算法、那些重要观念、那些编程实践中最重要最根本的珍宝,那些在你脑中蛰伏已久仿佛已经还给老师的记忆,将重新在你眼前闪闪发光 :)
emm...
当然,说的虽然挺好,但是,不可否认的事情是,学习编译原理并不容易。因为其中很多抽象的观念,我们很难通过形象的方式或者简单的代码片段得以实践。但是,很难,不等于不可以。而这,就是我们这个系列的目的。在开始动手实现一门简单的编程语言之前,我们先来介绍一个工具:Antlr。
现在,先不用管这个工具到底是干嘛的,我们直接把工作环境安装并搭建起来。在接下来的例子中,我们会随用,随着讲到它的各种功能。
准备Antlr环境
首先,Antlr是一个基于Java开发的工具,因此,你要先给自己的电脑安装Java环境。直接在这里下载对应操作系统版本的JDK安装包就好了。完成后,在终端执行java -version
,能够看到类似下面这样的结果就好了:
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
其次,我们来安装Antlr,直接按照官网给出的步骤就行了:
cd /usr/local/lib
sudo curl -O https://www.antlr.org/download/antlr-4.7.1-complete.jar
完成后,根据你使用的Terminal,把下面这三行内容添加到.zshrc
或者.bashrc
中:
export CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH"
alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool'
alias grun='java org.antlr.v4.gui.TestRig'
这里,你不了解Java也完全没关系,我们只是创建了两个命令的别名,其中:antlr4
表示执行Antlr工具自身;grun
是一个帮助我们测试语法的工具。下一节,我们会用到。
添加完成后,更新一下Termianl环境,然后直接执行antlr4
,如果可以看到帮助信息,就表示安装好了:
➜ ~ antlr4
ANTLR Parser Generator Version 4.7.1
-o ___ specify output directory where all output is generated
-lib ___ specify location of grammars, tokens files
-atn generate rule augmented transition network diagrams
-encoding ___ specify grammar file encoding; e.g., euc-jp
-message-format ___ specify output style for messages in antlr, gnu, vs2005
...
准备VS Code环境
ANTLR4 grammar syntax support
准备好Antlr环境之后,我们还要准备一个IDE进行开发。这里,推荐大家使用VS Code。一来,它免费并且足够好用;二来,它可以让我们更方便的从0开始构建一个Antlr项目。
安装好VS Code之后,我们还需要安装一个叫做ANTLR4 grammar syntax support的插件:

如上图中,在Extension中搜索antlr,第一个结果就是了。除了可以高亮显示语法和智能提示之外,这个插件还有很多强大的功能帮助我们理解编程语言的语法设计,稍后用到的时候,我们就会看到。
接下来,我们按Cmd + ,
打开VS Code设置,在右侧用户设置中,添加下面的配置:
"antlr4.generation": {
"mode": "external",
"language": "Cpp",
"outputDir": "antlr4-runtime",
"listeners": true,
"visitors": true
}
其中:
outputDir
表示Antlr生成文件保存的目录;language
表示让Antlr基于定义的语法文件生成对应的C++代码框架。在下一节就会看到,我们会通过Antlr,根据自己编写的语法文件生成C++文件,并基于这些生成的文件进行开发。当然,C++并不是唯一的选择,Antlr还可以基于语法文件生成Java / Python / C# / JS / Go / Swift版本的开发框架,这些生成的目标语言版本,在Antlr中,叫做Target。大家完全可以掌握了思路之后,使用自己更为熟悉的语言;
当然,你不理解这些配置也完全没问题。现在,大概有个概念就足够了。
C++
上面,由于我们选择了生成C++模板,除了支持Antlr的插件之外,我们还要安装一个C++插件:

这是微软官方为VS Code提供的C++支持。等用到的时候,我们再来讲它的具体配置方法。
What's next?
至此,开始研究编译原理的初期准备工作就结束了。下一节,我们通过定义并解析一个最简单的语法,来感性了解下编译器处理语法的第一步:词法分析。