parseman 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/combinators/completions.d.ts +14 -4
  3. package/dist/combinators/completions.d.ts.map +1 -1
  4. package/dist/combinators/expect.d.ts +2 -0
  5. package/dist/combinators/expect.d.ts.map +1 -1
  6. package/dist/combinators/grammar.d.ts +5 -5
  7. package/dist/combinators/not.d.ts.map +1 -1
  8. package/dist/combinators/parser.d.ts +3 -2
  9. package/dist/combinators/parser.d.ts.map +1 -1
  10. package/dist/combinators/repeat.d.ts.map +1 -1
  11. package/dist/combinators/sequence.d.ts.map +1 -1
  12. package/dist/combinators/trivia-skip.d.ts +1 -0
  13. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  14. package/dist/compiler/codegen.d.ts +9 -4
  15. package/dist/compiler/codegen.d.ts.map +1 -1
  16. package/dist/compiler/scannable-run.d.ts +2 -2
  17. package/dist/compiler/scannable-run.d.ts.map +1 -1
  18. package/dist/cst/capture-buffer.d.ts +1 -0
  19. package/dist/cst/capture-buffer.d.ts.map +1 -1
  20. package/dist/cst/relative-spans.d.ts +32 -0
  21. package/dist/cst/relative-spans.d.ts.map +1 -1
  22. package/dist/cst/types.d.ts +7 -7
  23. package/dist/cst/types.d.ts.map +1 -1
  24. package/dist/functional/doc.d.ts +89 -4
  25. package/dist/functional/doc.d.ts.map +1 -1
  26. package/dist/functional/run.d.ts +12 -1
  27. package/dist/functional/run.d.ts.map +1 -1
  28. package/dist/index.cjs +807 -278
  29. package/dist/index.cjs.map +4 -4
  30. package/dist/index.d.ts +2 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +807 -278
  33. package/dist/index.js.map +4 -4
  34. package/dist/language-service/index.cjs +776 -0
  35. package/dist/language-service/index.cjs.map +7 -0
  36. package/dist/language-service/index.d.ts +94 -0
  37. package/dist/language-service/index.d.ts.map +1 -0
  38. package/dist/language-service/index.js +753 -0
  39. package/dist/language-service/index.js.map +7 -0
  40. package/dist/plugin/evaluator.d.ts.map +1 -1
  41. package/dist/plugin/index.cjs +568 -129
  42. package/dist/plugin/index.cjs.map +4 -4
  43. package/dist/plugin/index.d.ts +11 -1
  44. package/dist/plugin/index.d.ts.map +1 -1
  45. package/dist/plugin/index.js +568 -129
  46. package/dist/plugin/index.js.map +4 -4
  47. package/dist/recovery/scan.d.ts +54 -0
  48. package/dist/recovery/scan.d.ts.map +1 -0
  49. package/dist/spec/index.cjs +67 -6
  50. package/dist/spec/index.cjs.map +3 -3
  51. package/dist/spec/index.d.ts +10 -2
  52. package/dist/spec/index.d.ts.map +1 -1
  53. package/dist/spec/index.js +67 -6
  54. package/dist/spec/index.js.map +3 -3
  55. package/dist/spec/model.d.ts.map +1 -1
  56. package/dist/spec/railroad.d.ts +12 -0
  57. package/dist/spec/railroad.d.ts.map +1 -1
  58. package/dist/types.d.ts +60 -6
  59. package/dist/types.d.ts.map +1 -1
  60. package/package.json +8 -2
  61. package/dist/combinators/recover-list.d.ts +0 -41
  62. package/dist/combinators/recover-list.d.ts.map +0 -1
  63. package/dist/combinators/recover.d.ts +0 -20
  64. package/dist/combinators/recover.d.ts.map +0 -1
@@ -0,0 +1,54 @@
1
+ import type { Combinator, FirstSet, ParseContext, ParseError, RecoveryHelpers } from '../types.ts';
2
+ /**
3
+ * Combine two recovery sentinels into one that matches when either does — used by
4
+ * tolerant `sepBy` to resync to its own separator OR the enclosing delimiter. Cold
5
+ * path only; a bare wrapper so we don't pull `choice()` (and its analysis) in.
6
+ */
7
+ export declare function orSentinel(a: Combinator<unknown>, b: Combinator<unknown> | undefined): Combinator<unknown>;
8
+ /**
9
+ * A lightweight zero-width sentinel that "matches" (succeeds, consuming nothing)
10
+ * when the input code point at `pos` starts the given first set. Sync inference
11
+ * builds one from a list's follow set so a nested list can resync to the enclosing
12
+ * delimiter with no grammar annotation. Returns `null` when the first set is `any`
13
+ * or `empty` (no usable inference).
14
+ */
15
+ export declare function firstSetSentinel(fs: FirstSet): Combinator<null> | null;
16
+ /**
17
+ * Cold-path recovery scan shared by tolerant `many()` / `sepBy()`. Scans forward
18
+ * from `from` until `sync` matches (or EOF) — probing the sentinel as pure
19
+ * lookahead — emits a {@link ParseError} spanning the skipped range, and pushes it
20
+ * to `ctx._errors`. The sync token is NOT consumed; the caller's loop resumes from
21
+ * `end`. Only ever reached after an element has failed, so entirely off the hot path.
22
+ *
23
+ * The caller owns the loop guard: `sepBy` progress is driven by its separator (a
24
+ * zero-width error for a missing element is fine); `many` checks `matchesAt(sync)`
25
+ * itself and breaks when sitting on the terminator, so a zero-width failure can
26
+ * never spin.
27
+ */
28
+ export declare function recoverScan(input: string, from: number, ctx: ParseContext, sync: Combinator<unknown>, expected: string[]): {
29
+ error: ParseError;
30
+ end: number;
31
+ };
32
+ /**
33
+ * Does `sentinel` match at `pos` (pure lookahead)? Used by the tolerant list loops
34
+ * to detect "we are sitting on the sync/terminator token" without consuming it or
35
+ * capturing anything.
36
+ */
37
+ export declare function matchesAt(sentinel: Combinator<unknown>, input: string, pos: number, ctx: ParseContext): boolean;
38
+ /**
39
+ * Embed a recovered error as a `parseError` CST child at the recovery point, so the
40
+ * error lives IN the tree (rides reused subtrees across incremental edits; a tree
41
+ * walk finds every diagnostic) — not only in the flat `ctx._errors` side-channel.
42
+ * No-op when CST capture is off (value/AST mode). Both the interpreter list loops
43
+ * and the compiled recovery branches call this (the latter via `_ctx._rec.capture`),
44
+ * so the embedded node is identical on both paths.
45
+ */
46
+ export declare function captureError(ctx: ParseContext, error: ParseError): void;
47
+ /**
48
+ * The recovery-helper bundle handed to a tolerant parse via `ctx._rec`. A COMPILED
49
+ * grammar can't import these, so the driver (`run`, `parseDoc`) injects them; the
50
+ * interpreter list loops read the same bundle, guaranteeing byte-identical recovery
51
+ * across paths. Shared here so every driver installs the exact same instance.
52
+ */
53
+ export declare const REC: RecoveryHelpers;
54
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/recovery/scan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAe,eAAe,EAAE,MAAM,aAAa,CAAA;AA6C/G;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EACtB,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,SAAS,GACjC,UAAU,CAAC,OAAO,CAAC,CAYrB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAiBtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,EACzB,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAMpC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,GAChB,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAEvE;AAED;;;;;GAKG;AACH,eAAO,MAAM,GAAG,EAAE,eAAyH,CAAA"}
@@ -20,12 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/spec/index.ts
21
21
  var spec_exports = {};
22
22
  __export(spec_exports, {
23
+ RAILROAD_CSS: () => RAILROAD_CSS,
23
24
  buildSpecModel: () => buildSpecModel,
24
25
  renderEBNF: () => renderEBNF,
25
26
  renderExpr: () => renderExpr,
26
27
  renderRailroadHtml: () => renderRailroadHtml,
28
+ renderRailroadSvg: () => renderRailroadSvg,
27
29
  toEBNF: () => toEBNF,
28
- toRailroadHtml: () => toRailroadHtml
30
+ toRailroadHtml: () => toRailroadHtml,
31
+ toRailroadSvg: () => toRailroadSvg
29
32
  });
30
33
  module.exports = __toCommonJS(spec_exports);
31
34
 
@@ -221,11 +224,25 @@ function declarationOrder(record) {
221
224
  function buildSpecModel(grammar, options = {}) {
222
225
  const record = toRecord(grammar);
223
226
  const decl = declarationOrder(record);
227
+ const known = new Set(decl);
228
+ const asList = (v) => Array.isArray(v) ? v : [v];
229
+ const requireKnown = (names, opt) => {
230
+ const bad = names.filter((n) => !known.has(n));
231
+ if (bad.length > 0) {
232
+ throw new Error(
233
+ `buildSpecModel: unknown rule name(s) in \`${opt}\`: ${bad.map((n) => JSON.stringify(n)).join(", ")}. Known rules: ${decl.map((n) => JSON.stringify(n)).join(", ")}.`
234
+ );
235
+ }
236
+ };
224
237
  let phases;
225
- if (options.order) {
226
- phases = [options.order];
238
+ if (options.order !== void 0) {
239
+ const order = asList(options.order);
240
+ requireKnown(order, "order");
241
+ phases = [order];
227
242
  } else if (options.root !== void 0) {
228
- phases = [Array.isArray(options.root) ? options.root : [options.root]];
243
+ const root = asList(options.root);
244
+ requireKnown(root, "root");
245
+ phases = [root];
229
246
  } else if (options.sort === "reachable") {
230
247
  phases = decl.length > 0 ? [[decl[0]], decl.slice(1)] : [decl];
231
248
  } else {
@@ -883,6 +900,47 @@ function toDsl(node) {
883
900
  return `Sequence(Comment("not"), ${toDsl(node.item)})`;
884
901
  }
885
902
  }
903
+ var _builders = null;
904
+ function builders() {
905
+ if (_builders) return _builders;
906
+ const mod = {};
907
+ new Function("exports", RAILROAD_JS)(mod);
908
+ _builders = mod;
909
+ return _builders;
910
+ }
911
+ function toDiagramNode(b, node) {
912
+ switch (node.kind) {
913
+ case "terminal":
914
+ return b.Terminal(node.text);
915
+ case "ref":
916
+ return b.NonTerminal(node.name);
917
+ case "empty":
918
+ return b.Skip();
919
+ case "annotation":
920
+ return b.Comment(node.text);
921
+ case "seq":
922
+ return b.Sequence(...node.items.map((n) => toDiagramNode(b, n)));
923
+ case "choice":
924
+ return b.Choice(0, ...node.items.map((n) => toDiagramNode(b, n)));
925
+ case "star":
926
+ return b.ZeroOrMore(toDiagramNode(b, node.item));
927
+ case "plus":
928
+ return b.OneOrMore(toDiagramNode(b, node.item));
929
+ case "opt":
930
+ return b.Optional(toDiagramNode(b, node.item));
931
+ case "sepBy":
932
+ return b.OneOrMore(toDiagramNode(b, node.item), toDiagramNode(b, node.sep));
933
+ case "not":
934
+ return b.Sequence(b.Comment("not"), toDiagramNode(b, node.item));
935
+ }
936
+ }
937
+ function renderRailroadSvg(model) {
938
+ const b = builders();
939
+ return model.productions.map((p) => ({
940
+ name: p.name,
941
+ svg: b.Diagram(toDiagramNode(b, p.expr)).toString()
942
+ }));
943
+ }
886
944
  function escapeHtml(s) {
887
945
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
888
946
  }
@@ -926,7 +984,7 @@ function renderRailroadHtml(model, options = {}) {
926
984
  ${ebnf}
927
985
  </section>`;
928
986
  }).join("\n");
929
- const builders = model.productions.map((p) => ` { name: ${j(p.name)}, dsl: function(){ return Diagram(${toDsl(p.expr)}); } }`).join(",\n");
987
+ const builders2 = model.productions.map((p) => ` { name: ${j(p.name)}, dsl: function(){ return Diagram(${toDsl(p.expr)}); } }`).join(",\n");
930
988
  return `<!doctype html>
931
989
  <html lang="en">
932
990
  <head>
@@ -951,7 +1009,7 @@ ${RAILROAD_JS}
951
1009
  <script>
952
1010
  (function () {
953
1011
  var rules = [
954
- ${builders}
1012
+ ${builders2}
955
1013
  ];
956
1014
  rules.forEach(function (r) {
957
1015
  var host = document.querySelector('.diagram[data-rule=' + CSS.escape(r.name) + ']');
@@ -974,4 +1032,7 @@ function toRailroadHtml(grammar, options) {
974
1032
  const model = buildSpecModel(grammar, options);
975
1033
  return renderRailroadHtml(model, options);
976
1034
  }
1035
+ function toRailroadSvg(grammar, options) {
1036
+ return renderRailroadSvg(buildSpecModel(grammar, options));
1037
+ }
977
1038
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spec/index.ts", "../../src/combinators/parser.ts", "../../src/spec/model.ts", "../../src/spec/ebnf.ts", "../../src/spec/railroad-lib.ts", "../../src/spec/railroad.ts"],
4
- "sourcesContent": ["/**\n * `parseman/spec` \u2014 generate a formal grammar specification directly from a\n * Pars\u00E9man `rules()` grammar.\n *\n * Because the emitter walks the SAME `_def` combinator tree the interpreter and\n * macro compiler consume, a generated spec is a single source of truth: it\n * cannot disagree with what actually parses.\n *\n * import { toEBNF, toRailroadHtml } from 'parseman/spec'\n *\n * const grammar = rules(g => ({ ... })) // your grammar\n * const ebnf = toEBNF(grammar) // EBNF text\n * const html = toRailroadHtml(grammar) // self-contained syntax diagrams\n *\n * Scope: syntax only, not semantics. See docs/proposals/grammar-spec-generation.md.\n */\nimport { buildSpecModel } from './model.ts'\nimport type { GrammarInput, SpecModel, SpecOptions } from './model.ts'\nimport { renderEBNF } from './ebnf.ts'\nimport { renderRailroadHtml } from './railroad.ts'\nimport type { RailroadHtmlOptions } from './railroad.ts'\n\nexport { buildSpecModel } from './model.ts'\nexport type { GrammarInput, SpecModel, SpecOptions, SpecNode, Production } from './model.ts'\nexport { renderEBNF, renderExpr } from './ebnf.ts'\nexport { renderRailroadHtml } from './railroad.ts'\nexport type { RailroadHtmlOptions } from './railroad.ts'\n\n/** Generate W3C-style EBNF text (one production per named rule). */\nexport function toEBNF(grammar: GrammarInput, options?: SpecOptions): string {\n return renderEBNF(buildSpecModel(grammar, options))\n}\n\n/**\n * Generate a self-contained HTML page of SVG railroad (syntax) diagrams \u2014 one\n * per production \u2014 with an EBNF caption under each. No external dependencies.\n */\nexport function toRailroadHtml(\n grammar: GrammarInput,\n options?: SpecOptions & RailroadHtmlOptions,\n): string {\n const model: SpecModel = buildSpecModel(grammar, options)\n return renderRailroadHtml(model, options)\n}\n", "import type { Combinator } from '../types.ts'\nimport { ref } from './ref.ts'\nimport { markUnusedValues } from '../compiler/value-usage.ts'\n\n/**\n * Non-enumerable key on a `rules()` result holding the factory's declaration\n * order (the returned object's key order), which differs from the result's own\n * reference-creation key order. Read by `parseman/spec` for source-order output.\n */\nexport const RULE_ORDER = '__parsemanRuleOrder'\n\nfunction tagRule(r: Combinator<unknown>, key: string): void {\n ;(r as unknown as { _ruleName?: string })._ruleName = key\n if (r._def.tag === 'node' && r._def.type === undefined) r._def.type = key\n}\n\n/**\n * Define named grammar rules without forward declarations.\n *\n * Pass a factory that receives all rule names as references (via a Proxy)\n * and returns a record of combinators. rules() handles creating ref()\n * placeholders and wiring them up \u2014 the user never sees ref() at all.\n *\n * const { value } = rules(g => ({\n * value: choice(g.object, g.array, str, num, bool, nil),\n * object: transform(sequence('{', sepBy(g.pair, ','), '}'), Object.fromEntries),\n * array: transform(sequence('[', sepBy(g.value, ','), ']'), ([, items]) => items),\n * pair: transform(sequence(g.key, literal(':'), g.value), ([k,, v]) => [k, v]),\n * }))\n *\n * Not every name in the factory must appear in the returned object \u2014 local helpers\n * (like `comma`, `key`) can be plain const inside the factory and composed normally.\n * Only names that OTHER rules reference via `g.xxx` need to be in the returned record.\n *\n * TypeScript: use an explicit type parameter for full type safety on `g`:\n * rules<{ value: Combinator<JSONValue>; array: Combinator<JSONValue[]> }>(g => ({ ... }))\n * Without it, `g.*` accesses are typed as `any` but the return is still inferred.\n */\n/**\n * Grammar-level options for `rules()`. Parity with `parser({...})`, but declared\n * ONCE for the whole grammar instead of wrapped around a scope. `trivia` becomes\n * the ambient trivia for every rule (installed at the parse entry, inherited\n * everywhere, incremental parse included); `parser({trivia})` / `noTrivia` still\n * override it locally for a sub-region.\n */\nexport type RulesOptions = {\n /** Ambient trivia for the whole grammar. See `parser({ trivia })` for the shape. */\n trivia?: Combinator<unknown>\n}\n\n// Options-first, mirroring `parser({ opts }, combinator)` \u2014 set once on the grammar\n// vs scope it locally, same options in the same position. The bare `rules(factory)`\n// form is unchanged. The impl also tolerates the legacy `rules(factory, opts)` order.\nexport function rules<T extends Record<string, Combinator<unknown>>>(factory: (self: any) => T): T\nexport function rules<T extends Record<string, Combinator<unknown>>>(options: RulesOptions, factory: (self: any) => T): T\nexport function rules<T extends Record<string, Combinator<unknown>>>(\n a: ((self: any) => T) | RulesOptions,\n b?: (self: any) => T,\n): T {\n const factory = (typeof a === 'function' ? a : b) as (self: any) => T\n const options = (typeof a === 'function' ? b : a) as RulesOptions | undefined\n const cache: Partial<T> = {}\n\n // Proxy: accessing any property creates a ref() placeholder on first touch.\n const proxy = new Proxy(cache, {\n get(target, key) {\n if (typeof key !== 'string') return undefined\n const record = target as Record<string, Combinator<unknown>>\n if (!(key in record)) {\n const r = ref()\n // Tag the placeholder with its rule name so the linkable compiler can\n // emit a by-name `_r_<key>` call for a reference to a rule defined in\n // ANOTHER artifact (resolved at fuse time) \u2014 see compileLinkable.\n tagRule(r, key)\n record[key] = r\n }\n return record[key]\n },\n })\n\n // Evaluate all rule definitions. JavaScript evaluates object-literal values\n // left-to-right, so any `g.ruleName` access inside triggers placeholder creation\n // before the rule's own parser is built \u2014 enabling forward references.\n const definitions = factory(proxy)\n\n // Fill each ref with its actual definition, or store directly if never accessed via proxy.\n for (const key of Object.keys(definitions)) {\n const placeholder = (cache as Record<string, Combinator<unknown>>)[key]\n const parser = (definitions as Record<string, Combinator<unknown>>)[key]!\n if (placeholder !== undefined && typeof (placeholder as any).define === 'function') {\n tagRule(parser, key)\n ;(placeholder as any).define(parser)\n // Propagate actual first-set so later choices wrapping this ref get correct dispatch.\n placeholder._meta.firstSet = parser._meta.firstSet\n placeholder._meta.canMatchNewline = parser._meta.canMatchNewline\n } else {\n tagRule(parser, key)\n ;(cache as Record<string, Combinator<unknown>>)[key] = parser\n }\n }\n\n // Declare the grammar-level ambient trivia on every rule, so parsing ANY rule\n // as an entry installs it (run()/parse() read this), and the macro can seed the\n // compiled map. `parser({trivia})` / `noTrivia` still override it locally.\n if (options?.trivia !== undefined) {\n for (const key of Object.keys(definitions)) {\n const rule = (cache as Record<string, Combinator<unknown>>)[key]\n // Skip trivia rules (e.g. the grammar's `rw`, returned so the driver can\n // reach it as `g.rw`): a trivia rule must never carry ambient trivia, or it\n // would recursively skip trivia within itself. Mirrors the codegen guard.\n if (rule && !rule._meta.isTrivia) (rule._meta as { grammarTrivia?: Combinator<unknown> }).grammarTrivia = options.trivia\n }\n }\n\n // Dead-value analysis: mark container aggregates that only feed a node()'s\n // capture so the interpreter (and, via the same flag, the compiled output) skips\n // building them. Each rule is its own root \u2014 refs are boundaries (see value-usage).\n for (const key of Object.keys(definitions)) {\n markUnusedValues((cache as Record<string, Combinator<unknown>>)[key]!)\n }\n\n // Record the factory's DECLARATION order (the returned object's key order).\n // `cache`'s own key order is reference-creation order \u2014 a Proxy artifact \u2014 so\n // it can lead with an internal rule instead of the entry rule. Consumers that\n // want the order the author actually wrote (e.g. `parseman/spec`) read this.\n // Non-enumerable, so Object.keys / spread / for-in over the grammar are\n // unaffected and every existing consumer sees exactly the rules it did before.\n Object.defineProperty(cache, RULE_ORDER, {\n value: Object.keys(definitions),\n enumerable: false,\n configurable: true,\n })\n\n return cache as T\n}\n", "/**\n * Grammar spec model \u2014 a small, notation-agnostic tree that both the EBNF\n * emitter and the railroad-diagram emitter consume.\n *\n * The model is produced by walking the SAME `_def` structure the interpreter\n * and macro compiler consume, so a generated spec cannot drift from what\n * actually parses. See `docs/proposals/grammar-spec-generation.md`.\n */\nimport type { Combinator, ParserDef } from '../types.ts'\nimport { RULE_ORDER } from '../combinators/parser.ts'\n\n// ---------------------------------------------------------------------------\n// Spec node tree\n// ---------------------------------------------------------------------------\n\n/** A node in the grammar spec tree \u2014 one per syntactic construct. */\nexport type SpecNode =\n | { kind: 'seq'; items: SpecNode[] }\n | { kind: 'choice'; items: SpecNode[] }\n | { kind: 'star'; item: SpecNode }\n | { kind: 'plus'; item: SpecNode }\n | { kind: 'opt'; item: SpecNode }\n /** Separated repetition (`sepBy`): `item (sep item)*` (min 0) or `item (sep item)+` \u2014 always \u22651 here. */\n | { kind: 'sepBy'; item: SpecNode; sep: SpecNode }\n /** Reference to a named production (non-terminal). */\n | { kind: 'ref'; name: string }\n /**\n * A terminal. `literal` terminals are exact strings (rendered quoted);\n * non-literal terminals are patterns/prose (rendered as-is, e.g. a regex\n * or a caller-supplied display name).\n */\n | { kind: 'terminal'; text: string; literal: boolean }\n /** Negative lookahead (`not`). Rendered as an annotation, not consumed input. */\n | { kind: 'not'; item: SpecNode }\n /** An out-of-band annotation (guards, error-recovery, unknowns). */\n | { kind: 'annotation'; text: string }\n /** Matches nothing (elided trivia / semantic-only wrappers). */\n | { kind: 'empty' }\n\n/** One named production: `name ::= expr`. */\nexport type Production = {\n name: string\n expr: SpecNode\n /** True when the rule is trivia (whitespace/comment). Elided by default. */\n trivia: boolean\n}\n\nexport type SpecModel = {\n productions: Production[]\n}\n\nexport type SpecOptions = {\n /**\n * How to order the emitted productions when neither `order` nor `root` is given:\n * - `'source'` (default) \u2014 the order the rules were **declared** in the\n * `rules()` factory. Predictable, includes every rule, and leads with the\n * entry rule (authors write it first). Internal-but-referenced helper rules\n * follow, in first-reference order.\n * - `'reachable'` \u2014 BFS from the entry rule: the first-declared rule leads,\n * then each rule appears the first time it is referenced; any rules not\n * reachable from the entry are appended in declaration order.\n * Ignored when `order` or `root` is set.\n */\n sort?: 'source' | 'reachable'\n /**\n * Explicit rule order (and subset). When given, only these rules are emitted,\n * in this order, plus any rules they reach. Overrides `sort`.\n */\n order?: string[]\n /**\n * Start rule(s). When given, only these and the rules they reach are emitted\n * (a pruned, reachability-ordered spec). Overrides `sort`.\n */\n root?: string | string[]\n /** Include trivia rules (whitespace/comment) in the output. Default: false. */\n includeTrivia?: boolean\n /**\n * Display names for terminals, keyed by rule name. When a rule whose body is a\n * single terminal (regex/literal/keywords) has an entry here, that whole rule\n * renders as the given terminal name instead of expanding \u2014 e.g.\n * `{ Ident: 'identifier' }`.\n */\n terminals?: Record<string, string>\n /**\n * Best-effort rendering of a regex terminal to a readable form. Return\n * `undefined` to fall back to the default `/source/` rendering.\n */\n regexDisplay?: (source: string, flags: string) => string | undefined\n}\n\nexport type GrammarInput =\n | Record<string, Combinator<unknown>>\n | Combinator<unknown>\n\n// ---------------------------------------------------------------------------\n// Walk\n// ---------------------------------------------------------------------------\n\ntype Tagged = Combinator<unknown> & { _ruleName?: string }\n\nfunction ruleNameOf(c: Combinator<unknown>): string | undefined {\n return (c as Tagged)._ruleName\n}\n\n/** Resolve a `lazy`/`ref` combinator one hop to its defined body, if resolvable. */\nfunction resolveLazy(c: Combinator<unknown>): Combinator<unknown> | undefined {\n const def = c._def\n if (def.tag !== 'lazy') return undefined\n try {\n return def.thunk() as Combinator<unknown>\n } catch {\n return undefined\n }\n}\n\nfunction defaultRegexDisplay(source: string): string {\n return `/${source}/`\n}\n\nclass Builder {\n private seen = new Set<string>()\n private pending: Array<{ name: string; comb: Combinator<unknown> }> = []\n private pendingNames = new Set<string>()\n private record: Record<string, Combinator<unknown>>\n private opts: SpecOptions\n productions: Production[] = []\n\n constructor(record: Record<string, Combinator<unknown>>, opts: SpecOptions) {\n this.record = record\n this.opts = opts\n }\n\n enqueue(name: string, comb: Combinator<unknown>): void {\n if (this.seen.has(name)) return\n if (this.pendingNames.has(name)) return\n this.pendingNames.add(name)\n this.pending.push({ name, comb })\n }\n\n /**\n * Seed and drain in phases. Each phase seeds its names, then BFS-drains the\n * queue (following references) before the next phase seeds. This lets callers\n * express \"entry first, then its reachable closure, then any leftovers\" by\n * splitting the seed across phases; a single phase with every rule yields plain\n * declaration order (references, already queued, keep their declared slot).\n */\n run(phases: string[][]): SpecModel {\n for (const phase of phases) {\n for (const name of phase) {\n const comb = this.record[name]\n if (comb) this.enqueue(name, comb)\n }\n this.drain()\n }\n return { productions: this.productions }\n }\n\n private drain(): void {\n while (this.pending.length > 0) {\n const { name, comb } = this.pending.shift()!\n this.pendingNames.delete(name)\n if (this.seen.has(name)) continue\n this.seen.add(name)\n const expr = this.ruleBody(comb, name)\n this.productions.push({ name, expr, trivia: comb._meta.isTrivia === true })\n }\n }\n\n /** Walk a rule's top-level combinator, transparently unwrapping its own self-ref. */\n private ruleBody(comb: Combinator<unknown>, name: string): SpecNode {\n // A rule that IS a single terminal can be pinned to a caller display name.\n const pinned = this.opts.terminals?.[name]\n if (pinned !== undefined) return { kind: 'terminal', text: pinned, literal: false }\n\n let c = comb\n // Unwrap the rule's own placeholder ref(s) so we expand its body, not a\n // self-reference. Both the placeholder and the resolved body carry the same\n // `_ruleName`, so guard against cycles.\n const guard = new Set<Combinator<unknown>>()\n while (c._def.tag === 'lazy' && ruleNameOf(c) === name && !guard.has(c)) {\n guard.add(c)\n const next = resolveLazy(c)\n if (!next) break\n c = next\n }\n return this.walk(c, true)\n }\n\n /** Walk any combinator. `isRuleRoot` suppresses treating it as a self-reference. */\n private walk(c: Combinator<unknown>, isRuleRoot = false): SpecNode {\n // A reference to a named rule \u2192 non-terminal (unless this IS that rule's root).\n const rn = ruleNameOf(c)\n if (rn !== undefined && !isRuleRoot) {\n // Register the target so it gets its own production, even if it wasn't in\n // the returned record (internal-but-referenced helper rules).\n if (!this.record[rn]) this.record[rn] = c\n this.enqueue(rn, c)\n return { kind: 'ref', name: rn }\n }\n return this.walkDef(c._def, c)\n }\n\n private walkDef(def: ParserDef, self: Combinator<unknown>): SpecNode {\n switch (def.tag) {\n case 'literal':\n return { kind: 'terminal', text: def.value, literal: true }\n\n case 'regex': {\n const shown =\n this.opts.regexDisplay?.(def.source, def.flags) ??\n defaultRegexDisplay(def.source)\n return { kind: 'terminal', text: shown, literal: false }\n }\n\n case 'keywords':\n return {\n kind: 'choice',\n items: def.words.map(w => ({ kind: 'terminal', text: w, literal: true }) as SpecNode),\n }\n\n case 'sequence': {\n const items = def.parsers.map(p => this.walk(p)).filter(nonEmpty)\n return flattenSeq(items)\n }\n\n case 'choice': {\n const items = def.parsers.map(p => this.walk(p)).filter(nonEmpty)\n return flattenChoice(items)\n }\n\n case 'many':\n return { kind: 'star', item: this.walk(def.parser) }\n case 'oneOrMore':\n return { kind: 'plus', item: this.walk(def.parser) }\n case 'optional':\n return { kind: 'opt', item: this.walk(def.parser) }\n case 'sepBy':\n return { kind: 'sepBy', item: this.walk(def.parser), sep: this.walk(def.separator) }\n\n case 'not':\n return { kind: 'not', item: this.walk(def.parser) }\n\n // Transparent semantic wrappers \u2014 render the inner syntax.\n case 'transform':\n case 'token':\n case 'label':\n case 'field':\n case 'expect':\n case 'withCtx':\n case 'node':\n return this.walk((def as { parser: Combinator<unknown> }).parser)\n\n case 'skip':\n return this.walk(def.main)\n case 'grammar':\n return this.walk(def.parser)\n\n // Error recovery \u2014 render the intended sub-parser, drop the sentinel.\n case 'recover':\n return this.walk(def.parser)\n case 'scanTo':\n return { kind: 'annotation', text: '\u2026' }\n\n // Trivia \u2014 elided by default; included as an annotation when asked.\n case 'trivia':\n return this.opts.includeTrivia ? this.walk(def.parser) : { kind: 'empty' }\n\n case 'guard':\n return { kind: 'empty' }\n\n case 'lazy': {\n const inner = resolveLazy(self)\n return inner ? this.walk(inner) : { kind: 'annotation', text: '?' }\n }\n\n case 'unknown':\n default:\n return { kind: 'annotation', text: '?' }\n }\n }\n}\n\nfunction nonEmpty(n: SpecNode): boolean {\n return n.kind !== 'empty'\n}\n\nfunction flattenSeq(items: SpecNode[]): SpecNode {\n const flat: SpecNode[] = []\n for (const it of items) {\n if (it.kind === 'seq') flat.push(...it.items)\n else flat.push(it)\n }\n if (flat.length === 0) return { kind: 'empty' }\n if (flat.length === 1) return flat[0]!\n return { kind: 'seq', items: flat }\n}\n\nfunction flattenChoice(items: SpecNode[]): SpecNode {\n const flat: SpecNode[] = []\n for (const it of items) {\n if (it.kind === 'choice') flat.push(...it.items)\n else flat.push(it)\n }\n if (flat.length === 0) return { kind: 'empty' }\n if (flat.length === 1) return flat[0]!\n return { kind: 'choice', items: flat }\n}\n\nfunction toRecord(grammar: GrammarInput): Record<string, Combinator<unknown>> {\n // A single combinator \u2192 a one-rule grammar keyed by its rule name or \"start\".\n if (isCombinator(grammar)) {\n const name = ruleNameOf(grammar) ?? 'start'\n return { [name]: grammar }\n }\n return grammar\n}\n\nfunction isCombinator(x: unknown): x is Combinator<unknown> {\n return (\n typeof x === 'object' &&\n x !== null &&\n typeof (x as { parse?: unknown }).parse === 'function' &&\n '_def' in (x as object)\n )\n}\n\n/** Declaration order recorded by `rules()`; falls back to the record's key order. */\nfunction declarationOrder(record: Record<string, Combinator<unknown>>): string[] {\n const declared = (record as Record<string, unknown>)[RULE_ORDER]\n if (Array.isArray(declared)) return declared.filter(k => k in record)\n return Object.keys(record)\n}\n\n/**\n * Build the notation-agnostic spec model from a `rules()` grammar (or a single\n * combinator). Following every referenced named rule keeps the closure complete;\n * ordering is controlled by `order` / `root` / `sort` (see {@link SpecOptions}).\n */\nexport function buildSpecModel(grammar: GrammarInput, options: SpecOptions = {}): SpecModel {\n const record = toRecord(grammar)\n const decl = declarationOrder(record)\n\n // Seed phases (see Builder.run). Priority: explicit `order` > `root` (pruned) >\n // `sort`. Default `sort` = 'source' (declaration order, every rule).\n let phases: string[][]\n if (options.order) {\n phases = [options.order]\n } else if (options.root !== undefined) {\n phases = [Array.isArray(options.root) ? options.root : [options.root]]\n } else if (options.sort === 'reachable') {\n // Entry (first-declared) leads; BFS discovers the rest in first-reference\n // order; unreachable rules trail in declaration order.\n phases = decl.length > 0 ? [[decl[0]!], decl.slice(1)] : [decl]\n } else {\n phases = [decl]\n }\n\n const model = new Builder({ ...record }, options).run(phases)\n if (!options.includeTrivia) {\n model.productions = model.productions.filter(p => !p.trivia)\n }\n return model\n}\n", "/**\n * EBNF (W3C-style) text emitter for the grammar spec model.\n *\n * Precedence, lowest \u2192 highest: alternation (`|`) < concatenation (space) <\n * postfix (`* + ?`) < atom. The renderer parenthesizes only where a lower-\n * precedence construct sits inside a higher-precedence one.\n */\nimport type { Production, SpecModel, SpecNode } from './model.ts'\n\nconst ALT = 1 // choice\nconst CAT = 2 // sequence\nconst ATOM = 3 // terminal, ref, postfix, parenthesized\n\nfunction quote(s: string): string {\n // W3C EBNF uses quoted string terminals; prefer double quotes, fall back to\n // single quotes when the literal itself contains a double quote.\n if (s.includes('\"') && !s.includes(\"'\")) return `'${s}'`\n return `\"${s.replace(/\"/g, '\\\\\"')}\"`\n}\n\nfunction wrap(inner: string, innerLevel: number, minLevel: number): string {\n return innerLevel < minLevel ? `(${inner})` : inner\n}\n\n/** Render a node, returning its text and precedence level. */\nfunction render(node: SpecNode): { text: string; level: number } {\n switch (node.kind) {\n case 'terminal':\n return { text: node.literal ? quote(node.text) : node.text, level: ATOM }\n case 'ref':\n return { text: node.name, level: ATOM }\n case 'empty':\n return { text: '', level: ATOM }\n case 'annotation':\n return { text: `/* ${node.text} */`, level: ATOM }\n\n case 'seq': {\n const text = node.items\n .map(it => {\n const r = render(it)\n return wrap(r.text, r.level, CAT)\n })\n .filter(t => t.length > 0)\n .join(' ')\n return { text, level: CAT }\n }\n\n case 'choice': {\n const text = node.items\n .map(it => {\n const r = render(it)\n return wrap(r.text, r.level, ALT)\n })\n .join(' | ')\n return { text, level: ALT }\n }\n\n case 'star':\n case 'plus':\n case 'opt': {\n const r = render(node.item)\n const op = node.kind === 'star' ? '*' : node.kind === 'plus' ? '+' : '?'\n return { text: `${wrap(r.text, r.level, ATOM)}${op}`, level: ATOM }\n }\n\n case 'sepBy': {\n const item = render(node.item)\n const sep = render(node.sep)\n const itemA = wrap(item.text, item.level, ATOM)\n const sepA = wrap(sep.text, sep.level, CAT)\n // item (sep item)*\n return { text: `${itemA} (${sepA} ${itemA})*`, level: CAT }\n }\n\n case 'not': {\n const r = render(node.item)\n return { text: `!${wrap(r.text, r.level, ATOM)}`, level: ATOM }\n }\n }\n}\n\nfunction renderProduction(p: Production): string {\n const { text } = render(p.expr)\n return `${p.name} ::= ${text || '/* empty */'}`\n}\n\n/** Render the whole spec model as EBNF text (one production per line). */\nexport function renderEBNF(model: SpecModel): string {\n return model.productions.map(renderProduction).join('\\n') + '\\n'\n}\n\n/** Render a single production's right-hand side (no `name ::=`). */\nexport function renderExpr(node: SpecNode): string {\n return render(node).text\n}\n", "/**\n * Vendored copy of tabatkins railroad-diagrams (v1.0.0), license CC0-1.0.\n * https://github.com/tabatkins/railroad-diagrams\n *\n * Public domain (CC0) \u2014 embedded verbatim as strings so the generated\n * railroad-diagram HTML page is fully self-contained (no CDN, no runtime dep).\n * Do not edit by hand; regenerate from the npm package if bumping versions.\n */\n/* eslint-disable */\nexport const RAILROAD_JS: string = `/*\nRailroad Diagrams\nby Tab Atkins Jr. (and others)\nhttp://xanthir.com\nhttp://twitter.com/tabatkins\nhttp://github.com/tabatkins/railroad-diagrams\n\nThis document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/\nThis means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION.\n(The actual legal meaning can be found at the above link.)\nDon't ask me for permission to use any part of this project, JUST USE IT.\nI would appreciate attribution, but that is not required by the license.\n*/\n\n/*\nThis file uses a module pattern to avoid leaking names into the global scope.\nThe only accidental leakage is the name \"temp\".\nThe exported names can be found at the bottom of this file;\nsimply change the names in the array of strings to change what they are called in your application.\n\nAs well, several configuration constants are passed into the module function at the bottom of this file.\nAt runtime, these constants can be found on the Diagram class.\n*/\n\n(function(options) {\n\tfunction subclassOf(baseClass, superClass) {\n\t\tbaseClass.prototype = Object.create(superClass.prototype);\n\t\tbaseClass.prototype.$super = superClass.prototype;\n\t}\n\n\tfunction unnull(/* children */) {\n\t\treturn [].slice.call(arguments).reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; });\n\t}\n\n\tfunction determineGaps(outer, inner) {\n\t\tvar diff = outer - inner;\n\t\tswitch(Diagram.INTERNAL_ALIGNMENT) {\n\t\t\tcase 'left': return [0, diff]; break;\n\t\t\tcase 'right': return [diff, 0]; break;\n\t\t\tcase 'center':\n\t\t\tdefault: return [diff/2, diff/2]; break;\n\t\t}\n\t}\n\n\tfunction wrapString(value) {\n\t\treturn ((typeof value) == 'string') ? new Terminal(value) : value;\n\t}\n\n\n\tfunction SVG(name, attrs, text) {\n\t\tattrs = attrs || {};\n\t\ttext = text || '';\n\t\tvar el = document.createElementNS(\"http://www.w3.org/2000/svg\",name);\n\t\tfor(var attr in attrs) {\n\t\t\tel.setAttribute(attr, attrs[attr]);\n\t\t}\n\t\tel.textContent = text;\n\t\treturn el;\n\t}\n\n\tfunction FakeSVG(tagName, attrs, text){\n\t\tif(!(this instanceof FakeSVG)) return new FakeSVG(tagName, attrs, text);\n\t\tif(text) this.children = text;\n\t\telse this.children = [];\n\t\tthis.tagName = tagName;\n\t\tthis.attrs = unnull(attrs, {});\n\t\treturn this;\n\t};\n\tFakeSVG.prototype.format = function(x, y, width) {\n\t\t// Virtual\n\t};\n\tFakeSVG.prototype.addTo = function(parent) {\n\t\tif(parent instanceof FakeSVG) {\n\t\t\tparent.children.push(this);\n\t\t\treturn this;\n\t\t} else {\n\t\t\tvar svg = this.toSVG();\n\t\t\tparent.appendChild(svg);\n\t\t\treturn svg;\n\t\t}\n\t};\n\tFakeSVG.prototype.escapeString = function(string) {\n // Escape markdown and HTML special characters\n\t\treturn string.replace(/[*_\\\\\\`\\\\[\\\\]<&]/g, function(charString) {\n\t\t\treturn '&#' + charString.charCodeAt(0) + ';';\n\t\t});\n\t};\n\tFakeSVG.prototype.toSVG = function() {\n\t\tvar el = SVG(this.tagName, this.attrs);\n\t\tif(typeof this.children == 'string') {\n\t\t\tel.innerHTML = FakeSVG.prototype.escapeString(this.children);\n\t\t} else {\n\t\t\tthis.children.forEach(function(e) {\n\t\t\t\tel.appendChild(e.toSVG());\n\t\t\t});\n\t\t}\n\t\treturn el;\n\t};\n\tFakeSVG.prototype.toString = function() {\n\t\tvar str = '<' + this.tagName;\n\t\tvar group = this.tagName == \"g\" || this.tagName == \"svg\";\n\t\tfor(var attr in this.attrs) {\n\t\t\tstr += ' ' + attr + '=\"' + (this.attrs[attr]+'').replace(/&/g, '&amp;').replace(/\"/g, '&quot;') + '\"';\n\t\t}\n\t\tstr += '>';\n\t\tif(group) str += \"\\\\n\";\n\t\tif(typeof this.children == 'string') {\n\t\t\tstr += FakeSVG.prototype.escapeString(this.children);\n\t\t} else {\n\t\t\tthis.children.forEach(function(e) {\n\t\t\t\tstr += e;\n\t\t\t});\n\t\t}\n\t\tstr += '</' + this.tagName + '>\\\\n';\n\t\treturn str;\n\t}\n\n\tfunction Path(x,y) {\n\t\tif(!(this instanceof Path)) return new Path(x,y);\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.attrs.d = \"M\"+x+' '+y;\n\t}\n\tsubclassOf(Path, FakeSVG);\n\tPath.prototype.m = function(x,y) {\n\t\tthis.attrs.d += 'm'+x+' '+y;\n\t\treturn this;\n\t}\n\tPath.prototype.h = function(val) {\n\t\tthis.attrs.d += 'h'+val;\n\t\treturn this;\n\t}\n\tPath.prototype.right = Path.prototype.h;\n\tPath.prototype.left = function(val) { return this.h(-val); }\n\tPath.prototype.v = function(val) {\n\t\tthis.attrs.d += 'v'+val;\n\t\treturn this;\n\t}\n\tPath.prototype.down = Path.prototype.v;\n\tPath.prototype.up = function(val) { return this.v(-val); }\n\tPath.prototype.arc = function(sweep){\n\t\tvar x = Diagram.ARC_RADIUS;\n\t\tvar y = Diagram.ARC_RADIUS;\n\t\tif(sweep[0] == 'e' || sweep[1] == 'w') {\n\t\t\tx *= -1;\n\t\t}\n\t\tif(sweep[0] == 's' || sweep[1] == 'n') {\n\t\t\ty *= -1;\n\t\t}\n\t\tif(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') {\n\t\t\tvar cw = 1;\n\t\t} else {\n\t\t\tvar cw = 0;\n\t\t}\n\t\tthis.attrs.d += \"a\"+Diagram.ARC_RADIUS+\" \"+Diagram.ARC_RADIUS+\" 0 0 \"+cw+' '+x+' '+y;\n\t\treturn this;\n\t}\n\tPath.prototype.format = function() {\n\t\t// All paths in this library start/end horizontally.\n\t\t// The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers.\n\t\tthis.attrs.d += 'h.5';\n\t\treturn this;\n\t}\n\n\tfunction Diagram(items) {\n\t\tif(!(this instanceof Diagram)) return new Diagram([].slice.call(arguments));\n\t\tFakeSVG.call(this, 'svg', {class: Diagram.DIAGRAM_CLASS});\n\t\tthis.items = items.map(wrapString);\n\t\tthis.items.unshift(new Start);\n\t\tthis.items.push(new End);\n\t\tthis.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0)+1;\n\t\tthis.up = Math.max.apply(null, this.items.map(function (x) { return x.up; }));\n\t\tthis.down = Math.max.apply(null, this.items.map(function (x) { return x.down; }));\n\t\tthis.formatted = false;\n\t}\n\tsubclassOf(Diagram, FakeSVG);\n\tfor(var option in options) {\n\t\tDiagram[option] = options[option];\n\t}\n\tDiagram.prototype.format = function(paddingt, paddingr, paddingb, paddingl) {\n\t\tpaddingt = unnull(paddingt, 20);\n\t\tpaddingr = unnull(paddingr, paddingt, 20);\n\t\tpaddingb = unnull(paddingb, paddingt, 20);\n\t\tpaddingl = unnull(paddingl, paddingr, 20);\n\t\tvar x = paddingl;\n\t\tvar y = paddingt;\n\t\ty += this.up;\n\t\tvar g = FakeSVG('g', Diagram.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {});\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(g);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t\titem.format(x, y, item.width).addTo(g);\n\t\t\tx += item.width;\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(g);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t}\n\t\tthis.attrs.width = this.width + paddingl + paddingr;\n\t\tthis.attrs.height = this.up + this.down + paddingt + paddingb;\n\t\tthis.attrs.viewBox = \"0 0 \" + this.attrs.width + \" \" + this.attrs.height;\n\t\tg.addTo(this);\n\t\tthis.formatted = true;\n\t\treturn this;\n\t}\n\tDiagram.prototype.addTo = function(parent) {\n\t\tvar scriptTag = document.getElementsByTagName('script');\n\t\tscriptTag = scriptTag[scriptTag.length - 1];\n\t\tvar parentTag = scriptTag.parentNode;\n\t\tparent = parent || parentTag;\n\t\treturn this.$super.addTo.call(this, parent);\n\t}\n\tDiagram.prototype.toSVG = function() {\n\t\tif (!this.formatted) {\n\t\t\tthis.format();\n\t\t}\n\t\treturn this.$super.toSVG.call(this);\n\t}\n\tDiagram.prototype.toString = function() {\n\t\tif (!this.formatted) {\n\t\t\tthis.format();\n\t\t}\n\t\treturn this.$super.toString.call(this);\n\t}\n\n\tfunction ComplexDiagram() {\n\t\tvar diagram = new Diagram([].slice.call(arguments));\n var items = diagram.items;\n\t\titems.shift();\n\t\titems.pop();\n\t\titems.unshift(new Start(false));\n\t\titems.push(new End(false));\n\t\tdiagram.items = items;\n\t\treturn diagram;\n }\n\n\tfunction Sequence(items) {\n\t\tif(!(this instanceof Sequence)) return new Sequence([].slice.call(arguments));\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.items = items.map(wrapString);\n\t\tthis.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0);\n\t\tthis.up = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.up)}, 0);\n\t\tthis.down = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.down)}, 0);\n\t}\n\tsubclassOf(Sequence, FakeSVG);\n\tSequence.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(this);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t\titem.format(x, y, item.width).addTo(this);\n\t\t\tx += item.width;\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(this);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction Choice(normal, items) {\n\t\tif(!(this instanceof Choice)) return new Choice(normal, [].slice.call(arguments,1));\n\t\tFakeSVG.call(this, 'g');\n\t\tif( typeof normal !== \"number\" || normal !== Math.floor(normal) ) {\n\t\t\tthrow new TypeError(\"The first argument of Choice() must be an integer.\");\n\t\t} else if(normal < 0 || normal >= items.length) {\n\t\t\tthrow new RangeError(\"The first argument of Choice() must be an index for one of the items.\");\n\t\t} else {\n\t\t\tthis.normal = normal;\n\t\t}\n\t\tthis.items = items.map(wrapString);\n\t\tthis.width = this.items.reduce(function(sofar, el){return Math.max(sofar, el.width)},0) + Diagram.ARC_RADIUS*4;\n\t\tthis.up = this.down = 0;\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(i < normal) { this.up += Math.max(Diagram.ARC_RADIUS,item.up + item.down + Diagram.VERTICAL_SEPARATION); }\n\t\t\tif(i == normal) { this.up += Math.max(Diagram.ARC_RADIUS, item.up); this.down += Math.max(Diagram.ARC_RADIUS, item.down); }\n\t\t\tif(i > normal) { this.down += Math.max(Diagram.ARC_RADIUS,Diagram.VERTICAL_SEPARATION + item.up + item.down); }\n\t\t}\n\t}\n\tsubclassOf(Choice, FakeSVG);\n\tChoice.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tvar last = this.items.length -1;\n\t\tvar innerWidth = this.width - Diagram.ARC_RADIUS*4;\n\n\t\t// Do the elements that curve above\n\t\tfor(var i = this.normal - 1; i >= 0; i--) {\n\t\t\tvar item = this.items[i];\n\t\t\tif( i == this.normal - 1 ) {\n\t\t\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i+1].up + Diagram.VERTICAL_SEPARATION + item.down);\n\t\t\t}\n\t\t\tPath(x,y).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);\n\t\t\titem.format(x+Diagram.ARC_RADIUS*2,y - distanceFromY,innerWidth).addTo(this);\n\t\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y-distanceFromY).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\t\tdistanceFromY += Math.max(Diagram.ARC_RADIUS, item.up + Diagram.VERTICAL_SEPARATION + (i == 0 ? 0 : this.items[i-1].down));\n\t\t}\n\n\t\t// Do the straight-line path.\n\t\tPath(x,y).right(Diagram.ARC_RADIUS*2).addTo(this);\n\t\tthis.items[this.normal].format(x+Diagram.ARC_RADIUS*2, y, innerWidth).addTo(this);\n\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y).right(Diagram.ARC_RADIUS*2).addTo(this);\n\n\t\t// Do the elements that curve below\n\t\tfor(var i = this.normal+1; i <= last; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif( i == this.normal + 1 ) {\n\t\t\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i-1].down + Diagram.VERTICAL_SEPARATION + item.up);\n\t\t\t}\n\t\t\tPath(x,y).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\t\titem.format(x+Diagram.ARC_RADIUS*2, y+distanceFromY, innerWidth).addTo(this);\n\t\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y+distanceFromY).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);\n\t\t\tdistanceFromY += Math.max(Diagram.ARC_RADIUS, item.down + Diagram.VERTICAL_SEPARATION + (i == last ? 0 : this.items[i+1].up));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tfunction Optional(item, skip) {\n\t\tif( skip === undefined )\n\t\t\treturn Choice(1, Skip(), item);\n\t\telse if ( skip === \"skip\" )\n\t\t\treturn Choice(0, Skip(), item);\n\t\telse\n\t\t\tthrow \"Unknown value for Optional()'s 'skip' argument.\";\n\t}\n\n\tfunction OneOrMore(item, rep) {\n\t\tif(!(this instanceof OneOrMore)) return new OneOrMore(item, rep);\n\t\tFakeSVG.call(this, 'g');\n\t\trep = rep || (new Skip);\n\t\tthis.item = wrapString(item);\n\t\tthis.rep = wrapString(rep);\n\t\tthis.width = Math.max(this.item.width, this.rep.width) + Diagram.ARC_RADIUS*2;\n\t\tthis.up = this.item.up;\n\t\tthis.down = Math.max(Diagram.ARC_RADIUS*2, this.item.down + Diagram.VERTICAL_SEPARATION + this.rep.up + this.rep.down);\n\t}\n\tsubclassOf(OneOrMore, FakeSVG);\n\tOneOrMore.prototype.needsSpace = true;\n\tOneOrMore.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\t// Draw item\n\t\tPath(x,y).right(Diagram.ARC_RADIUS).addTo(this);\n\t\tthis.item.format(x+Diagram.ARC_RADIUS,y,this.width-Diagram.ARC_RADIUS*2).addTo(this);\n\t\tPath(x+this.width-Diagram.ARC_RADIUS,y).right(Diagram.ARC_RADIUS).addTo(this);\n\n\t\t// Draw repeat arc\n\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up);\n\t\tPath(x+Diagram.ARC_RADIUS,y).arc('nw').down(distanceFromY-Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\tthis.rep.format(x+Diagram.ARC_RADIUS, y+distanceFromY, this.width - Diagram.ARC_RADIUS*2).addTo(this);\n\t\tPath(x+this.width-Diagram.ARC_RADIUS, y+distanceFromY).arc('se').up(distanceFromY-Diagram.ARC_RADIUS*2).arc('en').addTo(this);\n\n\t\treturn this;\n\t}\n\n\tfunction ZeroOrMore(item, rep, skip) {\n\t\treturn Optional(OneOrMore(item, rep), skip);\n\t}\n\n\tfunction Start(simpleType) {\n\t\tif(!(this instanceof Start)) return new Start();\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.width = 20;\n\t\tthis.up = 10;\n\t\tthis.down = 10;\n\t\tthis.simpleType = simpleType;\n\t}\n\tsubclassOf(Start, FakeSVG);\n\tStart.prototype.format = function(x,y) {\n\t\tif (this.simpleType === false) {\n\t\t\tthis.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 0 -10 h 20.5';\n\t\t} else {\n\t\t\tthis.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 10 -20 v 20 m -10 -10 h 20.5';\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction End(simpleType) {\n\t\tif(!(this instanceof End)) return new End();\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.width = 20;\n\t\tthis.up = 10;\n\t\tthis.down = 10;\n\t\tthis.simpleType = simpleType;\n\t}\n\tsubclassOf(End, FakeSVG);\n\tEnd.prototype.format = function(x,y) {\n\t\tif (this.simpleType === false) {\n\t\t\tthis.attrs.d = 'M '+x+' '+y+' h 20 m 0 -10 v 20';\n\t\t} else {\n\t\t\tthis.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20';\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction Terminal(text) {\n\t\tif(!(this instanceof Terminal)) return new Terminal(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 8 + 20; /* Assume that each char is .5em, and that the em is 16px */\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(Terminal, FakeSVG);\n\tTerminal.prototype.needsSpace = true;\n\tTerminal.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this);\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction NonTerminal(text) {\n\t\tif(!(this instanceof NonTerminal)) return new NonTerminal(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 8 + 20;\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(NonTerminal, FakeSVG);\n\tNonTerminal.prototype.needsSpace = true;\n\tNonTerminal.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this);\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction Comment(text) {\n\t\tif(!(this instanceof Comment)) return new Comment(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 7 + 10;\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(Comment, FakeSVG);\n\tComment.prototype.needsSpace = true;\n\tComment.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction Skip() {\n\t\tif(!(this instanceof Skip)) return new Skip();\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.width = 0;\n\t\tthis.up = 0;\n\t\tthis.down = 0;\n\t}\n\tsubclassOf(Skip, FakeSVG);\n\tSkip.prototype.format = function(x, y, width) {\n\t\tPath(x,y).right(width).addTo(this);\n\t\treturn this;\n\t}\n\t\n\tvar root;\n\tif (typeof define === 'function' && define.amd) {\n\t\t// AMD. Register as an anonymous module.\n\t\troot = {};\n\t\tdefine([], function() {\n\t\t\treturn root;\n\t\t});\n\t} else if (typeof exports === 'object') {\n\t\t// CommonJS for node\n\t\troot = exports;\n\t} else {\n\t\t// Browser globals (root is window)\n\t\troot = this;\n\t}\n\n\tvar temp = [Diagram, ComplexDiagram, Sequence, Choice, Optional, OneOrMore, ZeroOrMore, Terminal, NonTerminal, Comment, Skip];\n\t/*\n\tThese are the names that the internal classes are exported as.\n\tIf you would like different names, adjust them here.\n\t*/\n\t['Diagram', 'ComplexDiagram', 'Sequence', 'Choice', 'Optional', 'OneOrMore', 'ZeroOrMore', 'Terminal', 'NonTerminal', 'Comment', 'Skip']\n\t\t.forEach(function(e,i) { root[e] = temp[i]; });\n}).call(this,\n\t{\n\tVERTICAL_SEPARATION: 8,\n\tARC_RADIUS: 10,\n\tDIAGRAM_CLASS: 'railroad-diagram',\n\tSTROKE_ODD_PIXEL_LENGTH: true,\n\tINTERNAL_ALIGNMENT: 'center',\n\t}\n);\n`\n\nexport const RAILROAD_CSS: string = `svg.railroad-diagram {\n background-color: hsl(30,20%,95%);\n}\nsvg.railroad-diagram path {\n stroke-width: 3;\n stroke: black;\n fill: rgba(0,0,0,0);\n}\nsvg.railroad-diagram text {\n font: bold 14px monospace;\n text-anchor: middle;\n}\nsvg.railroad-diagram text.label {\n text-anchor: start;\n}\nsvg.railroad-diagram text.comment {\n font: italic 12px monospace;\n}\nsvg.railroad-diagram rect {\n stroke-width: 3;\n stroke: black;\n fill: hsl(120,100%,90%);\n}\n`\n", "/**\n * Railroad-diagram (syntax-diagram) emitter. Converts the spec model to a\n * self-contained HTML page that renders SVG railroad diagrams \u2014 one per\n * production \u2014 using a vendored copy of tabatkins/railroad-diagrams (CC0).\n *\n * The page has no external dependencies: the diagram library and its CSS are\n * inlined, so it renders offline and drops straight into a docs site.\n */\nimport type { Production, SpecModel, SpecNode } from './model.ts'\nimport { renderExpr } from './ebnf.ts'\nimport { RAILROAD_CSS, RAILROAD_JS } from './railroad-lib.ts'\n\nconst j = (s: string): string => JSON.stringify(s)\n\n/** Convert a spec node to a railroad-diagrams DSL expression string. */\nfunction toDsl(node: SpecNode): string {\n switch (node.kind) {\n case 'terminal':\n return `Terminal(${j(node.text)})`\n case 'ref':\n return `NonTerminal(${j(node.name)})`\n case 'empty':\n return `Skip()`\n case 'annotation':\n return `Comment(${j(node.text)})`\n case 'seq':\n return `Sequence(${node.items.map(toDsl).join(', ')})`\n case 'choice':\n return `Choice(0, ${node.items.map(toDsl).join(', ')})`\n case 'star':\n return `ZeroOrMore(${toDsl(node.item)})`\n case 'plus':\n return `OneOrMore(${toDsl(node.item)})`\n case 'opt':\n return `Optional(${toDsl(node.item)})`\n case 'sepBy':\n // OneOrMore(item, separator): the separator rides the repeat loop.\n return `OneOrMore(${toDsl(node.item)}, ${toDsl(node.sep)})`\n case 'not':\n return `Sequence(Comment(\"not\"), ${toDsl(node.item)})`\n }\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction slug(name: string): string {\n return 'rule-' + name.replace(/[^\\w-]/g, '_')\n}\n\nexport type RailroadHtmlOptions = {\n /** Page `<title>` and top heading. Default: \"Grammar\". */\n title?: string\n /** Show the EBNF production text under each diagram. Default: true. */\n showEbnf?: boolean\n}\n\nconst PAGE_CSS = `\n /* The railroad SVGs ship a fixed light background, so the page commits to a\n light theme for a consistent look regardless of the viewer's OS setting. */\n body { font: 14px/1.5 system-ui, sans-serif; margin: 0; padding: 2rem 2.5rem;\n color: #1a1a1a; background: #fff; }\n h1 { font-size: 1.6rem; margin: 0 0 0.25rem; }\n .subtitle { color: #666; margin: 0 0 2rem; }\n .toc { columns: 3 12rem; margin: 0 0 2.5rem; padding: 1rem 1.25rem; background: #f6f4f1; border-radius: 8px; }\n .toc a { display: block; color: #0b6; text-decoration: none; font-family: monospace; padding: 1px 0; }\n .toc a:hover { text-decoration: underline; }\n .rule { margin: 0 0 2.75rem; padding-top: 0.5rem; border-top: 1px solid #eee; }\n .rule h2 { font-size: 1.1rem; font-family: monospace; margin: 0 0 0.75rem; }\n .rule h2 a { color: #bbb; text-decoration: none; font-weight: normal; }\n .rule h2 a:hover { color: #0b6; }\n .ebnf { margin: 0.5rem 0 0; padding: 0.5rem 0.75rem; background: #f6f4f1; border-radius: 6px;\n font-family: monospace; font-size: 12px; white-space: pre-wrap; overflow-x: auto; }\n .diagram { overflow-x: auto; }\n /* The vendored library sizes each shape as (chars * 8 + padding), which assumes\n an 8px glyph advance (0.5em at 16px). Its own 14px-bold CSS actually advances\n ~8.4px/char, so long terminals crowd the box edges. Drop the text to 13px\n (advance ~7.8px) to restore comfortable side padding, and nudge the baked\n baseline (y+4) down slightly so glyphs sit vertically centered in the shapes. */\n svg.railroad-diagram text { font-size: 13px; }\n svg.railroad-diagram text:not(.comment) { transform: translateY(0.75px); }\n`\n\n/** Render the spec model as a self-contained HTML page of railroad diagrams. */\nexport function renderRailroadHtml(model: SpecModel, options: RailroadHtmlOptions = {}): string {\n const title = options.title ?? 'Grammar'\n const showEbnf = options.showEbnf ?? true\n\n const toc = model.productions\n .map(p => `<a href=\"#${slug(p.name)}\">${escapeHtml(p.name)}</a>`)\n .join('\\n ')\n\n const sections = model.productions\n .map((p: Production) => {\n const ebnf = showEbnf\n ? `<div class=\"ebnf\">${escapeHtml(`${p.name} ::= ${renderExpr(p.expr) || '/* empty */'}`)}</div>`\n : ''\n return ` <section class=\"rule\" id=\"${slug(p.name)}\">\n <h2><a href=\"#${slug(p.name)}\">\u00A7</a> ${escapeHtml(p.name)}</h2>\n <div class=\"diagram\" data-rule=\"${escapeHtml(p.name)}\"></div>\n ${ebnf}\n </section>`\n })\n .join('\\n')\n\n // One DSL expression per rule, built into its container at load time.\n const builders = model.productions\n .map(p => ` { name: ${j(p.name)}, dsl: function(){ return Diagram(${toDsl(p.expr)}); } }`)\n .join(',\\n')\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(title)}</title>\n<style>\n${RAILROAD_CSS}\n${PAGE_CSS}\n</style>\n</head>\n<body>\n<h1>${escapeHtml(title)}</h1>\n<p class=\"subtitle\">Syntax diagrams generated from the parser grammar.</p>\n<nav class=\"toc\">\n ${toc}\n</nav>\n${sections}\n<script>\n${RAILROAD_JS}\n</script>\n<script>\n(function () {\n var rules = [\n${builders}\n ];\n rules.forEach(function (r) {\n var host = document.querySelector('.diagram[data-rule=' + CSS.escape(r.name) + ']');\n if (!host) return;\n try { r.dsl().addTo(host); }\n catch (e) { host.textContent = 'diagram error: ' + e.message; }\n });\n})();\n</script>\n</body>\n</html>\n`\n}\n"],
5
- "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
6
- "names": []
4
+ "sourcesContent": ["/**\n * `parseman/spec` \u2014 generate a formal grammar specification directly from a\n * Pars\u00E9man `rules()` grammar.\n *\n * Because the emitter walks the SAME `_def` combinator tree the interpreter and\n * macro compiler consume, a generated spec is a single source of truth: it\n * cannot disagree with what actually parses.\n *\n * import { toEBNF, toRailroadHtml } from 'parseman/spec'\n *\n * const grammar = rules(g => ({ ... })) // your grammar\n * const ebnf = toEBNF(grammar) // EBNF text\n * const html = toRailroadHtml(grammar) // self-contained syntax diagrams\n *\n * Scope: syntax only, not semantics. See docs/proposals/grammar-spec-generation.md.\n */\nimport { buildSpecModel } from './model.ts'\nimport type { GrammarInput, SpecModel, SpecOptions } from './model.ts'\nimport { renderEBNF } from './ebnf.ts'\nimport { renderRailroadHtml, renderRailroadSvg } from './railroad.ts'\nimport type { RailroadHtmlOptions } from './railroad.ts'\n\nexport { buildSpecModel } from './model.ts'\nexport type { GrammarInput, SpecModel, SpecOptions, SpecNode, Production } from './model.ts'\nexport { renderEBNF, renderExpr } from './ebnf.ts'\nexport { renderRailroadHtml, renderRailroadSvg } from './railroad.ts'\nexport type { RailroadHtmlOptions, RailroadSvg } from './railroad.ts'\nexport { RAILROAD_CSS } from './railroad-lib.ts'\n\n/** Generate W3C-style EBNF text (one production per named rule). */\nexport function toEBNF(grammar: GrammarInput, options?: SpecOptions): string {\n return renderEBNF(buildSpecModel(grammar, options))\n}\n\n/**\n * Generate a self-contained HTML page of SVG railroad (syntax) diagrams \u2014 one\n * per production \u2014 with an EBNF caption under each. No external dependencies.\n */\nexport function toRailroadHtml(\n grammar: GrammarInput,\n options?: SpecOptions & RailroadHtmlOptions,\n): string {\n const model: SpecModel = buildSpecModel(grammar, options)\n return renderRailroadHtml(model, options)\n}\n\n/**\n * Render each production to a static, self-contained SVG string \u2014 one per named\n * rule \u2014 ready to inline in a docs page, README, or any HTML (no client script).\n * Style with the exported `RAILROAD_CSS`, scoped to whatever wraps the SVGs.\n */\nexport function toRailroadSvg(grammar: GrammarInput, options?: SpecOptions): ReturnType<typeof renderRailroadSvg> {\n return renderRailroadSvg(buildSpecModel(grammar, options))\n}\n", "import type { Combinator } from '../types.ts'\nimport { ref } from './ref.ts'\nimport { markUnusedValues } from '../compiler/value-usage.ts'\n\n/**\n * Non-enumerable key on a `rules()` result holding the factory's declaration\n * order (the returned object's key order), which differs from the result's own\n * reference-creation key order. Read by `parseman/spec` for source-order output.\n */\nexport const RULE_ORDER = '__parsemanRuleOrder'\n\nfunction tagRule(r: Combinator<unknown>, key: string): void {\n ;(r as unknown as { _ruleName?: string })._ruleName = key\n if (r._def.tag === 'node' && r._def.type === undefined) r._def.type = key\n}\n\n/**\n * Define named grammar rules without forward declarations.\n *\n * Pass a factory that receives all rule names as references (via a Proxy)\n * and returns a record of combinators. rules() handles creating ref()\n * placeholders and wiring them up \u2014 the user never sees ref() at all.\n *\n * const { value } = rules(g => ({\n * value: choice(g.object, g.array, str, num, bool, nil),\n * object: transform(sequence('{', sepBy(g.pair, ','), '}'), Object.fromEntries),\n * array: transform(sequence('[', sepBy(g.value, ','), ']'), ([, items]) => items),\n * pair: transform(sequence(g.key, literal(':'), g.value), ([k,, v]) => [k, v]),\n * }))\n *\n * Not every name in the factory must appear in the returned object \u2014 local helpers\n * (like `comma`, `key`) can be plain const inside the factory and composed normally.\n * Only names that OTHER rules reference via `g.xxx` need to be in the returned record.\n *\n * TypeScript: use an explicit type parameter for full type safety on `g`:\n * rules<{ value: Combinator<JSONValue>; array: Combinator<JSONValue[]> }>(g => ({ ... }))\n * Without it, `g.*` accesses are typed as `any` but the return is still inferred.\n */\n/**\n * Grammar-level options for `rules()`. Parity with `parser({...})`, but declared\n * ONCE for the whole grammar instead of wrapped around a scope. `trivia` becomes\n * the ambient trivia for every rule (installed at the parse entry, inherited\n * everywhere, incremental parse included); `parser({trivia})` / `noTrivia` still\n * override it locally for a sub-region.\n */\nexport type RulesOptions = {\n /** Ambient trivia for the whole grammar. See `parser({ trivia })` for the shape\n * (`null` clears it \u2014 equivalent to omitting it at the grammar level). */\n trivia?: Combinator<unknown> | null\n}\n\n// Options-first, mirroring `parser({ opts }, combinator)` \u2014 set once on the grammar\n// vs scope it locally, same options in the same position. The bare `rules(factory)`\n// form is unchanged. The impl also tolerates the legacy `rules(factory, opts)` order.\nexport function rules<T extends Record<string, Combinator<unknown>>>(factory: (self: any) => T): T\nexport function rules<T extends Record<string, Combinator<unknown>>>(options: RulesOptions, factory: (self: any) => T): T\nexport function rules<T extends Record<string, Combinator<unknown>>>(\n a: ((self: any) => T) | RulesOptions,\n b?: (self: any) => T,\n): T {\n const factory = (typeof a === 'function' ? a : b) as (self: any) => T\n const options = (typeof a === 'function' ? b : a) as RulesOptions | undefined\n const cache: Partial<T> = {}\n\n // Proxy: accessing any property creates a ref() placeholder on first touch.\n const proxy = new Proxy(cache, {\n get(target, key) {\n if (typeof key !== 'string') return undefined\n const record = target as Record<string, Combinator<unknown>>\n if (!(key in record)) {\n const r = ref()\n // Tag the placeholder with its rule name so the linkable compiler can\n // emit a by-name `_r_<key>` call for a reference to a rule defined in\n // ANOTHER artifact (resolved at fuse time) \u2014 see compileLinkable.\n tagRule(r, key)\n record[key] = r\n }\n return record[key]\n },\n })\n\n // Evaluate all rule definitions. JavaScript evaluates object-literal values\n // left-to-right, so any `g.ruleName` access inside triggers placeholder creation\n // before the rule's own parser is built \u2014 enabling forward references.\n const definitions = factory(proxy)\n\n // Fill each ref with its actual definition, or store directly if never accessed via proxy.\n for (const key of Object.keys(definitions)) {\n const placeholder = (cache as Record<string, Combinator<unknown>>)[key]\n const parser = (definitions as Record<string, Combinator<unknown>>)[key]!\n if (placeholder !== undefined && typeof (placeholder as any).define === 'function') {\n tagRule(parser, key)\n ;(placeholder as any).define(parser)\n // Propagate actual first-set so later choices wrapping this ref get correct dispatch.\n placeholder._meta.firstSet = parser._meta.firstSet\n placeholder._meta.canMatchNewline = parser._meta.canMatchNewline\n } else {\n tagRule(parser, key)\n ;(cache as Record<string, Combinator<unknown>>)[key] = parser\n }\n }\n\n // Declare the grammar-level ambient trivia on every rule, so parsing ANY rule\n // as an entry installs it (run()/parse() read this), and the macro can seed the\n // compiled map. `parser({trivia})` / `noTrivia` still override it locally.\n // `!= null`: a `trivia: null` grammar clears trivia \u2014 same as omitting it at the\n // grammar level \u2014 so store nothing (and never write null, which has no `_meta`).\n if (options?.trivia != null) {\n for (const key of Object.keys(definitions)) {\n const rule = (cache as Record<string, Combinator<unknown>>)[key]\n // Skip trivia rules (e.g. the grammar's `rw`, returned so the driver can\n // reach it as `g.rw`): a trivia rule must never carry ambient trivia, or it\n // would recursively skip trivia within itself. Mirrors the codegen guard.\n if (rule && !rule._meta.isTrivia) (rule._meta as { grammarTrivia?: Combinator<unknown> }).grammarTrivia = options.trivia\n }\n }\n\n // Dead-value analysis: mark container aggregates that only feed a node()'s\n // capture so the interpreter (and, via the same flag, the compiled output) skips\n // building them. Each rule is its own root \u2014 refs are boundaries (see value-usage).\n for (const key of Object.keys(definitions)) {\n markUnusedValues((cache as Record<string, Combinator<unknown>>)[key]!)\n }\n\n // Record the factory's DECLARATION order (the returned object's key order).\n // `cache`'s own key order is reference-creation order \u2014 a Proxy artifact \u2014 so\n // it can lead with an internal rule instead of the entry rule. Consumers that\n // want the order the author actually wrote (e.g. `parseman/spec`) read this.\n // Non-enumerable, so Object.keys / spread / for-in over the grammar are\n // unaffected and every existing consumer sees exactly the rules it did before.\n Object.defineProperty(cache, RULE_ORDER, {\n value: Object.keys(definitions),\n enumerable: false,\n configurable: true,\n })\n\n return cache as T\n}\n", "/**\n * Grammar spec model \u2014 a small, notation-agnostic tree that both the EBNF\n * emitter and the railroad-diagram emitter consume.\n *\n * The model is produced by walking the SAME `_def` structure the interpreter\n * and macro compiler consume, so a generated spec cannot drift from what\n * actually parses. See `docs/proposals/grammar-spec-generation.md`.\n */\nimport type { Combinator, ParserDef } from '../types.ts'\nimport { RULE_ORDER } from '../combinators/parser.ts'\n\n// ---------------------------------------------------------------------------\n// Spec node tree\n// ---------------------------------------------------------------------------\n\n/** A node in the grammar spec tree \u2014 one per syntactic construct. */\nexport type SpecNode =\n | { kind: 'seq'; items: SpecNode[] }\n | { kind: 'choice'; items: SpecNode[] }\n | { kind: 'star'; item: SpecNode }\n | { kind: 'plus'; item: SpecNode }\n | { kind: 'opt'; item: SpecNode }\n /** Separated repetition (`sepBy`): `item (sep item)*` (min 0) or `item (sep item)+` \u2014 always \u22651 here. */\n | { kind: 'sepBy'; item: SpecNode; sep: SpecNode }\n /** Reference to a named production (non-terminal). */\n | { kind: 'ref'; name: string }\n /**\n * A terminal. `literal` terminals are exact strings (rendered quoted);\n * non-literal terminals are patterns/prose (rendered as-is, e.g. a regex\n * or a caller-supplied display name).\n */\n | { kind: 'terminal'; text: string; literal: boolean }\n /** Negative lookahead (`not`). Rendered as an annotation, not consumed input. */\n | { kind: 'not'; item: SpecNode }\n /** An out-of-band annotation (guards, error-recovery, unknowns). */\n | { kind: 'annotation'; text: string }\n /** Matches nothing (elided trivia / semantic-only wrappers). */\n | { kind: 'empty' }\n\n/** One named production: `name ::= expr`. */\nexport type Production = {\n name: string\n expr: SpecNode\n /** True when the rule is trivia (whitespace/comment). Elided by default. */\n trivia: boolean\n}\n\nexport type SpecModel = {\n productions: Production[]\n}\n\nexport type SpecOptions = {\n /**\n * How to order the emitted productions when neither `order` nor `root` is given:\n * - `'source'` (default) \u2014 the order the rules were **declared** in the\n * `rules()` factory. Predictable, includes every rule, and leads with the\n * entry rule (authors write it first). Internal-but-referenced helper rules\n * follow, in first-reference order.\n * - `'reachable'` \u2014 BFS from the entry rule: the first-declared rule leads,\n * then each rule appears the first time it is referenced; any rules not\n * reachable from the entry are appended in declaration order.\n * Ignored when `order` or `root` is set.\n */\n sort?: 'source' | 'reachable'\n /**\n * Explicit rule order (and subset). When given, only these rules are emitted,\n * in this order, plus any rules they reach. Overrides `sort`.\n */\n order?: string[]\n /**\n * Start rule(s). When given, only these and the rules they reach are emitted\n * (a pruned, reachability-ordered spec). Overrides `sort`.\n */\n root?: string | string[]\n /** Include trivia rules (whitespace/comment) in the output. Default: false. */\n includeTrivia?: boolean\n /**\n * Display names for terminals, keyed by rule name. When a rule whose body is a\n * single terminal (regex/literal/keywords) has an entry here, that whole rule\n * renders as the given terminal name instead of expanding \u2014 e.g.\n * `{ Ident: 'identifier' }`.\n */\n terminals?: Record<string, string>\n /**\n * Best-effort rendering of a regex terminal to a readable form. Return\n * `undefined` to fall back to the default `/source/` rendering.\n */\n regexDisplay?: (source: string, flags: string) => string | undefined\n}\n\nexport type GrammarInput =\n | Record<string, Combinator<unknown>>\n | Combinator<unknown>\n\n// ---------------------------------------------------------------------------\n// Walk\n// ---------------------------------------------------------------------------\n\ntype Tagged = Combinator<unknown> & { _ruleName?: string }\n\nfunction ruleNameOf(c: Combinator<unknown>): string | undefined {\n return (c as Tagged)._ruleName\n}\n\n/** Resolve a `lazy`/`ref` combinator one hop to its defined body, if resolvable. */\nfunction resolveLazy(c: Combinator<unknown>): Combinator<unknown> | undefined {\n const def = c._def\n if (def.tag !== 'lazy') return undefined\n try {\n return def.thunk() as Combinator<unknown>\n } catch {\n return undefined\n }\n}\n\nfunction defaultRegexDisplay(source: string): string {\n return `/${source}/`\n}\n\nclass Builder {\n private seen = new Set<string>()\n private pending: Array<{ name: string; comb: Combinator<unknown> }> = []\n private pendingNames = new Set<string>()\n private record: Record<string, Combinator<unknown>>\n private opts: SpecOptions\n productions: Production[] = []\n\n constructor(record: Record<string, Combinator<unknown>>, opts: SpecOptions) {\n this.record = record\n this.opts = opts\n }\n\n enqueue(name: string, comb: Combinator<unknown>): void {\n if (this.seen.has(name)) return\n if (this.pendingNames.has(name)) return\n this.pendingNames.add(name)\n this.pending.push({ name, comb })\n }\n\n /**\n * Seed and drain in phases. Each phase seeds its names, then BFS-drains the\n * queue (following references) before the next phase seeds. This lets callers\n * express \"entry first, then its reachable closure, then any leftovers\" by\n * splitting the seed across phases; a single phase with every rule yields plain\n * declaration order (references, already queued, keep their declared slot).\n */\n run(phases: string[][]): SpecModel {\n for (const phase of phases) {\n for (const name of phase) {\n const comb = this.record[name]\n if (comb) this.enqueue(name, comb)\n }\n this.drain()\n }\n return { productions: this.productions }\n }\n\n private drain(): void {\n while (this.pending.length > 0) {\n const { name, comb } = this.pending.shift()!\n this.pendingNames.delete(name)\n if (this.seen.has(name)) continue\n this.seen.add(name)\n const expr = this.ruleBody(comb, name)\n this.productions.push({ name, expr, trivia: comb._meta.isTrivia === true })\n }\n }\n\n /** Walk a rule's top-level combinator, transparently unwrapping its own self-ref. */\n private ruleBody(comb: Combinator<unknown>, name: string): SpecNode {\n // A rule that IS a single terminal can be pinned to a caller display name.\n const pinned = this.opts.terminals?.[name]\n if (pinned !== undefined) return { kind: 'terminal', text: pinned, literal: false }\n\n let c = comb\n // Unwrap the rule's own placeholder ref(s) so we expand its body, not a\n // self-reference. Both the placeholder and the resolved body carry the same\n // `_ruleName`, so guard against cycles.\n const guard = new Set<Combinator<unknown>>()\n while (c._def.tag === 'lazy' && ruleNameOf(c) === name && !guard.has(c)) {\n guard.add(c)\n const next = resolveLazy(c)\n if (!next) break\n c = next\n }\n return this.walk(c, true)\n }\n\n /** Walk any combinator. `isRuleRoot` suppresses treating it as a self-reference. */\n private walk(c: Combinator<unknown>, isRuleRoot = false): SpecNode {\n // A reference to a named rule \u2192 non-terminal (unless this IS that rule's root).\n const rn = ruleNameOf(c)\n if (rn !== undefined && !isRuleRoot) {\n // Register the target so it gets its own production, even if it wasn't in\n // the returned record (internal-but-referenced helper rules).\n if (!this.record[rn]) this.record[rn] = c\n this.enqueue(rn, c)\n return { kind: 'ref', name: rn }\n }\n return this.walkDef(c._def, c)\n }\n\n private walkDef(def: ParserDef, self: Combinator<unknown>): SpecNode {\n switch (def.tag) {\n case 'literal':\n return { kind: 'terminal', text: def.value, literal: true }\n\n case 'regex': {\n const shown =\n this.opts.regexDisplay?.(def.source, def.flags) ??\n defaultRegexDisplay(def.source)\n return { kind: 'terminal', text: shown, literal: false }\n }\n\n case 'keywords':\n return {\n kind: 'choice',\n items: def.words.map(w => ({ kind: 'terminal', text: w, literal: true }) as SpecNode),\n }\n\n case 'sequence': {\n const items = def.parsers.map(p => this.walk(p)).filter(nonEmpty)\n return flattenSeq(items)\n }\n\n case 'choice': {\n const items = def.parsers.map(p => this.walk(p)).filter(nonEmpty)\n return flattenChoice(items)\n }\n\n case 'many':\n return { kind: 'star', item: this.walk(def.parser) }\n case 'oneOrMore':\n return { kind: 'plus', item: this.walk(def.parser) }\n case 'optional':\n return { kind: 'opt', item: this.walk(def.parser) }\n case 'sepBy':\n return { kind: 'sepBy', item: this.walk(def.parser), sep: this.walk(def.separator) }\n\n case 'not':\n return { kind: 'not', item: this.walk(def.parser) }\n\n // Transparent semantic wrappers \u2014 render the inner syntax.\n case 'transform':\n case 'token':\n case 'label':\n case 'field':\n case 'expect':\n case 'withCtx':\n case 'node':\n return this.walk((def as { parser: Combinator<unknown> }).parser)\n\n case 'skip':\n return this.walk(def.main)\n case 'grammar':\n return this.walk(def.parser)\n\n // Error recovery \u2014 render the intended sub-parser, drop the sentinel.\n case 'recover':\n return this.walk(def.parser)\n case 'scanTo':\n return { kind: 'annotation', text: '\u2026' }\n\n // Trivia \u2014 elided by default; included as an annotation when asked.\n case 'trivia':\n return this.opts.includeTrivia ? this.walk(def.parser) : { kind: 'empty' }\n\n case 'guard':\n return { kind: 'empty' }\n\n case 'lazy': {\n const inner = resolveLazy(self)\n return inner ? this.walk(inner) : { kind: 'annotation', text: '?' }\n }\n\n case 'unknown':\n default:\n return { kind: 'annotation', text: '?' }\n }\n }\n}\n\nfunction nonEmpty(n: SpecNode): boolean {\n return n.kind !== 'empty'\n}\n\nfunction flattenSeq(items: SpecNode[]): SpecNode {\n const flat: SpecNode[] = []\n for (const it of items) {\n if (it.kind === 'seq') flat.push(...it.items)\n else flat.push(it)\n }\n if (flat.length === 0) return { kind: 'empty' }\n if (flat.length === 1) return flat[0]!\n return { kind: 'seq', items: flat }\n}\n\nfunction flattenChoice(items: SpecNode[]): SpecNode {\n const flat: SpecNode[] = []\n for (const it of items) {\n if (it.kind === 'choice') flat.push(...it.items)\n else flat.push(it)\n }\n if (flat.length === 0) return { kind: 'empty' }\n if (flat.length === 1) return flat[0]!\n return { kind: 'choice', items: flat }\n}\n\nfunction toRecord(grammar: GrammarInput): Record<string, Combinator<unknown>> {\n // A single combinator \u2192 a one-rule grammar keyed by its rule name or \"start\".\n if (isCombinator(grammar)) {\n const name = ruleNameOf(grammar) ?? 'start'\n return { [name]: grammar }\n }\n return grammar\n}\n\nfunction isCombinator(x: unknown): x is Combinator<unknown> {\n return (\n typeof x === 'object' &&\n x !== null &&\n typeof (x as { parse?: unknown }).parse === 'function' &&\n '_def' in (x as object)\n )\n}\n\n/** Declaration order recorded by `rules()`; falls back to the record's key order. */\nfunction declarationOrder(record: Record<string, Combinator<unknown>>): string[] {\n const declared = (record as Record<string, unknown>)[RULE_ORDER]\n if (Array.isArray(declared)) return declared.filter(k => k in record)\n return Object.keys(record)\n}\n\n/**\n * Build the notation-agnostic spec model from a `rules()` grammar (or a single\n * combinator). Following every referenced named rule keeps the closure complete;\n * ordering is controlled by `order` / `root` / `sort` (see {@link SpecOptions}).\n */\nexport function buildSpecModel(grammar: GrammarInput, options: SpecOptions = {}): SpecModel {\n const record = toRecord(grammar)\n const decl = declarationOrder(record)\n\n // Validate rule names in `order` / `root` up front. Left unchecked, an unknown\n // name (or a stray string like `order: 'source'` where a `string[]` is meant)\n // seeds a phase that reaches nothing and silently yields an EMPTY model \u2014 a\n // confusing footgun. Fail loudly with the offending names and the known rules.\n const known = new Set(decl)\n const asList = (v: string | string[]): string[] => (Array.isArray(v) ? v : [v])\n const requireKnown = (names: string[], opt: string): void => {\n const bad = names.filter(n => !known.has(n))\n if (bad.length > 0) {\n throw new Error(\n `buildSpecModel: unknown rule name(s) in \\`${opt}\\`: ${bad.map(n => JSON.stringify(n)).join(', ')}. ` +\n `Known rules: ${decl.map(n => JSON.stringify(n)).join(', ')}.`,\n )\n }\n }\n\n // Seed phases (see Builder.run). Priority: explicit `order` > `root` (pruned) >\n // `sort`. Default `sort` = 'source' (declaration order, every rule).\n let phases: string[][]\n if (options.order !== undefined) {\n const order = asList(options.order as string | string[])\n requireKnown(order, 'order')\n phases = [order]\n } else if (options.root !== undefined) {\n const root = asList(options.root)\n requireKnown(root, 'root')\n phases = [root]\n } else if (options.sort === 'reachable') {\n // Entry (first-declared) leads; BFS discovers the rest in first-reference\n // order; unreachable rules trail in declaration order.\n phases = decl.length > 0 ? [[decl[0]!], decl.slice(1)] : [decl]\n } else {\n phases = [decl]\n }\n\n const model = new Builder({ ...record }, options).run(phases)\n if (!options.includeTrivia) {\n model.productions = model.productions.filter(p => !p.trivia)\n }\n return model\n}\n", "/**\n * EBNF (W3C-style) text emitter for the grammar spec model.\n *\n * Precedence, lowest \u2192 highest: alternation (`|`) < concatenation (space) <\n * postfix (`* + ?`) < atom. The renderer parenthesizes only where a lower-\n * precedence construct sits inside a higher-precedence one.\n */\nimport type { Production, SpecModel, SpecNode } from './model.ts'\n\nconst ALT = 1 // choice\nconst CAT = 2 // sequence\nconst ATOM = 3 // terminal, ref, postfix, parenthesized\n\nfunction quote(s: string): string {\n // W3C EBNF uses quoted string terminals; prefer double quotes, fall back to\n // single quotes when the literal itself contains a double quote.\n if (s.includes('\"') && !s.includes(\"'\")) return `'${s}'`\n return `\"${s.replace(/\"/g, '\\\\\"')}\"`\n}\n\nfunction wrap(inner: string, innerLevel: number, minLevel: number): string {\n return innerLevel < minLevel ? `(${inner})` : inner\n}\n\n/** Render a node, returning its text and precedence level. */\nfunction render(node: SpecNode): { text: string; level: number } {\n switch (node.kind) {\n case 'terminal':\n return { text: node.literal ? quote(node.text) : node.text, level: ATOM }\n case 'ref':\n return { text: node.name, level: ATOM }\n case 'empty':\n return { text: '', level: ATOM }\n case 'annotation':\n return { text: `/* ${node.text} */`, level: ATOM }\n\n case 'seq': {\n const text = node.items\n .map(it => {\n const r = render(it)\n return wrap(r.text, r.level, CAT)\n })\n .filter(t => t.length > 0)\n .join(' ')\n return { text, level: CAT }\n }\n\n case 'choice': {\n const text = node.items\n .map(it => {\n const r = render(it)\n return wrap(r.text, r.level, ALT)\n })\n .join(' | ')\n return { text, level: ALT }\n }\n\n case 'star':\n case 'plus':\n case 'opt': {\n const r = render(node.item)\n const op = node.kind === 'star' ? '*' : node.kind === 'plus' ? '+' : '?'\n return { text: `${wrap(r.text, r.level, ATOM)}${op}`, level: ATOM }\n }\n\n case 'sepBy': {\n const item = render(node.item)\n const sep = render(node.sep)\n const itemA = wrap(item.text, item.level, ATOM)\n const sepA = wrap(sep.text, sep.level, CAT)\n // item (sep item)*\n return { text: `${itemA} (${sepA} ${itemA})*`, level: CAT }\n }\n\n case 'not': {\n const r = render(node.item)\n return { text: `!${wrap(r.text, r.level, ATOM)}`, level: ATOM }\n }\n }\n}\n\nfunction renderProduction(p: Production): string {\n const { text } = render(p.expr)\n return `${p.name} ::= ${text || '/* empty */'}`\n}\n\n/** Render the whole spec model as EBNF text (one production per line). */\nexport function renderEBNF(model: SpecModel): string {\n return model.productions.map(renderProduction).join('\\n') + '\\n'\n}\n\n/** Render a single production's right-hand side (no `name ::=`). */\nexport function renderExpr(node: SpecNode): string {\n return render(node).text\n}\n", "/**\n * Vendored copy of tabatkins railroad-diagrams (v1.0.0), license CC0-1.0.\n * https://github.com/tabatkins/railroad-diagrams\n *\n * Public domain (CC0) \u2014 embedded verbatim as strings so the generated\n * railroad-diagram HTML page is fully self-contained (no CDN, no runtime dep).\n * Do not edit by hand; regenerate from the npm package if bumping versions.\n */\n/* eslint-disable */\nexport const RAILROAD_JS: string = `/*\nRailroad Diagrams\nby Tab Atkins Jr. (and others)\nhttp://xanthir.com\nhttp://twitter.com/tabatkins\nhttp://github.com/tabatkins/railroad-diagrams\n\nThis document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/\nThis means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION.\n(The actual legal meaning can be found at the above link.)\nDon't ask me for permission to use any part of this project, JUST USE IT.\nI would appreciate attribution, but that is not required by the license.\n*/\n\n/*\nThis file uses a module pattern to avoid leaking names into the global scope.\nThe only accidental leakage is the name \"temp\".\nThe exported names can be found at the bottom of this file;\nsimply change the names in the array of strings to change what they are called in your application.\n\nAs well, several configuration constants are passed into the module function at the bottom of this file.\nAt runtime, these constants can be found on the Diagram class.\n*/\n\n(function(options) {\n\tfunction subclassOf(baseClass, superClass) {\n\t\tbaseClass.prototype = Object.create(superClass.prototype);\n\t\tbaseClass.prototype.$super = superClass.prototype;\n\t}\n\n\tfunction unnull(/* children */) {\n\t\treturn [].slice.call(arguments).reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; });\n\t}\n\n\tfunction determineGaps(outer, inner) {\n\t\tvar diff = outer - inner;\n\t\tswitch(Diagram.INTERNAL_ALIGNMENT) {\n\t\t\tcase 'left': return [0, diff]; break;\n\t\t\tcase 'right': return [diff, 0]; break;\n\t\t\tcase 'center':\n\t\t\tdefault: return [diff/2, diff/2]; break;\n\t\t}\n\t}\n\n\tfunction wrapString(value) {\n\t\treturn ((typeof value) == 'string') ? new Terminal(value) : value;\n\t}\n\n\n\tfunction SVG(name, attrs, text) {\n\t\tattrs = attrs || {};\n\t\ttext = text || '';\n\t\tvar el = document.createElementNS(\"http://www.w3.org/2000/svg\",name);\n\t\tfor(var attr in attrs) {\n\t\t\tel.setAttribute(attr, attrs[attr]);\n\t\t}\n\t\tel.textContent = text;\n\t\treturn el;\n\t}\n\n\tfunction FakeSVG(tagName, attrs, text){\n\t\tif(!(this instanceof FakeSVG)) return new FakeSVG(tagName, attrs, text);\n\t\tif(text) this.children = text;\n\t\telse this.children = [];\n\t\tthis.tagName = tagName;\n\t\tthis.attrs = unnull(attrs, {});\n\t\treturn this;\n\t};\n\tFakeSVG.prototype.format = function(x, y, width) {\n\t\t// Virtual\n\t};\n\tFakeSVG.prototype.addTo = function(parent) {\n\t\tif(parent instanceof FakeSVG) {\n\t\t\tparent.children.push(this);\n\t\t\treturn this;\n\t\t} else {\n\t\t\tvar svg = this.toSVG();\n\t\t\tparent.appendChild(svg);\n\t\t\treturn svg;\n\t\t}\n\t};\n\tFakeSVG.prototype.escapeString = function(string) {\n // Escape markdown and HTML special characters\n\t\treturn string.replace(/[*_\\\\\\`\\\\[\\\\]<&]/g, function(charString) {\n\t\t\treturn '&#' + charString.charCodeAt(0) + ';';\n\t\t});\n\t};\n\tFakeSVG.prototype.toSVG = function() {\n\t\tvar el = SVG(this.tagName, this.attrs);\n\t\tif(typeof this.children == 'string') {\n\t\t\tel.innerHTML = FakeSVG.prototype.escapeString(this.children);\n\t\t} else {\n\t\t\tthis.children.forEach(function(e) {\n\t\t\t\tel.appendChild(e.toSVG());\n\t\t\t});\n\t\t}\n\t\treturn el;\n\t};\n\tFakeSVG.prototype.toString = function() {\n\t\tvar str = '<' + this.tagName;\n\t\tvar group = this.tagName == \"g\" || this.tagName == \"svg\";\n\t\tfor(var attr in this.attrs) {\n\t\t\tstr += ' ' + attr + '=\"' + (this.attrs[attr]+'').replace(/&/g, '&amp;').replace(/\"/g, '&quot;') + '\"';\n\t\t}\n\t\tstr += '>';\n\t\tif(group) str += \"\\\\n\";\n\t\tif(typeof this.children == 'string') {\n\t\t\tstr += FakeSVG.prototype.escapeString(this.children);\n\t\t} else {\n\t\t\tthis.children.forEach(function(e) {\n\t\t\t\tstr += e;\n\t\t\t});\n\t\t}\n\t\tstr += '</' + this.tagName + '>\\\\n';\n\t\treturn str;\n\t}\n\n\tfunction Path(x,y) {\n\t\tif(!(this instanceof Path)) return new Path(x,y);\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.attrs.d = \"M\"+x+' '+y;\n\t}\n\tsubclassOf(Path, FakeSVG);\n\tPath.prototype.m = function(x,y) {\n\t\tthis.attrs.d += 'm'+x+' '+y;\n\t\treturn this;\n\t}\n\tPath.prototype.h = function(val) {\n\t\tthis.attrs.d += 'h'+val;\n\t\treturn this;\n\t}\n\tPath.prototype.right = Path.prototype.h;\n\tPath.prototype.left = function(val) { return this.h(-val); }\n\tPath.prototype.v = function(val) {\n\t\tthis.attrs.d += 'v'+val;\n\t\treturn this;\n\t}\n\tPath.prototype.down = Path.prototype.v;\n\tPath.prototype.up = function(val) { return this.v(-val); }\n\tPath.prototype.arc = function(sweep){\n\t\tvar x = Diagram.ARC_RADIUS;\n\t\tvar y = Diagram.ARC_RADIUS;\n\t\tif(sweep[0] == 'e' || sweep[1] == 'w') {\n\t\t\tx *= -1;\n\t\t}\n\t\tif(sweep[0] == 's' || sweep[1] == 'n') {\n\t\t\ty *= -1;\n\t\t}\n\t\tif(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') {\n\t\t\tvar cw = 1;\n\t\t} else {\n\t\t\tvar cw = 0;\n\t\t}\n\t\tthis.attrs.d += \"a\"+Diagram.ARC_RADIUS+\" \"+Diagram.ARC_RADIUS+\" 0 0 \"+cw+' '+x+' '+y;\n\t\treturn this;\n\t}\n\tPath.prototype.format = function() {\n\t\t// All paths in this library start/end horizontally.\n\t\t// The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers.\n\t\tthis.attrs.d += 'h.5';\n\t\treturn this;\n\t}\n\n\tfunction Diagram(items) {\n\t\tif(!(this instanceof Diagram)) return new Diagram([].slice.call(arguments));\n\t\tFakeSVG.call(this, 'svg', {class: Diagram.DIAGRAM_CLASS});\n\t\tthis.items = items.map(wrapString);\n\t\tthis.items.unshift(new Start);\n\t\tthis.items.push(new End);\n\t\tthis.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0)+1;\n\t\tthis.up = Math.max.apply(null, this.items.map(function (x) { return x.up; }));\n\t\tthis.down = Math.max.apply(null, this.items.map(function (x) { return x.down; }));\n\t\tthis.formatted = false;\n\t}\n\tsubclassOf(Diagram, FakeSVG);\n\tfor(var option in options) {\n\t\tDiagram[option] = options[option];\n\t}\n\tDiagram.prototype.format = function(paddingt, paddingr, paddingb, paddingl) {\n\t\tpaddingt = unnull(paddingt, 20);\n\t\tpaddingr = unnull(paddingr, paddingt, 20);\n\t\tpaddingb = unnull(paddingb, paddingt, 20);\n\t\tpaddingl = unnull(paddingl, paddingr, 20);\n\t\tvar x = paddingl;\n\t\tvar y = paddingt;\n\t\ty += this.up;\n\t\tvar g = FakeSVG('g', Diagram.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {});\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(g);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t\titem.format(x, y, item.width).addTo(g);\n\t\t\tx += item.width;\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(g);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t}\n\t\tthis.attrs.width = this.width + paddingl + paddingr;\n\t\tthis.attrs.height = this.up + this.down + paddingt + paddingb;\n\t\tthis.attrs.viewBox = \"0 0 \" + this.attrs.width + \" \" + this.attrs.height;\n\t\tg.addTo(this);\n\t\tthis.formatted = true;\n\t\treturn this;\n\t}\n\tDiagram.prototype.addTo = function(parent) {\n\t\tvar scriptTag = document.getElementsByTagName('script');\n\t\tscriptTag = scriptTag[scriptTag.length - 1];\n\t\tvar parentTag = scriptTag.parentNode;\n\t\tparent = parent || parentTag;\n\t\treturn this.$super.addTo.call(this, parent);\n\t}\n\tDiagram.prototype.toSVG = function() {\n\t\tif (!this.formatted) {\n\t\t\tthis.format();\n\t\t}\n\t\treturn this.$super.toSVG.call(this);\n\t}\n\tDiagram.prototype.toString = function() {\n\t\tif (!this.formatted) {\n\t\t\tthis.format();\n\t\t}\n\t\treturn this.$super.toString.call(this);\n\t}\n\n\tfunction ComplexDiagram() {\n\t\tvar diagram = new Diagram([].slice.call(arguments));\n var items = diagram.items;\n\t\titems.shift();\n\t\titems.pop();\n\t\titems.unshift(new Start(false));\n\t\titems.push(new End(false));\n\t\tdiagram.items = items;\n\t\treturn diagram;\n }\n\n\tfunction Sequence(items) {\n\t\tif(!(this instanceof Sequence)) return new Sequence([].slice.call(arguments));\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.items = items.map(wrapString);\n\t\tthis.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0);\n\t\tthis.up = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.up)}, 0);\n\t\tthis.down = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.down)}, 0);\n\t}\n\tsubclassOf(Sequence, FakeSVG);\n\tSequence.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(this);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t\titem.format(x, y, item.width).addTo(this);\n\t\t\tx += item.width;\n\t\t\tif(item.needsSpace) {\n\t\t\t\tPath(x,y).h(10).addTo(this);\n\t\t\t\tx += 10;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction Choice(normal, items) {\n\t\tif(!(this instanceof Choice)) return new Choice(normal, [].slice.call(arguments,1));\n\t\tFakeSVG.call(this, 'g');\n\t\tif( typeof normal !== \"number\" || normal !== Math.floor(normal) ) {\n\t\t\tthrow new TypeError(\"The first argument of Choice() must be an integer.\");\n\t\t} else if(normal < 0 || normal >= items.length) {\n\t\t\tthrow new RangeError(\"The first argument of Choice() must be an index for one of the items.\");\n\t\t} else {\n\t\t\tthis.normal = normal;\n\t\t}\n\t\tthis.items = items.map(wrapString);\n\t\tthis.width = this.items.reduce(function(sofar, el){return Math.max(sofar, el.width)},0) + Diagram.ARC_RADIUS*4;\n\t\tthis.up = this.down = 0;\n\t\tfor(var i = 0; i < this.items.length; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif(i < normal) { this.up += Math.max(Diagram.ARC_RADIUS,item.up + item.down + Diagram.VERTICAL_SEPARATION); }\n\t\t\tif(i == normal) { this.up += Math.max(Diagram.ARC_RADIUS, item.up); this.down += Math.max(Diagram.ARC_RADIUS, item.down); }\n\t\t\tif(i > normal) { this.down += Math.max(Diagram.ARC_RADIUS,Diagram.VERTICAL_SEPARATION + item.up + item.down); }\n\t\t}\n\t}\n\tsubclassOf(Choice, FakeSVG);\n\tChoice.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tvar last = this.items.length -1;\n\t\tvar innerWidth = this.width - Diagram.ARC_RADIUS*4;\n\n\t\t// Do the elements that curve above\n\t\tfor(var i = this.normal - 1; i >= 0; i--) {\n\t\t\tvar item = this.items[i];\n\t\t\tif( i == this.normal - 1 ) {\n\t\t\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i+1].up + Diagram.VERTICAL_SEPARATION + item.down);\n\t\t\t}\n\t\t\tPath(x,y).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);\n\t\t\titem.format(x+Diagram.ARC_RADIUS*2,y - distanceFromY,innerWidth).addTo(this);\n\t\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y-distanceFromY).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\t\tdistanceFromY += Math.max(Diagram.ARC_RADIUS, item.up + Diagram.VERTICAL_SEPARATION + (i == 0 ? 0 : this.items[i-1].down));\n\t\t}\n\n\t\t// Do the straight-line path.\n\t\tPath(x,y).right(Diagram.ARC_RADIUS*2).addTo(this);\n\t\tthis.items[this.normal].format(x+Diagram.ARC_RADIUS*2, y, innerWidth).addTo(this);\n\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y).right(Diagram.ARC_RADIUS*2).addTo(this);\n\n\t\t// Do the elements that curve below\n\t\tfor(var i = this.normal+1; i <= last; i++) {\n\t\t\tvar item = this.items[i];\n\t\t\tif( i == this.normal + 1 ) {\n\t\t\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i-1].down + Diagram.VERTICAL_SEPARATION + item.up);\n\t\t\t}\n\t\t\tPath(x,y).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\t\titem.format(x+Diagram.ARC_RADIUS*2, y+distanceFromY, innerWidth).addTo(this);\n\t\t\tPath(x+Diagram.ARC_RADIUS*2+innerWidth, y+distanceFromY).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);\n\t\t\tdistanceFromY += Math.max(Diagram.ARC_RADIUS, item.down + Diagram.VERTICAL_SEPARATION + (i == last ? 0 : this.items[i+1].up));\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tfunction Optional(item, skip) {\n\t\tif( skip === undefined )\n\t\t\treturn Choice(1, Skip(), item);\n\t\telse if ( skip === \"skip\" )\n\t\t\treturn Choice(0, Skip(), item);\n\t\telse\n\t\t\tthrow \"Unknown value for Optional()'s 'skip' argument.\";\n\t}\n\n\tfunction OneOrMore(item, rep) {\n\t\tif(!(this instanceof OneOrMore)) return new OneOrMore(item, rep);\n\t\tFakeSVG.call(this, 'g');\n\t\trep = rep || (new Skip);\n\t\tthis.item = wrapString(item);\n\t\tthis.rep = wrapString(rep);\n\t\tthis.width = Math.max(this.item.width, this.rep.width) + Diagram.ARC_RADIUS*2;\n\t\tthis.up = this.item.up;\n\t\tthis.down = Math.max(Diagram.ARC_RADIUS*2, this.item.down + Diagram.VERTICAL_SEPARATION + this.rep.up + this.rep.down);\n\t}\n\tsubclassOf(OneOrMore, FakeSVG);\n\tOneOrMore.prototype.needsSpace = true;\n\tOneOrMore.prototype.format = function(x,y,width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\t// Draw item\n\t\tPath(x,y).right(Diagram.ARC_RADIUS).addTo(this);\n\t\tthis.item.format(x+Diagram.ARC_RADIUS,y,this.width-Diagram.ARC_RADIUS*2).addTo(this);\n\t\tPath(x+this.width-Diagram.ARC_RADIUS,y).right(Diagram.ARC_RADIUS).addTo(this);\n\n\t\t// Draw repeat arc\n\t\tvar distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up);\n\t\tPath(x+Diagram.ARC_RADIUS,y).arc('nw').down(distanceFromY-Diagram.ARC_RADIUS*2).arc('ws').addTo(this);\n\t\tthis.rep.format(x+Diagram.ARC_RADIUS, y+distanceFromY, this.width - Diagram.ARC_RADIUS*2).addTo(this);\n\t\tPath(x+this.width-Diagram.ARC_RADIUS, y+distanceFromY).arc('se').up(distanceFromY-Diagram.ARC_RADIUS*2).arc('en').addTo(this);\n\n\t\treturn this;\n\t}\n\n\tfunction ZeroOrMore(item, rep, skip) {\n\t\treturn Optional(OneOrMore(item, rep), skip);\n\t}\n\n\tfunction Start(simpleType) {\n\t\tif(!(this instanceof Start)) return new Start();\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.width = 20;\n\t\tthis.up = 10;\n\t\tthis.down = 10;\n\t\tthis.simpleType = simpleType;\n\t}\n\tsubclassOf(Start, FakeSVG);\n\tStart.prototype.format = function(x,y) {\n\t\tif (this.simpleType === false) {\n\t\t\tthis.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 0 -10 h 20.5';\n\t\t} else {\n\t\t\tthis.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 10 -20 v 20 m -10 -10 h 20.5';\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction End(simpleType) {\n\t\tif(!(this instanceof End)) return new End();\n\t\tFakeSVG.call(this, 'path');\n\t\tthis.width = 20;\n\t\tthis.up = 10;\n\t\tthis.down = 10;\n\t\tthis.simpleType = simpleType;\n\t}\n\tsubclassOf(End, FakeSVG);\n\tEnd.prototype.format = function(x,y) {\n\t\tif (this.simpleType === false) {\n\t\t\tthis.attrs.d = 'M '+x+' '+y+' h 20 m 0 -10 v 20';\n\t\t} else {\n\t\t\tthis.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20';\n\t\t}\n\t\treturn this;\n\t}\n\n\tfunction Terminal(text) {\n\t\tif(!(this instanceof Terminal)) return new Terminal(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 8 + 20; /* Assume that each char is .5em, and that the em is 16px */\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(Terminal, FakeSVG);\n\tTerminal.prototype.needsSpace = true;\n\tTerminal.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this);\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction NonTerminal(text) {\n\t\tif(!(this instanceof NonTerminal)) return new NonTerminal(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 8 + 20;\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(NonTerminal, FakeSVG);\n\tNonTerminal.prototype.needsSpace = true;\n\tNonTerminal.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this);\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction Comment(text) {\n\t\tif(!(this instanceof Comment)) return new Comment(text);\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.text = text;\n\t\tthis.width = text.length * 7 + 10;\n\t\tthis.up = 11;\n\t\tthis.down = 11;\n\t}\n\tsubclassOf(Comment, FakeSVG);\n\tComment.prototype.needsSpace = true;\n\tComment.prototype.format = function(x, y, width) {\n\t\t// Hook up the two sides if this is narrower than its stated width.\n\t\tvar gaps = determineGaps(width, this.width);\n\t\tPath(x,y).h(gaps[0]).addTo(this);\n\t\tPath(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);\n\t\tx += gaps[0];\n\n\t\tFakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text).addTo(this);\n\t\treturn this;\n\t}\n\n\tfunction Skip() {\n\t\tif(!(this instanceof Skip)) return new Skip();\n\t\tFakeSVG.call(this, 'g');\n\t\tthis.width = 0;\n\t\tthis.up = 0;\n\t\tthis.down = 0;\n\t}\n\tsubclassOf(Skip, FakeSVG);\n\tSkip.prototype.format = function(x, y, width) {\n\t\tPath(x,y).right(width).addTo(this);\n\t\treturn this;\n\t}\n\t\n\tvar root;\n\tif (typeof define === 'function' && define.amd) {\n\t\t// AMD. Register as an anonymous module.\n\t\troot = {};\n\t\tdefine([], function() {\n\t\t\treturn root;\n\t\t});\n\t} else if (typeof exports === 'object') {\n\t\t// CommonJS for node\n\t\troot = exports;\n\t} else {\n\t\t// Browser globals (root is window)\n\t\troot = this;\n\t}\n\n\tvar temp = [Diagram, ComplexDiagram, Sequence, Choice, Optional, OneOrMore, ZeroOrMore, Terminal, NonTerminal, Comment, Skip];\n\t/*\n\tThese are the names that the internal classes are exported as.\n\tIf you would like different names, adjust them here.\n\t*/\n\t['Diagram', 'ComplexDiagram', 'Sequence', 'Choice', 'Optional', 'OneOrMore', 'ZeroOrMore', 'Terminal', 'NonTerminal', 'Comment', 'Skip']\n\t\t.forEach(function(e,i) { root[e] = temp[i]; });\n}).call(this,\n\t{\n\tVERTICAL_SEPARATION: 8,\n\tARC_RADIUS: 10,\n\tDIAGRAM_CLASS: 'railroad-diagram',\n\tSTROKE_ODD_PIXEL_LENGTH: true,\n\tINTERNAL_ALIGNMENT: 'center',\n\t}\n);\n`\n\nexport const RAILROAD_CSS: string = `svg.railroad-diagram {\n background-color: hsl(30,20%,95%);\n}\nsvg.railroad-diagram path {\n stroke-width: 3;\n stroke: black;\n fill: rgba(0,0,0,0);\n}\nsvg.railroad-diagram text {\n font: bold 14px monospace;\n text-anchor: middle;\n}\nsvg.railroad-diagram text.label {\n text-anchor: start;\n}\nsvg.railroad-diagram text.comment {\n font: italic 12px monospace;\n}\nsvg.railroad-diagram rect {\n stroke-width: 3;\n stroke: black;\n fill: hsl(120,100%,90%);\n}\n`\n", "/**\n * Railroad-diagram (syntax-diagram) emitter. Converts the spec model to a\n * self-contained HTML page that renders SVG railroad diagrams \u2014 one per\n * production \u2014 using a vendored copy of tabatkins/railroad-diagrams (CC0).\n *\n * The page has no external dependencies: the diagram library and its CSS are\n * inlined, so it renders offline and drops straight into a docs site.\n */\nimport type { Production, SpecModel, SpecNode } from './model.ts'\nimport { renderExpr } from './ebnf.ts'\nimport { RAILROAD_CSS, RAILROAD_JS } from './railroad-lib.ts'\n\nconst j = (s: string): string => JSON.stringify(s)\n\n/** Convert a spec node to a railroad-diagrams DSL expression string. */\nfunction toDsl(node: SpecNode): string {\n switch (node.kind) {\n case 'terminal':\n return `Terminal(${j(node.text)})`\n case 'ref':\n return `NonTerminal(${j(node.name)})`\n case 'empty':\n return `Skip()`\n case 'annotation':\n return `Comment(${j(node.text)})`\n case 'seq':\n return `Sequence(${node.items.map(toDsl).join(', ')})`\n case 'choice':\n return `Choice(0, ${node.items.map(toDsl).join(', ')})`\n case 'star':\n return `ZeroOrMore(${toDsl(node.item)})`\n case 'plus':\n return `OneOrMore(${toDsl(node.item)})`\n case 'opt':\n return `Optional(${toDsl(node.item)})`\n case 'sepBy':\n // OneOrMore(item, separator): the separator rides the repeat loop.\n return `OneOrMore(${toDsl(node.item)}, ${toDsl(node.sep)})`\n case 'not':\n return `Sequence(Comment(\"not\"), ${toDsl(node.item)})`\n }\n}\n\n// Vendored railroad-diagrams builders, evaluated once. `.toString()` on the\n// result walks an in-memory FakeSVG tree and emits SVG markup with no DOM \u2014 so a\n// diagram can be rendered to a static SVG string at build time (Node), not just\n// in the browser. The library exports onto `exports` when it's an object.\ntype RailroadBuilders = {\n Diagram: (item: unknown) => { toString(): string }\n Sequence: (...xs: unknown[]) => unknown\n Choice: (normal: number, ...xs: unknown[]) => unknown\n Optional: (x: unknown) => unknown\n OneOrMore: (x: unknown, sep?: unknown) => unknown\n ZeroOrMore: (x: unknown) => unknown\n Terminal: (t: string) => unknown\n NonTerminal: (t: string) => unknown\n Comment: (t: string) => unknown\n Skip: () => unknown\n}\nlet _builders: RailroadBuilders | null = null\nfunction builders(): RailroadBuilders {\n if (_builders) return _builders\n const mod = {} as Record<string, unknown>\n // eslint-disable-next-line no-new-func\n new Function('exports', RAILROAD_JS)(mod)\n _builders = mod as unknown as RailroadBuilders\n return _builders\n}\n\n/** Build a railroad-diagrams object from a spec node (mirrors `toDsl`, but live). */\nfunction toDiagramNode(b: RailroadBuilders, node: SpecNode): unknown {\n switch (node.kind) {\n case 'terminal': return b.Terminal(node.text)\n case 'ref': return b.NonTerminal(node.name)\n case 'empty': return b.Skip()\n case 'annotation': return b.Comment(node.text)\n case 'seq': return b.Sequence(...node.items.map((n) => toDiagramNode(b, n)))\n case 'choice': return b.Choice(0, ...node.items.map((n) => toDiagramNode(b, n)))\n case 'star': return b.ZeroOrMore(toDiagramNode(b, node.item))\n case 'plus': return b.OneOrMore(toDiagramNode(b, node.item))\n case 'opt': return b.Optional(toDiagramNode(b, node.item))\n case 'sepBy': return b.OneOrMore(toDiagramNode(b, node.item), toDiagramNode(b, node.sep))\n case 'not': return b.Sequence(b.Comment('not'), toDiagramNode(b, node.item))\n }\n}\n\n/** One production rendered to a static SVG string. */\nexport type RailroadSvg = { name: string; svg: string }\n\n/**\n * Render each production to a self-contained **static SVG** string \u2014 no DOM and\n * no client-side script, so a diagram can be inlined straight into a docs page,\n * README, or any HTML. Pair each SVG with [`RAILROAD_CSS`](./railroad-lib) (scope\n * it to a container) to style the strokes and boxes.\n */\nexport function renderRailroadSvg(model: SpecModel): RailroadSvg[] {\n const b = builders()\n return model.productions.map((p) => ({\n name: p.name,\n svg: b.Diagram(toDiagramNode(b, p.expr)).toString(),\n }))\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction slug(name: string): string {\n return 'rule-' + name.replace(/[^\\w-]/g, '_')\n}\n\nexport type RailroadHtmlOptions = {\n /** Page `<title>` and top heading. Default: \"Grammar\". */\n title?: string\n /** Show the EBNF production text under each diagram. Default: true. */\n showEbnf?: boolean\n}\n\nconst PAGE_CSS = `\n /* The railroad SVGs ship a fixed light background, so the page commits to a\n light theme for a consistent look regardless of the viewer's OS setting. */\n body { font: 14px/1.5 system-ui, sans-serif; margin: 0; padding: 2rem 2.5rem;\n color: #1a1a1a; background: #fff; }\n h1 { font-size: 1.6rem; margin: 0 0 0.25rem; }\n .subtitle { color: #666; margin: 0 0 2rem; }\n .toc { columns: 3 12rem; margin: 0 0 2.5rem; padding: 1rem 1.25rem; background: #f6f4f1; border-radius: 8px; }\n .toc a { display: block; color: #0b6; text-decoration: none; font-family: monospace; padding: 1px 0; }\n .toc a:hover { text-decoration: underline; }\n .rule { margin: 0 0 2.75rem; padding-top: 0.5rem; border-top: 1px solid #eee; }\n .rule h2 { font-size: 1.1rem; font-family: monospace; margin: 0 0 0.75rem; }\n .rule h2 a { color: #bbb; text-decoration: none; font-weight: normal; }\n .rule h2 a:hover { color: #0b6; }\n .ebnf { margin: 0.5rem 0 0; padding: 0.5rem 0.75rem; background: #f6f4f1; border-radius: 6px;\n font-family: monospace; font-size: 12px; white-space: pre-wrap; overflow-x: auto; }\n .diagram { overflow-x: auto; }\n /* The vendored library sizes each shape as (chars * 8 + padding), which assumes\n an 8px glyph advance (0.5em at 16px). Its own 14px-bold CSS actually advances\n ~8.4px/char, so long terminals crowd the box edges. Drop the text to 13px\n (advance ~7.8px) to restore comfortable side padding, and nudge the baked\n baseline (y+4) down slightly so glyphs sit vertically centered in the shapes. */\n svg.railroad-diagram text { font-size: 13px; }\n svg.railroad-diagram text:not(.comment) { transform: translateY(0.75px); }\n`\n\n/** Render the spec model as a self-contained HTML page of railroad diagrams. */\nexport function renderRailroadHtml(model: SpecModel, options: RailroadHtmlOptions = {}): string {\n const title = options.title ?? 'Grammar'\n const showEbnf = options.showEbnf ?? true\n\n const toc = model.productions\n .map(p => `<a href=\"#${slug(p.name)}\">${escapeHtml(p.name)}</a>`)\n .join('\\n ')\n\n const sections = model.productions\n .map((p: Production) => {\n const ebnf = showEbnf\n ? `<div class=\"ebnf\">${escapeHtml(`${p.name} ::= ${renderExpr(p.expr) || '/* empty */'}`)}</div>`\n : ''\n return ` <section class=\"rule\" id=\"${slug(p.name)}\">\n <h2><a href=\"#${slug(p.name)}\">\u00A7</a> ${escapeHtml(p.name)}</h2>\n <div class=\"diagram\" data-rule=\"${escapeHtml(p.name)}\"></div>\n ${ebnf}\n </section>`\n })\n .join('\\n')\n\n // One DSL expression per rule, built into its container at load time.\n const builders = model.productions\n .map(p => ` { name: ${j(p.name)}, dsl: function(){ return Diagram(${toDsl(p.expr)}); } }`)\n .join(',\\n')\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(title)}</title>\n<style>\n${RAILROAD_CSS}\n${PAGE_CSS}\n</style>\n</head>\n<body>\n<h1>${escapeHtml(title)}</h1>\n<p class=\"subtitle\">Syntax diagrams generated from the parser grammar.</p>\n<nav class=\"toc\">\n ${toc}\n</nav>\n${sections}\n<script>\n${RAILROAD_JS}\n</script>\n<script>\n(function () {\n var rules = [\n${builders}\n ];\n rules.forEach(function (r) {\n var host = document.querySelector('.diagram[data-rule=' + CSS.escape(r.name) + ']');\n if (!host) return;\n try { r.dsl().addTo(host); }\n catch (e) { host.textContent = 'diagram error: ' + e.message; }\n });\n})();\n</script>\n</body>\n</html>\n`\n}\n"],
5
+ "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
6
+ "names": ["builders"]
7
7
  }
@@ -1,10 +1,12 @@
1
1
  import type { GrammarInput, SpecOptions } from './model.ts';
2
+ import { renderRailroadSvg } from './railroad.ts';
2
3
  import type { RailroadHtmlOptions } from './railroad.ts';
3
4
  export { buildSpecModel } from './model.ts';
4
5
  export type { GrammarInput, SpecModel, SpecOptions, SpecNode, Production } from './model.ts';
5
6
  export { renderEBNF, renderExpr } from './ebnf.ts';
6
- export { renderRailroadHtml } from './railroad.ts';
7
- export type { RailroadHtmlOptions } from './railroad.ts';
7
+ export { renderRailroadHtml, renderRailroadSvg } from './railroad.ts';
8
+ export type { RailroadHtmlOptions, RailroadSvg } from './railroad.ts';
9
+ export { RAILROAD_CSS } from './railroad-lib.ts';
8
10
  /** Generate W3C-style EBNF text (one production per named rule). */
9
11
  export declare function toEBNF(grammar: GrammarInput, options?: SpecOptions): string;
10
12
  /**
@@ -12,4 +14,10 @@ export declare function toEBNF(grammar: GrammarInput, options?: SpecOptions): st
12
14
  * per production — with an EBNF caption under each. No external dependencies.
13
15
  */
14
16
  export declare function toRailroadHtml(grammar: GrammarInput, options?: SpecOptions & RailroadHtmlOptions): string;
17
+ /**
18
+ * Render each production to a static, self-contained SVG string — one per named
19
+ * rule — ready to inline in a docs page, README, or any HTML (no client script).
20
+ * Style with the exported `RAILROAD_CSS`, scoped to whatever wraps the SVGs.
21
+ */
22
+ export declare function toRailroadSvg(grammar: GrammarInput, options?: SpecOptions): ReturnType<typeof renderRailroadSvg>;
15
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spec/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAa,WAAW,EAAE,MAAM,YAAY,CAAA;AAGtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExD,oEAAoE;AACpE,wBAAgB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAE3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,WAAW,GAAG,mBAAmB,GAC1C,MAAM,CAGR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spec/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAa,WAAW,EAAE,MAAM,YAAY,CAAA;AAEtE,OAAO,EAAsB,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5F,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACrE,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,oEAAoE;AACpE,wBAAgB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAE3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,WAAW,GAAG,mBAAmB,GAC1C,MAAM,CAGR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAEhH"}