ANTLR4 TestRig (grun) 抛出 java.lang.NoClassDefFoundError 异常

ANTLR4 TestRig (grun) throws java.lang.NoClassDefFoundError exception

我正在尝试学习 ANTLR 4,我正在按照 The Definitive ANTLR 4 Reference 中给出的示例进行操作。可悲的是,我卡在了第一个例子中。


系统:
Windows 10 (1703)
Java8、更新151
ANTLR 4,v4.7

我的%CLASSPATH%设置为系统变量(.;"D:\Program Files\Java\libs\antlr-4.7-complete.jar";)。
我的 %PATH% 中有 antlr4.batgrun.bat,我可以从命令行 运行 antlr4

antlr4.bat : java -cp %CLASSPATH% org.antlr.v4.Tool %*
grun.bat : java -cp %CLASSPATH% org.antlr.v4.gui.TestRig %*

我明确地使用 -cp %CLASSPATH%,因为我看到其他一些人在不使用 -cp 选项时遇到问题。


我的问题是:
当我 运行 grun 在示例语法 Hello (grun Hello r -tokens) 上时,我收到此错误消息

Exception in thread "main" java.lang.NoClassDefFoundError: HelloLexer (wrong name: main/resource/hello/HelloLexer)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access0(Unknown Source)
        at java.net.URLClassLoader.run(Unknown Source)
        at java.net.URLClassLoader.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at org.antlr.v4.gui.TestRig.process(TestRig.java:129)
        at org.antlr.v4.gui.TestRig.main(TestRig.java:119)

对我做错了什么有什么想法吗?
非常感谢!


编辑:
我以为我找到了答案。通过 cd-ing 进入编译文件所在的文件夹(而不是从根项目文件夹调用 grun),我设法完成了所讨论的示例。

但是当我尝试建立自己的项目时,我遇到了同样的问题,并出现与上述相同的错误消息。

这一次,在我 运行 antlr4 使用 -package 选项后,grun 似乎在抱怨。

有人知道这是为什么吗?

哇...解决方案当然是一个简单的解决方案...我的问题是我已经 cd' 到我的测试项目的根文件夹,并且我只需要 cd 到(并从中调用 grun)编译文件所在的目录。

编辑:
看来我对 grun 仍有疑问。请参阅已编辑的问题。

编辑 2:
据我所知,grunantlr4-package 选项配合得不是很好。
所以我的解决方案是我必须将我的项目设置为 Gradle 项目,因为显然这样效果更好。

尝试使用它所属的包完全限定语法名称,例如 com.demo.pl.Grammar。似乎适用于 ANTLR 4.7.2

我遇到了和你一样的问题。
@DoTheGenes 提醒我这可能是由 .g4 文件中的 @header {package com.blahblah.antlr4.hello;} 引起的。 G运行 在包重定位命令中有一些未修复的错误。当我用@header 删除这一行时,问题就解决了,我可以 运行 g运行 gui、tree 和任何其他带有生成和编译文件的命令。
希望这能有所帮助。

我正在使用 ANTLR 4.9.1 并且遇到了完全相同的问题。我的项目布局有一个独特且独立的位置:

  • 语法
  • 生成的源文件(在语法中由 @header 块指定的位置)

这使得 grun 总是失败(因为所有东西都必须在同一个文件夹中)。解决方法是制作另一个脚本来修复这 2 个 grun 错误:

  1. 将所有内容移动到 1 个文件夹(修复第一个错误)
  2. 从语法中删除 @header{...} (修复第二个错误)
  3. (可选)如果类路径中没有 antlr,则添加它
  4. 编译所有 .java 个文件
  5. 运行 antlr4(或手动 org.antlr.v4.Tool)生成解析器 .java 文件
  6. 编译所有解析器 .java 个文件
  7. 运行 grun(或 org.antlr.v4.gui.TestRig 手动),随心所欲

下面的 PowerShell 脚本展示了我是如何完成的(请记住你的路径可能不同),在我的例子中,语言和项目被称为 Nameless 并且我使用了 .g4test 测试脚本的扩展(因此请相应地调整您的 Bash/Batch/PowerShell 脚本)

# Script name : run.ps1
# Script arguments
param ($Target="-tokens")
# Options
$lang = "Nameless"
$startRule = "file"

# Paths
$antlr = "D:\Desktop\Workspaces\Java\ANTLRv4\antlr-4.9.1-complete.jar"
$project = "D:\Desktop\Workspaces\Java\Eclipse Workspace 2020\Nameless"
$javas = "$project\target\generated-sources\antlr4\generated"
$script = "$project\scripts\LiteralsTest.g4test"
$classes = "$project\build\classes\generated"

# Fix weird bug of TestRig needing all in 1 folder lol
Write-Host "Moving project files.." -NoNewLine
Copy-Item "$project$lang.g4" -Destination $classes
Copy-Item -Path "$javas\*" -Destination $classes
cd $classes
Write-Host " done."

# Fix other framework bug that makes '@header' lines not run lol..
Write-Host "Removing package header line from grammar.." -NoNewline
(Get-Content -Path "$lang.g4" -Raw) -replace "(?sm)^@header`{.*?`}$" | Out-File -FilePath ".$lang.g4" -Encoding ASCII
Write-Host " done."

# All should be good now, do the usual
Write-Host "Adding to classpath temporarily.." -NoNewLine
$env:CLASSPATH = ".;$antlr;$env:CLASSPATH"
Write-Host " done."

Write-Host "Generating Java files from grammar.." -NoNewLine
java -cp ".;$antlr" org.antlr.v4.Tool "$lang.g4" -listener -visitor
Write-Host " done."

Write-Host "Compiling java files.." -NoNewLine
javac -cp ".;$antlr" *.java
Write-Host " done."

Write-Host "Running.."
java -Xmx500M -cp ".:$env:CLASSPATH" org.antlr.v4.gui.TestRig $lang $startRule $Target $script