Skip to content

Strumenta/antlr-kotlin

ANTLR Kotlin

Build Status Maven Central License Apache-2.0 License

This project contains everything needed to support Kotlin as a target for ANTLR.

  • Kotlin Target: a plugin for the ANTLR code generator that produces lexers, parsers, listeners, and visitors
  • Kotlin Runtime: a multiplatform library needed by the generated lexers and parsers

This being a fully multiplatform project, the code written using the Kotlin target for ANTLR will run on the JVM (including Android), in the browser, in Node.js, and natively on Mac, Windows, and Linux.

Want to start experimenting immediately? See Gradle Setup.

Status

The project should be considered experimental. Several parsers have been implemented and work so far using this target but not all the features are complete and well tested.

The runtime and target's template are up-to-date with mainstream commit: master/e9df464

Kotlin Target

The Kotlin target is a plugin for the ANTLR generator.

It should be added to the classpath used to run the ANTLR Tool.

You will need to specify the target language to be Kotlin (-Dlanguage=Kotlin), or use the com.strumenta.antlr-kotlin plugin, which instructs ANTLR automatically.

Kotlin Runtime

The Kotlin runtime for the Kotlin target is derived from the Java runtime, and is built as a multiplatform project running on JVM, JS, WebAssembly (including WASI), and Native.

Warning

The Native runtime is not thread safe

The supported Native platforms are:

Tier 1 Tier 2 Tier 3
macosX64 linuxX64 androidNativeArm32
macosArm64 linuxArm64 androidNativeArm64
iosSimulatorArm64 watchosSimulatorArm64 androidNativeX86
iosX64 watchosX64 androidNativeX64
watchosArm32 watchosDeviceArm64
watchosArm64 mingwX64
tvosSimulatorArm64 linuxArm32Hfp
tvosX64
tvosArm64
iosArm64

Note

The linuxArm32Hfp platform is deprecated

Gradle Setup

To start using ANTLR Kotlin:

  1. Add the mavenCentral repository to the list of repositories in your build script. This is required as artifacts are pushed to Maven Central.

    repositories {
      mavenCentral()
    }
  2. Add the ANTLR Gradle plugin for the Kotlin target to the list of plugins in your build script.

    plugins {
      id("com.strumenta.antlr-kotlin") version "$antlrKotlinVersion"
    }
  3. Add the ANTLR Kotlin Runtime to the list of dependencies. If you are working in a multiplatform project, add it to the common source set.

    kotlin {
      sourceSets {
        commonMain {
          dependencies {
            implementation("com.strumenta:antlr-kotlin-runtime:$antlrKotlinVersion")
          }
        }
      }
    }
  4. Register the ANTLR Kotlin grammar generation task.

    val generateKotlinGrammarSource = tasks.register<AntlrKotlinTask>("generateKotlinGrammarSource") {
      dependsOn("cleanGenerateKotlinGrammarSource")
    
      // ANTLR .g4 files are under {example-project}/antlr
      // Only include *.g4 files. This allows tools (e.g., IDE plugins)
      // to generate temporary files inside the base path
      source = fileTree(layout.projectDirectory.dir("antlr")) {
        include("**/*.g4")
      }
    
      // We want the generated source files to have this package name
      val pkgName = "com.strumenta.antlrkotlin.parsers.generated"
      packageName = pkgName
    
      // We want visitors alongside listeners.
      // The Kotlin target language is implicit, as is the file encoding (UTF-8)
      arguments = listOf("-visitor")
    
      // Generated files are outputted inside build/generatedAntlr/{package-name}
      val outDir = "generatedAntlr/${pkgName.replace(".", "/")}"
      outputDirectory = layout.buildDirectory.dir(outDir).get().asFile
    }

    Depending on cleanGenerateKotlinGrammarSource ensures the .tokens files are always fresh, and we do not end up with out-of-sync lexers and parsers.

  5. Instruct the Kotlin compilation tasks to depend on the grammar generation.

    tasks.withType<KotlinCompile<*>> {
      dependsOn(generateKotlinGrammarSource)
    }
    
  6. Register the build/generatedAntlr directory as part of the common source set.

    kotlin {
      sourceSets {
        commonMain {
          kotlin {
            srcDir(layout.buildDirectory.dir("generatedAntlr"))
          }
        }
      }
    }

Benchmarks

The antlr-kotlin-benchmarks module contains benchmarking code targeting JVM, JS and WebAssembly.
The scenario has been adapted from antlr4ng.

  • JVM benchmarks use kotlinx-benchmark, which under the hood uses JMH.

    To run benchmarks, use:

    ./gradlew :antlr-kotlin-benchmarks:jvmBenchmark
    
  • JS, WebAssembly and Native benchmarks cannot use kotlinx-benchmark currently.
    Instead, they use a test case which re-uses the benchmark code.

    To run benchmarks, remove the @Ignore annotation on ManualMySQLBenchmarks, and use:

    ./gradlew :antlr-kotlin-benchmarks:jsTest
    

    or

    ./gradlew :antlr-kotlin-benchmarks:wasmJsTest
    

    or

    ./gradlew :antlr-kotlin-benchmarks:mingwX64Test
    

Maven Central Publication

Publication can be performed running:

./gradlew publishAllPublicationsToMavenCentralRepository --no-configuration-cache

However, it is recommended to use the releases plugin and run:

./gradlew release

Contributors

You can see the complete list on GitHub, but here we list those who contributed ten commits or more.

License

Consumers of this project may choose the most appropriate license: either the Apache License 2.0, or the 3-Clause BSD License.