在上篇博客《ANTLR4入门(二):图示说明eclipse安装Antlr4IDE插件的过程》,我费半天劲装好了Eclise的AntlrIDE插件,简单的创建一个ANTLR 4 工程,感受了一下AntlrIDE插件提供的语法高亮的便利性。及语法文件(.g4)自动生成解析器代码的过程
然而热乎劲儿过后,我发现这个插件对于入门学习或许有用,但在基于maven构建的工程开发中实用性并不大,除了语法高亮比较方便外。
在maven管理的项目中,项目编译可以在命令行进行并不一定依赖Eclipse等IDE环境。所以在maven项目中需要使用ANTL4 Maven插件(antlr4-maven-plugin)来实现语法文件到解析器代码的生成。
本文以示例说明如何在项目pom.xml中通过使用ANTLR 4 Maven 插件,来完成语法文件(.g4)自动生成解析器代码,
为了学习ANTLR4插件的使用,我创建了一个antlr4-demo项目,完整的代码放在码云仓库:https://gitee.com/l0km/antlr4-demo.git 供参考
ANTLR 工具命令行选项
在之前的博客《ANTLR4入门(一):Windows安装antlr4命令行环境》,我们知道通过命令行就能执行解析器代码自动生成。如下是命令行执行 antlr-4.11.1-complete.jar显示的命令行参数说明:
D:\os.package\devtools\antlr4>antlr4.bat
ANTLR Parser Generator Version 4.11.1
-o ___ specify output directory where all output is generated(指定所有的生成文件的输出位置)
-lib ___ specify location of grammars, tokens files(指定语法和tokens)文件的位置
-atn generate rule augmented transition network diagrams(生成规则增强转移网络图)
-encoding ___ specify grammar file encoding; e.g., euc-jp(指定语法文件的编码,例如:utf-8)
-message-format ___ specify output style for messages in antlr, gnu, vs2005(指定消息的输出风格:antlr/gun/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<option>=value set/override a grammar-level option(以Key=Value形式设定/覆盖一个语法级的选项)
-Werror treat warnings as errors(将警告当做错误处理)
-XdbgST launch StringTemplate visualizer on generated code(对生成的代码启动StringTemplate可视化器)
-XdbgSTWait wait for STViz to close before continuing
-Xforce-atn use the ATN simulator for all predictions(对所有的预测启动ATN模拟器)
-Xlog dump lots of logging info to antlr-timestamp.log(将详细日志保存为antlr-timestamp.log)
-Xexact-output-dir all output goes into -o dir regardless of paths/package(所有输出写入-o dir指定的位置,忽略路径和包)
关于命令行的详细说明参见:https://github.com/antlr/antlr4/blob/master/doc/tool-options.md
ANTLR 4 Mave 插件(org.antlr:antlr4-maven-plugin)本身也有一些参数定义,从插件执行和命令行执行最终都运行相同的程序。所以这两个体系提供的参数有重合。命令行参数也可以通过插件的arguments
参数来指定
关于插件的参数说明参见 :《ANTLR 4 Maven plugin》
说实话,这个Maven插件写的质量不怎么样,参数设计有些混乱,我是经过很长时间尝试才让插件运行正常,如下是插件设置的完整内容,详细说明参见pom.xml中的注释:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.l0km</groupId>
<artifactId>antlr4-demo</artifactId>
<version>0.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>antlr4-demo</name>
<url>https://gitee.com/l0km/antlr4-demo</url>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- ANTLR 4 从4.10 版本后最低要求的JDK版本升到了11,所以如果还想在JDK8下运行行ANTLR4可以只能使用4.9.3 -->
<antlr4.vesion>4.9.3</antlr4.vesion>
<!-- <antlr4.vesion>4.11.1</antlr4.vesion> -->
<!-- 定义antlr4插件输出生成代码的位置-->
<antlr4.dir>${project.build.directory}/generated-sources/antlr4</antlr4.dir>
<!--
如果希望将antlr4生成的代码加入git版本控制,
就不能将antlr4.dir定义在${project.build.directory}文件夹下,如下定义在src文件夹中 -->
<!--<antlr4.dir>${basedir}/src/antlr4/java</antlr4.dir>-->
<!-- surefire 插件 跳过测试 -->
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!-- 增加antlr4 运行时库依赖 -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${antlr4.vesion}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 执行插件 antlr4:antlr4,根据语法文件(.g4)生成解析器(java)代码
完整说明参见 antlr4-maven-plugin 官方文档:
https://www.antlr.org/api/maven-plugin/latest/plugin-info.html
也可以命令行执行 mvn antlr4:help -Ddetail=true -Dgoal=antlr4 查看在线说明
-->
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>${antlr4.vesion}</version>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
<configuration>
<arguments>
<!-- 命令行参数 -package ${package} 定义生成java代码的包名-->
<argument>-package</argument>
<argument>com.gitee.l0km.parser</argument>
<!-- 输出生成的Java源码文件位置
这里的输出文件夹定义一定要与上面 -package 定义的包名匹配
-->
<argument>-o</argument>
<argument>${antlr4.dir}/com/gitee/l0km/parser</argument>
</arguments>
<!-- 指定语法文件的编码方式,默认utf-8 -->
<!--<inputEncoding>utf-8</inputEncoding>-->
<!-- ANTLR 语法文件(.g4) 所在位置-->
<sourceDirectory>${basedir}/src/main/java/com/gitee/l0km/parser</sourceDirectory>
<!-- 生成语法树侦听器(Listener)代码,默认为true -->
<listener>true</listener>
<!-- 生成语法树访问器(Visitor)代码,默认为false-->
<visitor>true</visitor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 不建议使用插件的
outputDirectory
参数指定输出文件夹。如上pom.xml,使用命令行参数-o
代替。 - 因为所有的解析代码器都可以由语法文件生成,所以ANTLR4一般将生成的解析器代码视为中间文件,所以在本例中,也是一样,将生成的解析器代码放在了target文件夹,也就是没有保存,如果希望保存,那就换个文件夹不要指向target。
Maven执行
在antlr4-demo下执行mvn install
,如下即可看到antlr4-maven-plugin
的执行输出
guyadong@guyadong-PC MINGW64 /j/antlr4-demo (master)
$ mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< com.gitee.l0km:antlr4-demo >---------------------
[INFO] Building antlr4-demo 0.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- antlr4-maven-plugin:4.9.3:antlr4 (default) @ antlr4-demo ---
[INFO] ANTLR 4: Processing source directory J:\antlr4-demo\src\main\java\com\gitee\l0km\parser
[INFO] Processing grammar: Hello.g4
[INFO]
[INFO] --- build-helper-maven-plugin:3.0.0:add-source (add-source) @ antlr4-demo ---
[INFO] Source directory: J:\antlr4-demo\target\antlr4-generated\java added.
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ antlr4-demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory J:\antlr4-demo\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ antlr4-demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 7 source files to J:\antlr4-demo\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ antlr4-demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory J:\antlr4-demo\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ antlr4-demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to J:\antlr4-demo\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ antlr4-demo ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ antlr4-demo ---
[INFO] Building jar: J:\antlr4-demo\target\antlr4-demo-0.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ antlr4-demo ---
[INFO] Installing J:\antlr4-demo\target\antlr4-demo-0.0.0-SNAPSHOT.jar to J:\maven_repository\com\gitee\l0km\antlr4-demo\0.0.0-SNAPSHOT\antlr4-demo-0.0.0-SNAPSHOT.jar
[INFO] Installing J:\antlr4-demo\pom.xml to J:\maven_repository\com\gitee\l0km\antlr4-demo\0.0.0-SNAPSHOT\antlr4-demo-0.0.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.002 s
[INFO] Finished at: 2022-12-19T16:39:35+08:00
[INFO] ------------------------------------------------------------------------
JDK8下执行
ANTLR 4 从4.10 版本后最低要求的JDK版本升到了11,所以如果还想在JDK8下支行ANTLR4可以只能使用4.9.3
如果希望在不改变自己的当前默认JDK版本的情况使用最新的ANTLR4版本,建议使用如下脚本来执行mvn命令
mvn11.bat
@ECHO OFF
SETLOCAL
SET JAVA_HOME=C:\Program Files\Java\jdk-11.0.11
SET PATH=%JAVA_HOME%\bin;%PATH%
mvn %*
ENDLOCAL
代码结构
用Eclipse打开antlr4-demo,显示的项目结构如下:
完整的代码放在码云仓库:https://gitee.com/l0km/antlr4-demo.git
参考资料
《ANTLR 4 Maven plugin》
《ANTLR 工具命令行选项》