ANTLR4入门:使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ANTLR4入门:使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器相关的知识,希望对你有一定的参考价值。

在上篇博客《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] ------------------------------------------------------------------------

Java 8下执行

ANTLR 4 从4.10 版本后最低要求的JDK版本升到了Java 11,所以如果在Java 8上运行ANTLR4只能使用4.9.3以下的版本。
如果希望在不改变自己的当前默认JDK版本的情况使用最新的ANTLR4版本,建议使用如下脚本来执行mvn命令
mvn11.bat – 使用Java 11执行MAVEN命令

@ECHO OFF
SETLOCAL
SET JAVA_HOME=C:\\Program Files\\Java\\jdk-11.0.11
SET PATH=%JAVA_HOME%\\bin;%PATH%
mvn %*
ENDLOCAL

SETLOCAL/ENDLOCAL指令之间SET定义/修复的环境变量都只作用于当前脚本,不会影响系统的环境变量

代码结构

用Eclipse打开antlr4-demo,显示的项目结构如下:

完整的代码放在码云仓库:https://gitee.com/l0km/antlr4-demo.git

参考资料

《ANTLR 4 Maven plugin》
《ANTLR 工具命令行选项》

以上是关于ANTLR4入门:使用mave ANTLR4插件(antlr4-maven-plugin)执行语法解析生成器的主要内容,如果未能解决你的问题,请参考以下文章

ANTLR4入门:图示说明eclipse安装Antlr4IDE插件的过程

ANTLR4入门:图示说明eclipse Antlr4IDE插件的安装及语法测试过程

1.ANTLR4 helloworld基础开发与IDEA插件使用

1.ANTLR4 helloworld基础开发与IDEA插件使用

ANTLR4入门:Windows安装antlr4命令行环境

ANTLR4入门:Windows安装antlr4命令行环境