Skip to content

Who This Is For

Lanexio™ Parser is tooling-first: built for the tooling, editor, and static-analysis niche. If you are writing a linter, a formatter, an editor extension, a language server, a migration tool, a bundler plugin, or a test harness, this parser was designed around the properties you need. General parsing ships first-party: the HTML DOM facade, the GraphQL validation core, and the plugin/visitor runtime are part of this release (ADR 0049, ADR 0050, and ADR 0051, each superseding the ADR 0047 deferral for its own deliverable), and the documented extension seams remain for consumer grammars and provider bridges. This page states that position and the non-goals that come with it (ADR 0043).

PropertyWhy tooling needs it
Lossless flat ASTemitSource(parse(x)) === x byte-for-byte on tiling grammars; the tree preserves every byte, so formatters and codemods never lose trivia
Incremental editreparse() with a grammar ReuseOracle reuses untouched subtrees instead of re-parsing a whole file on every keystroke
Multi-grammar dispatchone registry (grammarRegistry), 11 grammar families, and language/extension/MIME detection behind one parse()
Never-throwmalformed input becomes LexError nodes, never exceptions, so an editor never crashes on a half-typed document
Grammar-agnostic queriesLexQuery and a shared 16-byte node layout work the same across every grammar
  • Editors and language servers that reparse on every keystroke and need incremental subtree reuse and a stable never-throw contract.
  • Linters and static analyzers that want the raw, lossless syntax tree rather than a value-returning projection, so every warning points at the exact byte range.
  • Formatters and codemods that round-trip source byte-for-byte and only touch the nodes they intend to change.
  • Migration and conversion tools that parse several languages at once and benefit from one AST model and one query API.
  • Test harnesses and fuzzers that need deterministic, never-throwing behavior on arbitrary input.

These are deliberate, not oversights. The report that shaped 1.0 rated the parser as release-grade for the tooling niche and as competing with value-returning parsers for general app parsing; the non-goals are the other side of that choice (ADR 0043). ADR 0047 deferred a first-party DOM projection, GraphQL validator, and plugin runtime to a market-pull-gated future run. That market pull arrived, and this release ships all three: ADR 0049, ADR 0050, and ADR 0051 each supersedes the ADR 0047 deferral for its own deliverable. The non-goal is now scope, not presence: each shipped module is a deliberate subset of the standard it faces, and the boundary is documented in the bullets below.

  • General app parsing against value-returning parsers. If your product is a JSON/YAML/TOML loader that throws on malformed config, a dedicated value-returning parser (or the toValue() projection on top of a parse) is the better fit. This parser’s contract is the lossless tree, not a forgiving object graph.
  • DOM without full WHATWG conformance. The first-party facade (DOM Adapter, ADR 0049) exposes parseDom / toDom in @lanexio/parser-grammar-html as a read layer with a decorator override map. It is not a browser Document with a live mutation engine, and it does not chase every WHATWG/W3C DOM behavior.
  • GraphQL without full spec parity. The first-party core (GraphQL validation, ADR 0050) covers the operation, field, argument, fragment, and value-type rules through buildSchema / validate in @lanexio/parser-grammar-graphql. Full graphql-js parity is an optional adapter bridge for consumers who already hold a graphql-js schema, not a reimplementation of the library.
  • Plugin runtime without a plugin market. The first-party runtime (Plugins, ADR 0051) is walk / transform / createPipeline in @lanexio/parser-core. A marketplace of third-party published plugins is a market, not a shipped product.
  • Strict mode is not everywhere. CSV/TSV, TOML, XML, and SQL expose strict parsing under one convention (mode: "strict" or strict: true, plus the tsql clientBatch control); the remaining grammars are lenient only (Leniency and strict mode).

Written down so they are not misread as regressions:

  • SQL placeholders. sqlite’s ?NNN and $name forms are not emitted as markers (only bare ?, :name, @name); markers are accepted in any position because the grammar is a flat token scanner; and ? under postgres is a JSON operator by design, not a marker.
  • XML external DTDs. External-subset and parameter-entity resolution is never performed; the strict profile covers internal-subset DTD validation with content-model and standalone-VC coverage gaps.
  • HTML serialization. Seven documented WPT files have serialization fixed-point gaps (rawtext/RCDATA canonicality, plaintext, skip-leading-LF, nested-form round-trip); everything else passes the corrected gate.
  • Statement-level SQL coverage. Window functions, CTE+UNION, PL/pgSQL bodies, and generated columns remain a documented coverage gap for the postgres family.