Gradle Plugin Setup¶
The gradle-grammar-kit-plugin automates parser and lexer generation in your Gradle build. It provides generateParser and generateLexer tasks that invoke Grammar-Kit and JFlex without a running IDE, making it suitable for CI/CD pipelines and team builds.
Warning
The Gradle plugin does not support mixin or psiImplUtilClass. Upstream describes this as a cycle between generated PSI and user-written PSI support code that would require two-pass generation. Generic signatures and annotations may also be less precise. If your grammar uses either customization, generate from the IDE and commit the output.
Plugin Installation¶
Apply the plugin in your build.gradle.kts. The plugin is published to the Gradle Plugin Portal:
plugins {
id("org.jetbrains.intellij.platform") version "..."
id("org.jetbrains.grammarkit") version "2023.3.0.3"
}
The two version numbers serve different purposes here: current upstream Grammar-Kit is 2023.3.2, while the separately versioned Gradle plugin is 2023.3.0.3.
Configure your IntelliJ Platform dependency as usual. Grammar-Kit's own build uses these settings as a reference:
dependencies {
intellijPlatform {
create(
providers.gradleProperty("platformType"),
providers.gradleProperty("platformVersion")
)
bundledPlugins(
providers.gradleProperty("platformBundledPlugins")
.map { it.split(',') }
)
}
}
Set the Java version and platform target in gradle.properties. Grammar-Kit's current upstream build uses Java 17 and targets IntelliJ 2023.3 or later:
javaVersion = 17
platformType = IU
platformVersion = 2023.3.8
platformBundledPlugins = com.intellij.java
This matches the current upstream build baseline: Java 17, since-build 233, and platform 2023.3.8.
Generation Tasks¶
The plugin provides two tasks: generateParser for BNF grammars and generateLexer for JFlex files.
Configure generateParser to point at your grammar file and specify where to write the output:
tasks {
generateParser {
sourceFile.set(file("src/main/grammar/My.bnf"))
targetRootOutputDir.set(file("src/main/gen"))
pathToParser.set("com/example/parser/MyParser.java")
pathToPsiRoot.set("com/example/psi")
}
}
Configure generateLexer similarly for your JFlex file:
tasks {
generateLexer {
sourceFile.set(file("src/main/grammar/My.flex"))
targetOutputDir.set(file("src/main/gen/com/example/lexer"))
}
}
Wire these tasks into the build so they run before compilation:
tasks {
compileJava {
dependsOn(generateParser, generateLexer)
}
}
sourceSets {
main {
java.srcDirs("src/main/gen")
}
}
The generated sources go into src/main/gen, which is added as a source directory. This keeps generated code separate from hand-written code and makes it straightforward to add gen/ to .gitignore if you prefer not to commit generated files.
CI/CD Integration¶
Gradle-based generation produces reproducible output without an IDE. This makes it well-suited for continuous integration. A basic CI configuration runs the generation tasks as part of the standard build:
./gradlew build
The generateParser and generateLexer tasks participate in Gradle's up-to-date checking. If the grammar file has not changed, the tasks are skipped on subsequent runs, speeding up incremental builds.
For command-line generation without Gradle, Grammar-Kit also provides a standalone JAR:
java -jar grammar-kit.jar <output-dir> <grammars-and-dirs>
The standalone JAR uses LightPsi to create a minimal parsing environment. In current upstream source, it remains a classic-generation utility. Upstream labels standalone usage as a proof of concept, so use it for scripted classic parser generation only, not as the syntax-api / Kotlin generation path.
For projects that need mixin or psiImplUtilClass, use a hybrid workflow: generate from the IDE during development and commit the generated files. CI then compiles the committed sources without running the generator. See Gradle vs IDE Generation for guidance on choosing an approach.