spec_to_rest
Parser reuse

The decision

Edit on GitHub

The comparison and why the compiler builds its own parser

Last updated:

The per-construct coverage is on the formal-methods and API-language pages; lined up on the criteria that actually decide a reuse question, the six candidates fall out like this:

CriterionAlloy 6QuintDafnyTypeSpecSmithyBallerina
Constructs covered8.5/146.5/148/143.5/144/144.5/14
Integration efforthighmed-highvery highvery highhighvery high
Parser extensibilitylow, CUPmedium, ANTLRlow, C#low, TSlow, Javalow, Java
Fork-maintenance burdenhighhighvery highvery highhighvery high
Verification backendKodkod / SATApalache / SMTZ3 / Boogienonenonenone
Code generationnonenonemany targetsvia emitterssmithy-codegenJVM bytecode
HTTP awarenessnonenonenoneexcellentexcellentexcellent

The core tension

One split runs through the whole table. The languages strong on behavior, Alloy, Quint, and Dafny, have no HTTP awareness and little or no path to a running service. The languages strong on HTTP and API modeling, TypeSpec, Smithy, and Ballerina, have no behavioral specification at all. No existing language sits on both sides of that line, which is the gap this project was built to fill, so no single parser was ever going to cover it.

Build it, and reuse the rest

So the parser is built from scratch, and the existing tools are kept as pipeline components rather than as a base to extend. The reasoning is cumulative. No candidate covers more than 61% of the constructs, and the missing ones are foundational rather than additive: adding HTTP conventions to Alloy, or behavioral contracts to TypeSpec, changes what the language is for, not just what it can say. Extending a grammar is roughly 5% of the work; the other 95% is the AST, the type checker, and every downstream phase, none of which a foreign codebase hands you. Forking any of these actively developed languages is a permanent merge-conflict tax, and each one locks you into its stack (Alloy to the JVM and SAT, Dafny to C# and Boogie, Quint to TypeScript and Apalache). A purpose-built parser was estimated at two to three months against four to nine for extending any of them, at lower risk and with a clean AST shaped for the pipeline.

What shipped follows that plan, with one correction from a later decision: the parser is an ANTLR4 grammar compiled through sbt-antlr4 inside the Scala 3 compiler, not the TypeScript-targeted port the research originally assumed. ANTLR4's ALL(*) algorithm handles the grammar's operator precedence and quantifiers without the ambiguity trouble an LALR generator like CUP would hit. The tools that earned their place stay in the pipeline: Dafny as the verification and synthesis backend, Z3 and Alloy for spec checking, and OpenAPI emitted alongside the generated code, with Smithy and TypeSpec export available as future targets.

Own parserANTLR4 via sbt-antlr4 Verified IRScala ADT Z3 and Alloyspec verification Dafnysynthesis backend Code generatorFastAPI, go-chi, ts-express OpenAPIemitted alongside

The Langium reconsideration

After the survey settled on ANTLR4, a separate evaluation weighed Langium, a TypeScript language workbench that bundles parser, AST, and LSP, and briefly preferred it before reversing back. The short version: Langium's companion type system cannot express refinement types, relations, or quantified expressions, so most of the type checker has to be hand-built whichever way the choice goes, which erases Langium's main productivity argument; ANTLR's community dwarfs it; and ANTLR keeps the parser independent of any one framework. The full back-and-forth is the DSL frameworks survey.

On this page