Antlr4 Eclipse and Gradle

For my DSL ‘s the preferred tool is ANLTR by Terence Parr and his team (although I sometimes like to hone my Flex/Lex, Bison/Yacc skills too). With the new ANLTR4 creating your own compiler front end has never been so easy.

It still took me a little bit of time to combine it with Eclipse and Gradle. I did the following to make it work:

  • Install Antlr4 by Edgar Espina from eclipse market place
  • Create ANLTR project New->General->ANLTR 4 Project
  • Add grammar file e.g. src/main/antlr/<package>/mygrammar.g4
  • Important. Add header to your grammar with package . This will make sure that the package structure is created in the jar file like in the following example:

 

grammar TimeParser;

@header {
    package eu.informationsuperhighway.timeparser;
    import java.util.HashMap;
}
  • Right Click the project->Build Path->Source Path->Click ‘Add Source Path’->Click ‘Browse’
  • Browse to build->generated-src->antlr->main and make sure the checkbox for main is checked. This is where the generated sources end up and if it is not listed as the source dir then the calling project won’t be able to find the sources! You might need to compile first before this directory shows up.
  • You can right click on the <grammar>.g4 file to set options (although I had to restart eclipse to make them take effect). I you do a Gradle build the following Gradle file should do. You might need to upgrade Gradle so it recognizes the antlr4 plugin (execute task wrapper).
  • Add Gradle Nature to the project by right clicking on the project Configure->Add Gradle Nature
  • Refresh Gradle in the ‘Gradle Tasks’ view with the ‘Refresh All Projects’ button.
  • Double click the ‘Jar’ taks in Gradle tasks.
  • I used the following Gradle file to create a library to include into other projects. I am only interested in the ‘Visitor Design Pattern’ so I added ‘-no-listener’ and ‘-visitor’  for the arguments parameter ( see end of this post).
  • Note that if this is a library (probably), in the calling project, under dependencies add ‘compile project( ‘:<your project name>’ )’  and in settings.gradle add:

 

include ':<your project name>'
project(':<your project name>').projectDir = new File(settingsDir, '../<your project name>')

e.g.

include ':timeparser'
project(':timeparser').projectDir = new File(settingsDir, '../timeparser')
  • Also in the calling project’s buildpath add this project as dependent project (so the jar gets included) Right Click project->Build Path->Configure Build Path->Projects-> Add the library project
  • For verification; Note that the library’s project’s jar should be in workspace\<project>\build\libs.
/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a commented-out sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/3.5/userguide/tutorial_java_projects.html
 */


// Apply the java plugin to add support for Java
apply plugin: 'antlr'
apply plugin: 'java-library'
// In this section you declare where to find the dependencies of your project
repositories 
{
    // Use 'jcenter' for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
    mavenCentral()
}

task wrapper(type: Wrapper) {
    gradleVersion = '4.3.1'
}

task compile(type: JavaCompile)

generateGrammarSource 
{
    maxHeapSize = "64m"
    arguments += ["-visitor", "-long-messages", "-no-listener"]
}

// In this section you declare the dependencies for your production and test code
dependencies 
{
    // The production code uses the SLF4J logging API at compile time
    //compile 'org.slf4j:slf4j-api:1.7.22'

    // Declare the dependency for your favourite test framework you want to use in your tests.
    // TestNG is also supported by the Gradle Test task. Just change the
    // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
    // 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
    
     // https://mvnrepository.com/artifact/org.antlr/antlr4-runtime
    compile group: 'org.antlr', name: 'antlr4-runtime', version: '4.7'
	
    antlr "org.antlr:antlr4:4.7" // use ANTLR version 4 
}
 
jar 
{
    archiveName = "timeparser.jar"
    from 
    {

        configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }

        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
    
    from( "timeparser/build/generated-src/antlr/main" )
    

    manifest 
    {
       //attributes 'Main-Class': 'eu.informationsuperhighway.something.Main'
    }

    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'    
}

Leave a Reply