Search code examples
javaantlr4javac

Antlr4 Project Directory Structure Issue


I'm trying to set up an Antlr4 project using Java's package directory structure.

The top level directory contains PondParser.g4, PondLexer.g4, and build_script.

build_script is expected to build and run the antlr4 test rig

{ 
    echo 'clean project' 
    find ./com/sevan/pond/ -type f -delete
} && { 
    echo 'launch ANTLR parser generator' 
    java -jar /usr/local/lib/antlr-4.8-complete.jar -package com.sevan.pond  ./PondLexer.g4 -o com/sevan/pond
    java -jar /usr/local/lib/antlr-4.8-complete.jar -package com.sevan.pond  ./PondParser.g4 -o com/sevan/pond
} && { 
    echo 'compile .java files'
    javac ./com/sevan/pond/*.java 
} && {
    echo 'run test rig with gui'
    java org.antlr.v4.gui.TestRig  ./com/sevan/pond/PondParser prog -gui 
}

Relevant PondParser.g4 header and options:

parser grammar PondParser;

@header {   
    package com.sevan.pond;
}

options {
    tokenVocab = PondLexer;
}

Relevant PondLexer.g4 header and options:

lexer grammar PondLexer ;

@header {   
    package com.sevan.pond;
}

The build script fails while compiling (javac ./com/sevan/pond/*.java ).

The specific errors are as follows:

./com/sevan/pond/LexerRules.java:4: error: class, interface, or enum expected
    package com.sevan.pond;
    ^
./com/sevan/pond/Pond.java:4: error: class, interface, or enum expected
    package com.sevan.pond;
    ^
./com/sevan/pond/PondBaseListener.java:4: error: class, interface, or enum expected
    package com.sevan.pond;
    ^
./com/sevan/pond/PondListener.java:4: error: class, interface, or enum expected
    package com.sevan.pond;
    ^
4 errors

What's missing/wrong here? Any suggestions, links, and answers would be greatly appreciated.


Update

The four errors above were due to a double package declaration in the generated java files. This was caused by specifying the package using -package and @header. After fixing this, however, the test rig still fails with Can't load PondParser as lexer or parser.


Solution

  • Shouldn't that be:

    # *nix
    javac -cp .:/usr/local/lib/antlr-4.8-complete.jar ./com/sevan/pond/*.java 
    
    # Windows
    javac -cp .;path\to\antlr-4.8-complete.jar .\com\sevan\pond\*.java 
    

    ?

    I.e.: you want to add the current working dir to the classpath (.), as well as the ANTLR lib.

    EDIT

    Here's a working demo (just tested it myself).

    Files/folder structure:

    -+
     |
     +-- antlr-4.8-complete.jar
     |
     +-- com/
          |
          +-- sevan/
               |
               +-- pond/
                    |
                    +-- PondParser.g4
                    |
                    +-- PondLexer.g4
    

    Navigate to where antlr-4.8-complete.jar resides.

    Generate lexer and parser classes:

    java -jar antlr-4.8-complete.jar -package com.sevan.pond com/sevan/pond/*.g4
    

    And compile all generated .java files:

    javac -cp .:antlr-4.8-complete.jar com/sevan/pond/*.java
    

    Fianlly, run TestRig as follows:

    java -cp .:antlr-4.8-complete.jar org.antlr.v4.gui.TestRig com.sevan.pond.Pond prog -gui
    

    You can now enter some text and can terminate by pressing CTRL+D. I typed abc\n and got this:

    enter image description here

    For reference, heres what the grammars look like:

    PondLexer.g4

    lexer grammar PondLexer;
    
    ANY
     : .
     ;
    

    PondParser.g4

    parser grammar PondParser;
    
    options {
      tokenVocab=PondLexer;
    }
    
    prog
     : ANY* EOF
     ;