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

1.7k views Asked by At

I'm trying to learn ANTLR 4, and I'm following the examples given in The Definitive ANTLR 4 Reference. Sadly I'm stuck at the first example.


System:
Windows 10 (1703)
Java 8, update 151
ANTLR 4, v4.7

My %CLASSPATH% is set as a system variable (.;"D:\Program Files\Java\libs\antlr-4.7-complete.jar";).
I have antlr4.bat and grun.bat available in my %PATH%, and I'm able to run antlr4 from the command line.

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

I'm using -cp %CLASSPATH% explicitly because I've seen a few others having problems when not using the -cp option.


My problem is this:
When I run grun on the example grammar Hello (grun Hello r -tokens) I get this error message

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.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.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)

Any ideas to what I'm doing wrong?
Many thanks in advance!


EDIT:
I thought I had found an answer. By cd-ing into the folder where the compiled files were (instead of calling grun from the root project folder) I managed to get through the example in question.

But when I tried to set up my own project, I came across the same issue, with the same error message as above.

This time, it seems like grun is complaining after I've run antlr4 with the -package option.

Does anyone know why this is?

4

There are 4 answers

3
DoTheGenes On BEST ANSWER

Wow... The solution was, of course, an easy solution... My problem was that I had cd'd to the root folder of my test project, and I just had to cd to (and call grun from) the directory where the compiled files are.

Edit:
It seems like I still have an issue with grun. See edited question.

Edit2:
From what I can tell, grun doesn't cooperate very well with antlr4's -package option.
So my solution was that I had to set up my project as a Gradle project, because apparently that works better.

0
Lorenzo On

I am using ANTLR 4.9.1 and i had the exact same issue. My project layout had a unique and separate location for :

  • the grammar
  • generated source files (location specified in the grammar by the @header block)

which made grun always fail (since everything has to be in the same folder). The workaround was to make another script that fixes these 2 grun bugs as such :

  1. Move everything to 1 folder (Fix first bug)
  2. Remove @header{...} from grammar (Fix second bug)
  3. (Optional) If you don't have antlr in classpath then add it
  4. Compile all .java files
  5. Run antlr4 (or org.antlr.v4.Tool manually) to generate parser .java files
  6. Compile all parser .java files
  7. Run grun (or org.antlr.v4.gui.TestRig manually) with whatever option you want

The following PowerShell script shows how I've done it (keep in mind your paths might be different), in my case the language and project are called Nameless and i used the .g4test extension for test scripts (so adapt your Bash/Batch/PowerShell scripts accordingly)

# 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
0
Markus M. On

Try with fully qualifying the grammar name with the package it's part of, e.g. com.demo.pl.Grammar. Seems to work with ANTLR 4.7.2

1
Yifeng On

I was facing the same problem as you did.
@DoTheGenes reminded me this may be caused by @header {package com.blahblah.antlr4.hello;} in your .g4 file. Grun has some unfixed bugs with package relocation command. When I removed this line with @header, the problem solved and I could run grun gui, tree and any other commands with generated and compiled files.
Hope this could help.