命令行编译_教你用Python学编译原理,保姆级教程(一)

从编译器说起

编译器是将一种语言(源语言)编写的代码翻译成另一种语言(目标语言)的程序。比如GCC编译器将C和C++源代码编译成机器语言,Go语言编译器将Go语言的源代码编译成机器语言,Java编译器将Java源代码编译成字节码,当然也可以不局限在编程语言。编译的过程通常十分复杂,所以被分为了多个中间步骤进行处理,如下图所示。编译器可以手工实现,但是费时费力,也可以用生成工具实现其中的某些步骤,比较著名的前端的生成工具有FlexBisonANTLR等等,后端工具如LLVM

命令行编译_教你用Python学编译原理,保姆级教程(一)_第1张图片

ANTLR的作用

ANTLR是一个词法分析器(lexer)和语法分析器(parser)的生成工具,可以根据语法文件自动生成的解析器可以实现编译器前端的词法分析语法分析、以及一部分语义分析的功能。

命令行编译_教你用Python学编译原理,保姆级教程(一)_第2张图片

使用ANTLR的好处在于可以快速开发解析器,生成的解析器代码称为代码生成目标(code generation targets),ANTLR支持多种语言的生成目标,目前ANTLR支持生成以下几种语言的解析器:Java、Python2、Python3、JavaScript、Go、C++、Swift、PHP、DART,更详细的资料可以看这里

命令行编译_教你用Python学编译原理,保姆级教程(一)_第3张图片

既然用ANTLR开发解析器如此方便,那么首先我们从下载安装开始,看一下如何使用ANTLR。

下载安装ANTLR

ANTLR本身是用Java开发的,所以我们需要先安装JDK才可以使用ANTLR。安装完JDK后可以在ANTLR官网的下载页面下载ANTLR二进制jar文件,目前最新版是ANTLR 4.9,直接下载的链接在这里

Linux和MacOS系统:

配置环境变量,在~/.bashrc~/.zshrc添加以下几行:

export CLASSPATH=".:/usr/local/lib/antlr-4.9-complete.jar:$CLASSPATH"
alias antlr='java org.antlr.v4.Tool'
alias grun='java org.antlr.v4.gui.TestRig'

注意:上面的/usr/local/lib/antlr-4.9-complete.jar只是例子,你需要改成自己的jar文件路径。

保存后执行source ~/.bashrcsource ~/.zshrc

Windows系统

首先需要将antlr-4.9-complete.jar文件的目录添加到环境变量CLASSPATH中,比如配置为.;C:librariesantlr-4.9-complete.jar

然后创建以下两个批处理文件:

antlr.bat

java org.antlr.v4.Tool %*

grun.bat

java org.antlr.v4.gui.TestRig %*

保存后将这两个文件的目录添加到环境变量PATH中,便可以在命令行中执行antlrgrun命令。

运行ANTLR

打开任意命令行,输入命令antlrgrun,如果输出以下文字,说明安装成功:

$ antlr
ANTLR Parser Generator  Version 4.9
 -o ___              specify output directory where all output is generated
 -lib ___            specify location of grammars, tokens files
 -atn                generate rule augmented transition network diagrams
 ...
​
$ grun
java org.antlr.v4.gui.TestRig GrammarName startRuleName
  [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]
  ...

示例

ANTLR语法文件的语言称为元语言(ANTLR Meta Language),文件名以.g4结尾。我们首先创建一个简单的语法文件:

Hello.g4

grammar Hello; // 定义语法Hello,必须与文件名相同
​
r : 'hello' ID ;
ID : [a-z]+ ;
WS : [ trn]+ -> skip ; // 跳过空白符

保存在命令行中执行antlr Hello.g4,会生成多个java文件,其中HelloLexer.java由上面的Hello.g4文件生成的词法分析器,HelloParser.java是生成的语法分析器,运行javac *.java编译,接下来运行grun Hello r -gui测试。

在命令行输入hello antlr回车,然后输入结束符(Windows系统CTRL+Z,Linux系统CTRL+D),会在图形界面中显示解析的结果:

命令行编译_教你用Python学编译原理,保姆级教程(一)_第4张图片

如果只输入hello,则会清楚地显示缺少ID

命令行编译_教你用Python学编译原理,保姆级教程(一)_第5张图片

也可以改用-tokens-tree参数。

grun Hello r -tokens  # 输出token stream
grun Hello r -tree  # 输出LISP格式的parse tree

更多的语法文件可以在Github上找到,比如这个repo。

命令参数列表

antlr 命令参数:

ANTLR Parser Generator  Version 4.8
 -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
 -long-messages      show exception details when available for errors and warnings
 -listener           generate parse tree listener (default)
 -no-listener        don't generate parse tree listener
 -visitor            generate parse tree visitor
 -no-visitor         don't generate parse tree visitor (default)
 -package ___        specify a package/namespace for the generated code
 -depend             generate file dependencies
 -D
  • -o:生成代码的目录
  • -lib:token文件的目录
  • -atn:生成atn
  • -encoding:语法文件的编码
  • -listener:生成listener,默认
  • -no-listener:不生成listener
  • -visitor:生成visitor
  • -no-visitor:不生成visitor,默认
  • -package:指定生成代码的包
  • -D:语法选项,比如-Dlanguage=Python3输出Python3实现的解释器

grun(grammar run)命令参数:

java org.antlr.v4.gui.TestRig GrammarName startRuleName
  [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]
  [-trace] [-diagnostics] [-SLL]
  [input-filename(s)]
Use startRuleName='tokens' if GrammarName is a lexer grammar.
Omitting input-filename makes rig read from stdin.
  • -tokens:打印token stream词法单元流
  • -tree:打印parse tree解析树,LISP格式
  • -gui:可视界面
  • -ps:生成PostScript文件
  • -encoding:编码
  • -trace:打印rule name和进入退出rule时的当前token
  • -diagnostics:输出诊断信息
  • -SLL:使用更快但是稍弱一些的解析策略

你可能感兴趣的:(命令行编译)