ANTLR4入门:在线语法调试塈Maven项目中使用语法调试工具TestRig

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ANTLR4入门:在线语法调试塈Maven项目中使用语法调试工具TestRig相关的知识,希望对你有一定的参考价值。

ANTLR是一款强大的语法分析器生成工具,可用于读取、处理、执行和翻译结构化的文本和二进制文件。它被广泛用于学术领域和工业生产实践,是众多语言、工具和技术框架基石。
一门语言的正式描述称为语法(grammar),ANTLR能够为该语言生成一个语法分析器,并自动建立语法分析树,ANTLR也能够自动生成树遍历器(Visitor),这样你就可以访问树中的节点,执行自定义的业务逻辑。
在设计自己的语法时,需要不断的通过测试来验证语法,ANTLR为语法的开发过程的测试提供简单但有效的调试工具,本文介绍ANTLR的两种语法调试方式。

在线语法调试工具/lab.antlr.org

lab.antlr.org是ANTLR提供的在线语法调试工具地址。

你可以如下将自己的语法文件复制(也支持鼠标拖拽)到Parser输入区,在输入文本区输入要测试的文本,执行Run就会生成图形化的语法分析树.

如果没有独立的词法文件,要将“Lexer”部分清空


lab.antlr.org对于简单语法测试以及参考ANTLR已经有的语法文件是很有帮助的。

离线语法调试工具/TestRig

ANTLR库中提供了一个名为TestRig的语法调试工具。它可以详细列出一个语法解析器在匹配输入文本过程中的信息,这些输入文本可以来自文件或者控制台标准输入。TestRig使用Java的反射机制来调用编译后的语法解析程序。它可以提供与在线语法调试工具lab.antlr.org差不多同样的离线语法调试功能。

在我之前博客《ANTLR4入门(一):Windows安装antlr4命令行环境》中有说明过TestRig工具Windows下的安装使用方式。这些内容也是我学习《ANTLR 4 权威指南》这本书是看到的。书中的例子都是在不指定包名(package)且命令行手工编译Java代码的简单用法。

为了学习ANTLR4插件的使用,我创建了一个antlr4-demo项目,完整的代码放在码云仓库:https://gitee.com/l0km/antlr4-demo.git 供参考,以下的说明都是基于antlr4-demo项目。

当我在Maven项目使用ANTLR4 插件(antlr4-maven-plugin)生成语法分析器代码并编译后,照搬书中的示例是无法执行的

grun Hello r -tree

书中的示例的执行环境是极简单的:生成语法分析器的代码没有包名,并在当前文件夹下,javac编译出的.class文件也在当前文件夹下。
因为antlr4-demo项目中我在生成语法分析器代码时指定了包名com.gitee.l0km.parser(参见 antlr4-demo/pom.xml),并且生成语法分析器的代码也并不在当前文件夹下(antlr4-demo/target/generated-sources/antlr4),对应编译的.class文件在antlr4-demo/target/classes下。

所以要在Mave项目中使用TestRig来调试语法,以antlr-demo为例需要如下执行:

如下示例中,命令行键入测试文本后,UNIX系统上需要键CTRL-D或在Windows系统上键入Ctrl-Z来输入文件结束符

-gui

-gui 在对话框中以可视化方式显示语法分析树

cd antlr4-demo
## 执行maven编译,生成解析器代码并编译成.class
mvn clean compile
java -cp lib/antlr-4.9.3-complete.jar;target/classes org.antlr.v4.gui.TestRig com.gitee.l0km.parser.Hello r -tree -gui
  • -cp 即-classpath参数用于指定Java执行搜索类的路径,
    lib/antlr-4.9.3-complete.jar 为ANTLR Tool jar包不指定找不到org.antlr.v4.gui.TestRig
    target/classes为当前项目编译的类路径,不指定它则找不到HelloParser等解析器的类文件
    注意Linux下路径分隔符为冒号:而不是分号;
  • com.gitee.l0km.parser.Hello
    因为我在生成语法分析器代码时指定了包名com.gitee.l0km.parser,所以在指定语法名是要加包名。否则报错:Can't load Hello as lexer or parser

执行后如下显示图形化的语法树

-tree

-tree 以LISP格式输出语法分析树

J:\\antlr4-demo>java -cp lib\\antlr-4.9.3-complete.jar;target\\classes org.antlr.v4.gui.TestRig com.gitee.l0km.parser.Hello r -tree
hello world
^Z
(r hello world)

-tokens

-tokens 打印出词法符号流

J:\\antlr4-demo>java -cp lib\\antlr-4.9.3-complete.jar;target\\classes org.antlr.v4.gui.TestRig com.gitee.l0km.parser.Hello r -tokens
hello world
^Z
[@0,0:4='hello',<'\\u0001'>,1:0]
[@1,6:10='world',<'\\u0002'>,1:6]
[@2,13:12='<EOF>',<EOF>,2:0]

ANTLR Tool version

如果你在执行过程中显示如下提示,意思是执行TestRig的ANTLR Tool版本(4.9.3)与生成的解析器代码的ANTLR Tool版本(4.4)不匹配,并不影响执行结果:

ANTLR Tool version 4.4 used for code generation does not match the current runtime version 4.9.3

原因是你的Eclipse中安装了ANTLR4IDE(0.3.6)插件,插件默认使用的ANTLR Tool版本是4.4.与当前使用的antlr-4.9.3-complete.jar不匹配.而你在运行TestRig时,Eclipse也打开着语法文件Hello.g4,插件自动编译了代码,导致了不匹配。

解决的办法就是如下将ANTLR4插件使用的ANTLR Tool版本与你当前使用版设置为同一个版本

grun.bat/grun.sh

如果每次测试都要向上面示例那样敲那么多字,真是好麻烦,所以我做了批处理脚本grun.batgrun.sh分别用于Windows和Linux下简化TestRig执行

Windows

grun.bat

@ECHO OFF
SETLOCAL
SET sh_folder="%~dp0"
PUSHD "%sh_folder%
java -cp lib\\antlr-4.9.3-complete.jar;target\\classes org.antlr.v4.gui.TestRig %*
POPD
ENDLOCAL

Linux

grun.sh

#!/bin/bash
sh_folder="$(cd "$(dirname $0)"; pwd -P)"
pushd "$sh_folder"
java -cp lib/antlr-4.9.3-complete.jar:target/classes org.antlr.v4.gui.TestRig $*
popd

有了grun脚本,做测试就方便多了。

J:\\antlr4-demo>grun com.gitee.l0km.parser.Hello r -tokens
hello world
^Z
[@0,0:4='hello',<'hello'>,1:0]
[@1,6:10='world',<ID>,1:6]
[@2,13:12='<EOF>',<EOF>,2:0]

TestRig 选项

执行不带参数的TestRig,输出命令行参数信息:

J:\\antlr4-demo>grun
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.
参数说明
GrammarName即为语法名(对于语法文件Hello.g4,语法名就是Hello)。如果生成的代码指定了包名,还要加上包名
startRuleName起始解析的规则名
-tokens打印出词法符号流
-tree以LISP格式输出语法分析树
-gui在对话框中以可视化方式显示语法分析树
-ps file.ps以PostScript格式生成可视化语法分析树存储于file.ps
-encoding encodingname指定测试输入文件的编码
-trace打印规则名字以及进入和离开该规则时的词法符号
-diagnostics开启解析过程中的调试信息输出
-SLL使用另外一种 更快但是功能稍弱的解析策略
input-filename(s)输入测试文本文件名,从控制台输入时忽略此参数

以上是关于ANTLR4入门:在线语法调试塈Maven项目中使用语法调试工具TestRig的主要内容,如果未能解决你的问题,请参考以下文章

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

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

conan入门:NDK交叉编译自己的conan包项目塈profile的定义

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

eclipse 2022:安装中文语言包(babel language packs)塈切换语言的方法

eclipse 2022:安装中文语言包(babel language packs)塈切换语言的方法