Installation and Setup¶
This page covers installing the Grammar-Kit plugin, setting up a project with the right directory structure, and creating your first grammar file. After following these steps, you will have a working .bnf file with syntax highlighting and Live Preview.
Prerequisites¶
Grammar-Kit runs inside IntelliJ IDEA. You need:
| Requirement | Minimum version |
|---|---|
| IntelliJ IDEA (Community or Ultimate) | 2023.3 or later |
| Java Development Kit | 17 or later |
You should be comfortable creating projects and navigating settings in IntelliJ IDEA. Java development experience is needed because Grammar-Kit generates Java source files. Familiarity with parsing concepts helps but is not required at this stage.
Note
IntelliJ IDEA 2024.2 and later requires Java 21. Check the Build Number Ranges page for your specific version.
Installing the plugin¶
From the marketplace¶
- Open Settings (Ctrl+Alt+S / Cmd+,) and select Plugins.
- Switch to the Marketplace tab and search for "Grammar-Kit".
- Click Install, then restart the IDE when prompted.
The plugin is also available at plugins.jetbrains.com/plugin/6606-grammar-kit.
For development builds, JetBrains publishes artifacts on TeamCity. Download the zip and install it through Settings > Plugins > gear icon > Install Plugin from Disk.
Version compatibility¶
| Grammar-Kit | IntelliJ IDEA | Java |
|---|---|---|
| 2023.3 | 2023.3+ | 17 |
| 2022.3 | 2022.3+ | 17 |
| 2021.1 | 2021.1+ | 11 |
| 2020.3 | 2020.3+ | 11 |
Grammar-Kit follows the IntelliJ IDEA version numbering scheme. Each release targets the corresponding platform version and later.
Verifying the installation¶
Create a new file with the .bnf extension in any project. If Grammar-Kit is installed correctly, you will see:
- A BNF file icon on the editor tab.
- Syntax highlighting for keywords, rules, and tokens.
- Code completion when you start typing attributes or rule names.
Open Live Preview with Ctrl+Alt+P (Cmd+Alt+P on macOS) to confirm the editor is fully functional. The preview pane displays a parse tree as you type grammar rules and sample input.
Project setup¶
A language plugin project needs separate source roots for handwritten code and generated code. As the Grammar-Kit documentation states: "Handwritten classes and generated classes should always be in different source roots."
The recommended directory layout for a Gradle-based IntelliJ plugin project:
my-language-plugin/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
│
├── src/main/java/ ← Handwritten source code
│ └── com/example/config/
│ ├── ConfigLanguage.java ← Language singleton
│ ├── ConfigFileType.java ← File type registration
│ ├── ConfigParserDefinition.java ← Connects parser + lexer
│ ├── ConfigSyntaxHighlighter.java ← Syntax coloring
│ └── ConfigLexer.flex ← JFlex lexer definition
│
├── src/main/gen/ ← Generated code (separate root!)
│ └── com/example/config/
│ ├── parser/
│ │ └── ConfigParser.java ← Generated parser
│ └── psi/
│ ├── ConfigTypes.java ← Generated element types
│ ├── ConfigProperty.java ← Generated PSI interface
│ └── impl/
│ └── ConfigPropertyImpl.java ← Generated PSI implementation
│
├── src/main/resources/
│ ├── META-INF/
│ │ └── plugin.xml ← Plugin registration
│ └── com/example/config/
│ └── config.bnf ← Grammar file
│
└── src/test/
├── java/ ← Test source code
└── testData/ ← Test input files
Warning
Do not mix generated and handwritten code in the same source root. Regenerating the parser may overwrite handwritten files, and refactoring tools may modify generated code.
Mark src/main/gen as a generated source root in your build.gradle.kts:
sourceSets {
main {
java.srcDirs("src/main/java", "src/main/gen")
}
}
idea {
module {
generatedSourceDirs.add(file("src/main/gen"))
}
}
Some projects use a flat layout closer to Grammar-Kit's own structure, with top-level src/, gen/, and resources/ directories. Either layout works as long as handwritten and generated code stay in separate roots.
Dependencies and templates¶
The generated parser relies on GeneratedParserUtilBase, which ships with the IntelliJ Platform since version 12.1. You do not need to bundle it.
For build automation, the Gradle Grammar-Kit Plugin (org.jetbrains.grammarkit, version 2023.3.0.2) runs parser and lexer generation as part of your Gradle build. See the IntelliJ SDK documentation for configuration details, and Gradle Plugin Setup for a full walkthrough. The Gradle plugin does not support method mixins, and generic signatures may not be correct in all cases.
To start a new project from scratch, the IntelliJ Platform Plugin Template provides a ready-made Gradle project structure. The IntelliJ SDK also has a Creating a Plugin Project guide that walks through the new-project wizard.
Configuring the development environment¶
The default output directory for generated code is gen. You can change it and other plugin behavior through Java system properties (-D flags passed to the IDE or Gradle):
| Property | Default | Purpose |
|---|---|---|
grammar.kit.gen.dir | gen | Output directory for generated code |
grammar.kit.gen.jflex.args | (empty) | Extra arguments for JFlex generation |
grammar.kit.gpub.max.level | 1000 | Parser recursion depth limit |
grammar.kit.inject.java | true | Inject Java language in JFlex files |
grammar.kit.inject.regexp | true | Inject RegExp language in BNF strings |
Whether to commit the gen/ directory to version control is a team decision. Committing it makes the build reproducible without running generation but adds noise to diffs. Adding gen/ to .gitignore keeps the repository clean but requires all contributors to generate before building.
Your first grammar file¶
The smallest valid grammar is a single rule with no attributes:
// minimal.bnf — Works in Live Preview without any attributes.
root ::= 'hello' 'world'
This grammar is enough to test Live Preview immediately. No attributes block is needed for prototyping, but without output paths configured, the grammar is not ready for code generation.
To generate code, you need an attributes block that specifies where the generated classes go. The following grammar for a simple key-value configuration language shows the complete structure:
// config.bnf — A grammar for key-value configuration files.
//
// Example input this grammar parses:
// host = "localhost"
// port = 8080
// debug = true
{
// Where to put generated parser code
parserClass="com.example.config.parser.ConfigParser"
// Where to put generated PSI interfaces and implementations
psiPackage="com.example.config.psi"
psiImplPackage="com.example.config.psi.impl"
// Class that holds all IElementType constants
elementTypeHolderClass="com.example.config.psi.ConfigTypes"
// Factory methods for element types (use defaults for now)
elementTypeClass="com.example.config.psi.ConfigElementType"
tokenTypeClass="com.example.config.psi.ConfigTokenType"
// Token definitions — names on the left, patterns on the right
tokens=[
EQUALS = '='
SEMI = ';'
space = 'regexp:\s+'
comment = 'regexp://.*'
number = 'regexp:\d+'
string = "regexp:\"[^\"]*\""
id = 'regexp:\p{Alpha}\w*'
]
}
// The first rule is the root of the grammar.
// The parser starts here.
root ::= item *
// 'private' means this rule won't create its own PSI node.
// Its children fold into the parent.
private item ::= property ';'? {recoverWhile=item_recover}
// A property is an identifier, '=', and a value.
property ::= id '=' value {pin=2}
// Values can be strings, numbers, or identifiers (references).
value ::= string | number | id
// Recovery rule: skip tokens until we find something
// that looks like the start of the next property.
private item_recover ::= !(id | ';')
A grammar file has three parts. The attributes block ({ ... }) at the top configures code generation output locations. The tokens list inside it maps token names to string literals or regex patterns using the 'regexp:...' syntax. The rules section defines the grammar structure, where each rule uses the ::= operator. The first rule in the file becomes the parse root.
You can reference tokens by their quoted value ('=') for readability or by their name (EQUALS). Both forms resolve to the same token.
Tip
Set parserClass, psiPackage, and elementTypeHolderClass before generating code. Without these attributes, Grammar-Kit uses defaults like generated.GeneratedParser and generated.GeneratedTypes, which are unlikely to match your project's package structure.
After saving the grammar file, test it:
- Confirm the file shows a BNF icon in the editor tab.
- Press Ctrl+Alt+P (Cmd+Alt+P) to open Live Preview.
- Type sample input in the preview pane and check that a parse tree appears.
- Press Ctrl+Shift+G (Cmd+Shift+G) to generate parser code into your
gen/directory.
Editor features available for .bnf files:
| Feature | Shortcut | What it does |
|---|---|---|
| Live Preview | Ctrl+Alt+P / Cmd+Alt+P | Test grammar against sample input |
| Generate Parser Code | Ctrl+Shift+G / Cmd+Shift+G | Generate parser, PSI, and element types |
| Structure View | Ctrl+F12 / Cmd+F12 | Browse rules in the current file |
| Quick Documentation | Ctrl+Q / Cmd+J | Show FIRST and FOLLOW sets for a rule |
| Go to Related File | Ctrl+Alt+Home / Cmd+Alt+Home | Jump to the generated file for a rule |
Eight inspections run by default, catching problems like unresolved references, unused rules, left recursion, and duplicate rules. Warnings appear directly in the editor as you type.
Next: the Quick Start Tutorial walks through building a complete language plugin from grammar to working IDE support.