Phase 3: Grammar-Kit parser, PSI and ParserDefinition

Adds src/main/grammar/Jai.bnf, the generated parser/PSI in src/main/gen, a
JaiParserDefinition, and the Tier 3 corpus parse gate (406/714 files clean).

Two things were not obvious:

- Grammar-Kit mints its own token instances from the .bnf 'tokens' block, which
  are different objects from the ones JaiLexer emits, so every rule silently
  failed to match. Fixed with tokenTypeFactory -> JaiTokenTypes.byName.
- A backslash inside an identifier is a continuation in the compiler's lexer
  (Jai_Lexer/module.jai:444): 'left\_margin' is one identifier. JaiLexer now
  does the same; the Tier 0 round-trip still holds because the token span
  covers the backslash and the skipped spaces.

Constructs that BNF alone cannot express live in JaiParserUtil: directive-name
tests (#ident is one token), '==' before '{' for the switch form, procedure
header vs parenthesised expression, and the declaration lookahead.
This commit is contained in:
hgranthorner
2026-08-04 12:05:42 -04:00
parent 746647d27d
commit 37809b8aa7
169 changed files with 8328 additions and 7 deletions

View File

@@ -4,6 +4,13 @@ plugins {
id("org.jetbrains.kotlin.jvm")
id("org.jetbrains.changelog")
id("org.jetbrains.intellij.platform")
id("org.jetbrains.intellij.platform.grammarkit")
}
sourceSets {
main {
java.srcDirs("src/main/gen")
}
}
// Read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin.html
@@ -19,3 +26,11 @@ dependencies {
// bundledPlugin("com.intellij.java")
}
}
tasks.generateParser {
sourceFile.set(file("src/main/grammar/Jai.bnf"))
targetRootOutputDir.set(file("src/main/gen"))
pathToParser.set("dev/hgh/jai/parser/JaiParser.java")
pathToPsiRoot.set("dev/hgh/jai/psi")
purgeOldFiles.set(true)
}