ADR-001: Langium as Parser and LSP Framework
Context
Weltenwanderer needs a parser generator that produces typed ASTs and an LSP server for IDE
integration. The .ddd DSL defines approximately 28 AST node types across constructs such
as Decider, Command, Event, State, evolve, decide, require, and ensure.
Options evaluated:
| Option | AST Typing | LSP | Error Recovery | TS Native |
|---|---|---|---|---|
| Hand-written parser | Manual | None | Manual | Yes |
| tree-sitter | No | Partial | Yes | No |
| ANTLR 4 | Java codegen | Adapter needed | Yes | No |
| Langium 4.x | Yes (generated) | Full | Yes | Yes |
Decision
Use Langium 4.x (Eclipse Foundation). A single grammar file
(packages/language/src/weltenwanderer.langium) drives:
- Parser generation with error recovery
- Typed TypeScript AST interfaces
- Scope resolution and cross-reference linking
- A complete LSP server (hover, go-to-definition, diagnostics)
- A validation framework with location-aware error reporting
The grammar file is the canonical source of truth for all AST structure. Parser artifacts are
regenerated via bun run langium:generate.
Consequences
Positive
- Typed AST eliminates a class of null-reference errors in validation passes.
- LSP server is produced without additional code; VS Code extension is a thin wrapper.
- TypeScript-native output integrates directly with the Bun/TS stack.
- Grammar-driven DI system (
module.ts) separates language services cleanly.
Negative
- All validation and generation code couples to Langium’s AST node shapes.
- Grammar modifications require a
langium:generatestep before compilation. - Langium’s expression grammar support required a dedicated workaround
(
ExpressionFragment→ operator-precedence grammar, resolved in ADR-013). - The Langium DI container (
module.ts) is a singleton file; parallel agents must not modify it concurrently (see file ownership matrix inCLAUDE.md).