parseman 0.46.0 → 0.47.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.
- package/README.md +8 -3
- package/dist/analysis/choice-cost-render.d.ts +12 -4
- package/dist/analysis/choice-cost-render.d.ts.map +1 -1
- package/dist/analysis/choice-cost.d.ts +2 -2
- package/dist/analysis/choice-cost.d.ts.map +1 -1
- package/dist/analysis/commitment.d.ts +131 -0
- package/dist/analysis/commitment.d.ts.map +1 -0
- package/dist/analysis/diagnostics.cjs +9929 -7465
- package/dist/analysis/diagnostics.cjs.map +3 -4
- package/dist/analysis/diagnostics.d.ts +2 -2
- package/dist/analysis/diagnostics.js +9929 -7465
- package/dist/analysis/diagnostics.js.map +3 -4
- package/dist/analysis/duplication.d.ts.map +1 -1
- package/dist/analysis/fix.d.ts +3 -3
- package/dist/analysis/fix.d.ts.map +1 -1
- package/dist/analysis/format-number.d.ts +23 -0
- package/dist/analysis/format-number.d.ts.map +1 -0
- package/dist/analysis/gating.d.ts +39 -2
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/analysis/rebuild.d.ts.map +1 -1
- package/dist/analysis/terminal.d.ts +5 -2
- package/dist/analysis/terminal.d.ts.map +1 -1
- package/dist/cli/index.cjs +10865 -8535
- package/dist/cli/index.cjs.map +3 -4
- package/dist/cli/index.js +10865 -8535
- package/dist/cli/index.js.map +3 -4
- package/dist/combinators/adjacency.d.ts +100 -0
- package/dist/combinators/adjacency.d.ts.map +1 -0
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/completions.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts +8 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/gate.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts +22 -0
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts +8 -0
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts +0 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +13 -3
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts +1 -1
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts +1 -16
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts +30 -2
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts +71 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/combinators/token.d.ts.map +1 -1
- package/dist/combinators/trivia-boundary.d.ts +26 -0
- package/dist/combinators/trivia-boundary.d.ts.map +1 -0
- package/dist/combinators/trivia-skip.d.ts +40 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/combinators/withCtx.d.ts.map +1 -1
- package/dist/compiler/compile-linkable-table.d.ts +104 -0
- package/dist/compiler/compile-linkable-table.d.ts.map +1 -0
- package/dist/compiler/degradation.d.ts +0 -2
- package/dist/compiler/degradation.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts +13 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts +5 -5
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +47 -53
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +81 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -0
- package/dist/compiler/token-dispatch.d.ts +95 -0
- package/dist/compiler/token-dispatch.d.ts.map +1 -0
- package/dist/compiler/token-scanner.d.ts +53 -0
- package/dist/compiler/token-scanner.d.ts.map +1 -0
- package/dist/compiler/value-usage.d.ts.map +1 -1
- package/dist/coverage.d.ts +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/capture-buffer.d.ts +35 -0
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/cst/reflection-attach.d.ts +8 -0
- package/dist/cst/reflection-attach.d.ts.map +1 -0
- package/dist/cst/reflection-symbols.d.ts +10 -0
- package/dist/cst/reflection-symbols.d.ts.map +1 -0
- package/dist/cst/reflection.d.ts +2 -4
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/cst/root-trivia-scope.d.ts +26 -0
- package/dist/cst/root-trivia-scope.d.ts.map +1 -0
- package/dist/cst/trivia-charscan.d.ts +18 -0
- package/dist/cst/trivia-charscan.d.ts.map +1 -0
- package/dist/cst/trivia-kinds.d.ts +19 -0
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/functional/run-tabled.d.ts +12 -0
- package/dist/functional/run-tabled.d.ts.map +1 -0
- package/dist/functional/run.d.ts +25 -42
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/grammar-metadata.d.ts +3 -0
- package/dist/grammar-metadata.d.ts.map +1 -0
- package/dist/index.cjs +9224 -7203
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9219 -7198
- package/dist/index.js.map +3 -4
- package/dist/language-service/index.cjs +311 -121
- package/dist/language-service/index.cjs.map +3 -4
- package/dist/language-service/index.js +311 -121
- package/dist/language-service/index.js.map +3 -4
- package/dist/oracle/index.cjs.map +0 -1
- package/dist/oracle/index.js.map +0 -1
- package/dist/parse-context.d.ts +49 -0
- package/dist/parse-context.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts +40 -1
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +11146 -9593
- package/dist/plugin/index.cjs.map +3 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +11146 -9593
- package/dist/plugin/index.js.map +3 -4
- package/dist/regex/classes.d.ts +28 -0
- package/dist/regex/classes.d.ts.map +1 -1
- package/dist/regex/first-set.d.ts +14 -0
- package/dist/regex/first-set.d.ts.map +1 -1
- package/dist/run/index.cjs +136 -51
- package/dist/run/index.cjs.map +2 -3
- package/dist/run/index.js +136 -51
- package/dist/run/index.js.map +2 -3
- package/dist/spec/index.cjs +2898 -1623
- package/dist/spec/index.cjs.map +3 -4
- package/dist/spec/index.js +2898 -1623
- package/dist/spec/index.js.map +3 -4
- package/dist/spec/model.d.ts +8 -0
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +307 -0
- package/dist/table/assemble.d.ts.map +1 -0
- package/dist/table/cell.d.ts +42 -0
- package/dist/table/cell.d.ts.map +1 -0
- package/dist/table/child-slots.d.ts +30 -0
- package/dist/table/child-slots.d.ts.map +1 -0
- package/dist/table/compile-rule-map.d.ts +136 -0
- package/dist/table/compile-rule-map.d.ts.map +1 -0
- package/dist/table/compile.d.ts +56 -0
- package/dist/table/compile.d.ts.map +1 -0
- package/dist/table/duplication-hook.d.ts +32 -0
- package/dist/table/duplication-hook.d.ts.map +1 -0
- package/dist/table/emit-assembly.d.ts +139 -0
- package/dist/table/emit-assembly.d.ts.map +1 -0
- package/dist/table/emit.d.ts +113 -0
- package/dist/table/emit.d.ts.map +1 -0
- package/dist/table/encode-baseline.d.ts +16 -0
- package/dist/table/encode-baseline.d.ts.map +1 -0
- package/dist/table/encode.d.ts +71 -0
- package/dist/table/encode.d.ts.map +1 -0
- package/dist/table/exec-baseline.d.ts +9 -0
- package/dist/table/exec-baseline.d.ts.map +1 -0
- package/dist/table/exec.d.ts +72 -0
- package/dist/table/exec.d.ts.map +1 -0
- package/dist/table/fold.d.ts +25 -0
- package/dist/table/fold.d.ts.map +1 -0
- package/dist/table/index.cjs +11375 -0
- package/dist/table/index.cjs.map +6 -0
- package/dist/table/index.d.ts +100 -0
- package/dist/table/index.d.ts.map +1 -0
- package/dist/table/index.js +11352 -0
- package/dist/table/index.js.map +6 -0
- package/dist/table/inspect.d.ts +17 -0
- package/dist/table/inspect.d.ts.map +1 -0
- package/dist/table/ops.d.ts +446 -0
- package/dist/table/ops.d.ts.map +1 -0
- package/dist/table/program.d.ts +493 -0
- package/dist/table/program.d.ts.map +1 -0
- package/dist/table/run-support.d.ts +38 -0
- package/dist/table/run-support.d.ts.map +1 -0
- package/dist/{compiler/scannable-run.d.ts → table/scan-shapes.d.ts} +14 -13
- package/dist/table/scan-shapes.d.ts.map +1 -0
- package/dist/table/site-labels.d.ts +58 -0
- package/dist/table/site-labels.d.ts.map +1 -0
- package/dist/table/stamp.d.ts +70 -0
- package/dist/table/stamp.d.ts.map +1 -0
- package/dist/types.d.ts +80 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +25 -2
- package/src/analysis/choice-cost-gate.ts +359 -0
- package/src/analysis/choice-cost-render.ts +293 -0
- package/src/analysis/choice-cost.ts +1008 -0
- package/src/analysis/commitment.ts +557 -0
- package/src/analysis/corpus.ts +130 -0
- package/src/analysis/diagnose-render.ts +625 -0
- package/src/analysis/diagnose.ts +317 -0
- package/src/analysis/diagnostics.ts +33 -0
- package/src/analysis/duplication.ts +1955 -0
- package/src/analysis/fix-render.ts +217 -0
- package/src/analysis/fix.ts +669 -0
- package/src/analysis/format-number.ts +31 -0
- package/src/analysis/gating.ts +792 -0
- package/src/analysis/grammar.ts +72 -0
- package/src/analysis/rebuild.ts +287 -0
- package/src/analysis/terminal.ts +336 -0
- package/src/cli/index.ts +413 -0
- package/src/combinators/adjacency.ts +171 -0
- package/src/combinators/attempt.ts +41 -0
- package/src/combinators/case-fold.ts +90 -0
- package/src/combinators/choice.ts +466 -0
- package/src/combinators/completions.ts +64 -0
- package/src/combinators/dispatch.ts +358 -0
- package/src/combinators/expect.ts +159 -0
- package/src/combinators/first-set.ts +322 -0
- package/src/combinators/gate.ts +50 -0
- package/src/combinators/grammar.ts +272 -0
- package/src/combinators/keywords.ts +145 -0
- package/src/combinators/literal.ts +102 -0
- package/src/combinators/map.ts +106 -0
- package/src/combinators/node.ts +345 -0
- package/src/combinators/not.ts +55 -0
- package/src/combinators/parser.ts +266 -0
- package/src/combinators/peek.ts +63 -0
- package/src/combinators/probe.ts +25 -0
- package/src/combinators/ref.ts +109 -0
- package/src/combinators/regex.ts +170 -0
- package/src/combinators/repeat.ts +561 -0
- package/src/combinators/scanTo.ts +393 -0
- package/src/combinators/sequence.ts +221 -0
- package/src/combinators/token.ts +120 -0
- package/src/combinators/trivia-boundary.ts +48 -0
- package/src/combinators/trivia-skip.ts +821 -0
- package/src/combinators/withCtx.ts +45 -0
- package/src/compiler/build-arity.ts +330 -0
- package/src/compiler/compile-linkable-table.ts +209 -0
- package/src/compiler/degradation.ts +266 -0
- package/src/compiler/fields.ts +191 -0
- package/src/compiler/grammar-coverage-ids.ts +129 -0
- package/src/compiler/ir-serialize.ts +615 -0
- package/src/compiler/linker.ts +954 -0
- package/src/compiler/token-alphabet.ts +209 -0
- package/src/compiler/token-dispatch.ts +353 -0
- package/src/compiler/token-scanner.ts +318 -0
- package/src/compiler/value-usage.ts +147 -0
- package/src/coverage.ts +383 -0
- package/src/cst/capture-buffer.ts +297 -0
- package/src/cst/host-mode.ts +69 -0
- package/src/cst/reflection-attach.ts +11 -0
- package/src/cst/reflection-symbols.ts +9 -0
- package/src/cst/reflection.ts +149 -0
- package/src/cst/relative-spans.ts +207 -0
- package/src/cst/root-trivia-scope.ts +30 -0
- package/src/cst/trivia-charscan.ts +312 -0
- package/src/cst/trivia-entries.ts +285 -0
- package/src/cst/trivia-index.ts +131 -0
- package/src/cst/trivia-kinds.ts +358 -0
- package/src/cst/types.ts +76 -0
- package/src/cst/walk.ts +101 -0
- package/src/functional/doc.ts +959 -0
- package/src/functional/run-tabled.ts +153 -0
- package/src/functional/run.ts +558 -0
- package/src/grammar-metadata.ts +2 -0
- package/src/index.ts +189 -0
- package/src/language-service/index.ts +221 -0
- package/src/line-index.ts +131 -0
- package/src/oracle/digest.ts +620 -0
- package/src/oracle/index.ts +55 -0
- package/src/parse-context.ts +91 -0
- package/src/plugin/direct-builder-static.ts +102 -0
- package/src/plugin/evaluator.ts +1505 -0
- package/src/plugin/free-identifiers.ts +338 -0
- package/src/plugin/index.ts +2281 -0
- package/src/plugin/reducer-resolver.ts +606 -0
- package/src/recovery/scan.ts +155 -0
- package/src/regex/classes.ts +183 -0
- package/src/regex/first-set.ts +316 -0
- package/src/run/index.ts +31 -0
- package/src/spec/ebnf.ts +128 -0
- package/src/spec/index.ts +54 -0
- package/src/spec/model.ts +636 -0
- package/src/spec/railroad-lib.ts +559 -0
- package/src/spec/railroad.ts +256 -0
- package/src/table/assemble.ts +2994 -0
- package/src/table/cell.ts +42 -0
- package/src/table/child-slots.ts +113 -0
- package/src/table/compile-rule-map.ts +336 -0
- package/src/table/compile.ts +244 -0
- package/src/table/duplication-hook.ts +89 -0
- package/src/table/emit-assembly.ts +1766 -0
- package/src/table/emit.ts +418 -0
- package/src/table/encode-baseline.ts +340 -0
- package/src/table/encode.ts +1569 -0
- package/src/table/exec-baseline.ts +537 -0
- package/src/table/exec.ts +1672 -0
- package/src/table/fold.ts +38 -0
- package/src/table/index.ts +108 -0
- package/src/table/inspect.ts +52 -0
- package/src/table/ops.ts +459 -0
- package/src/table/program.ts +855 -0
- package/src/table/run-support.ts +66 -0
- package/src/table/scan-shapes.ts +1578 -0
- package/src/table/site-labels.ts +228 -0
- package/src/table/stamp.ts +229 -0
- package/src/types.ts +563 -0
- package/src/version.ts +16 -0
- package/dist/compiler/codegen.d.ts +0 -334
- package/dist/compiler/codegen.d.ts.map +0 -1
- package/dist/compiler/inline-build.d.ts +0 -11
- package/dist/compiler/inline-build.d.ts.map +0 -1
- package/dist/compiler/inline-callback.d.ts +0 -21
- package/dist/compiler/inline-callback.d.ts.map +0 -1
- package/dist/compiler/line-index.d.ts +0 -2
- package/dist/compiler/line-index.d.ts.map +0 -1
- package/dist/compiler/module-hoist.d.ts +0 -106
- package/dist/compiler/module-hoist.d.ts.map +0 -1
- package/dist/compiler/scannable-run.d.ts.map +0 -1
- package/dist/compiler/scannable-terminal.d.ts +0 -23
- package/dist/compiler/scannable-terminal.d.ts.map +0 -1
- package/dist/compiler/trivia-fast-path.d.ts +0 -38
- package/dist/compiler/trivia-fast-path.d.ts.map +0 -1
package/src/types.ts
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
export type Span = {
|
|
2
|
+
start: number
|
|
3
|
+
end: number
|
|
4
|
+
startLine?: number
|
|
5
|
+
startColumn?: number
|
|
6
|
+
endLine?: number
|
|
7
|
+
endColumn?: number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ParseOk<T> = {
|
|
11
|
+
ok: true
|
|
12
|
+
value: T
|
|
13
|
+
span: Span
|
|
14
|
+
trivia?: Span[]
|
|
15
|
+
/** Populated when parse() is called with { recover: true }. Lists all ParseErrors collected via recover() nodes. */
|
|
16
|
+
errors?: ParseError[]
|
|
17
|
+
/**
|
|
18
|
+
* Populated when parse() is called with { recover: true }. The furthest-position
|
|
19
|
+
* failure seen during the parse (with expected-sets merged across ties) — the
|
|
20
|
+
* standard "this is where it actually got stuck" diagnostic, meaningful even when
|
|
21
|
+
* the parse otherwise succeeds with unconsumed trailing input.
|
|
22
|
+
*/
|
|
23
|
+
furthestFail?: ParseFail | null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type ParseFail = {
|
|
27
|
+
ok: false
|
|
28
|
+
expected: string[]
|
|
29
|
+
span: Span
|
|
30
|
+
/**
|
|
31
|
+
* Framework-internal cut/commit signal. A committed failure means an outer
|
|
32
|
+
* backtracking construct must propagate the failure instead of trying a later
|
|
33
|
+
* alternative or swallowing it as an optional/repeat miss.
|
|
34
|
+
*/
|
|
35
|
+
committed?: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ParseResult<T> = ParseOk<T> | ParseFail
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Combinator definition tree — carried on every Combinator so the compiler can
|
|
42
|
+
// traverse the full combinator structure without re-parsing source.
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
export type ParserDef =
|
|
45
|
+
| { tag: 'literal'; value: string; caseInsensitive: boolean }
|
|
46
|
+
| { tag: 'regex'; source: string; flags: string }
|
|
47
|
+
// `valueUnused` (set by markUnusedValues): the container's aggregate value is
|
|
48
|
+
// consumed by nothing but capture (it sits directly under a node() that reads
|
|
49
|
+
// children, not this value). When true, the interpreter and codegen skip
|
|
50
|
+
// building the array/tuple — the elements still parse + self-capture.
|
|
51
|
+
| { tag: 'sequence'; parsers: Combinator<unknown>[]; valueUnused?: boolean }
|
|
52
|
+
// `gateSrcs` (set by the macro evaluator): per-arm gate predicate SOURCE TEXT,
|
|
53
|
+
// aligned by arm index (null for an ungated arm). Lets codegen inline the gate
|
|
54
|
+
// into the macro's `_mf` array instead of pushing a `null` source (which would
|
|
55
|
+
// force interpreter fallback). Absent under runtime compile() — the real gate
|
|
56
|
+
// closures live in `gates`.
|
|
57
|
+
| { tag: 'choice'; parsers: Combinator<unknown>[]; gates: (((state: unknown) => boolean) | null)[]; gateSrcs?: (string | null)[]; disjoint: boolean; strategy: ChoiceStrategy; autoNot: (AutoNotCheck[] | null)[] }
|
|
58
|
+
| { tag: 'dispatch'; selector: Combinator<string>; cases: readonly DispatchCase[]; matchers?: readonly DispatchMatcherCase[] | undefined; otherwise?: Combinator<unknown> | undefined; otherwiseUsesRouted?: boolean | undefined }
|
|
59
|
+
| { tag: 'attempt'; parser: Combinator<unknown> }
|
|
60
|
+
// The TAG carries NULLABILITY (what every downstream switch keys on): `many` is
|
|
61
|
+
// the nullable min-0 repeat, `oneOrMore` the non-nullable min>=1 one. `min`/`max`
|
|
62
|
+
// carry the actual ITEM bounds (`many(x, { min: 3, max: 8 })` is a `oneOrMore`
|
|
63
|
+
// def with `min: 3, max: 8`). `max` absent = unbounded.
|
|
64
|
+
| { tag: 'many'; parser: Combinator<unknown>; min: 0; max?: number; valueUnused?: boolean }
|
|
65
|
+
| { tag: 'oneOrMore'; parser: Combinator<unknown>; min: number; max?: number; valueUnused?: boolean }
|
|
66
|
+
| { tag: 'optional'; parser: Combinator<unknown> }
|
|
67
|
+
// `min`/`max` count ITEMS, not separators. `min: 0` (the default) is
|
|
68
|
+
// `(item (sep item)*)?` — NULLABLE, matches the empty string. `min >= 1` is
|
|
69
|
+
// non-nullable with first-set = the item's, so it gates as a choice arm.
|
|
70
|
+
// `trailing` governs a separator with no item after it: 'forbid' (default) leaves
|
|
71
|
+
// it unconsumed, 'allow' consumes it. There is no "one after every item" mode —
|
|
72
|
+
// that is a terminated list, spelled `many(sequence(item, term))`.
|
|
73
|
+
| { tag: 'sepBy'; parser: Combinator<unknown>; separator: Combinator<unknown>; min: number; max?: number; trailing?: 'allow'; /** Author opted in via `keepSeparator()`: separators stay in `children`. Absent = items only. */ keepSeparators?: true }
|
|
74
|
+
| { tag: 'transform'; parser: Combinator<unknown>; fn: (v: unknown, span: { start: number; end: number }) => unknown; fnSrc?: string; recognitionOnly?: boolean }
|
|
75
|
+
| { tag: 'trivia'; parser: Combinator<unknown> }
|
|
76
|
+
| { tag: 'token'; parser: Combinator<unknown> }
|
|
77
|
+
// `fallback` is what `routed()` parses IN PLACE when there is no dispatch-consumed
|
|
78
|
+
// token to reuse (outside a dispatch branch, or at a position other than the one the
|
|
79
|
+
// selector matched). It exists so ONE production can serve both contexts instead of
|
|
80
|
+
// being spelled twice — a `routed()` twin and a concrete-lead original.
|
|
81
|
+
| { tag: 'routed'; fallback?: Combinator<unknown> }
|
|
82
|
+
| { tag: 'leaf'; parser: Combinator<unknown>; fn: (v: unknown, span: { start: number; end: number }) => unknown; fnSrc?: string }
|
|
83
|
+
| { tag: 'label'; label: string; parser: Combinator<unknown> }
|
|
84
|
+
| { tag: 'field'; name: string; parser: Combinator<unknown> }
|
|
85
|
+
| { tag: 'grammar'; parser: Combinator<unknown>; triviaParser: Combinator<unknown> | undefined; clearTrivia?: boolean; captureTrivia?: boolean; rootCapture?: 'opaque'; trackLines: boolean }
|
|
86
|
+
| { tag: 'lazy'; thunk: () => Combinator<unknown> }
|
|
87
|
+
| { tag: 'not'; parser: Combinator<unknown> }
|
|
88
|
+
// Positive lookahead. Zero-width like `not`, but — unlike `not` — it KNOWS what
|
|
89
|
+
// it requires, so it carries `parser`'s first-set and a leading `peek()` gates
|
|
90
|
+
// its choice arm (see `isPositiveLookahead` / `sequenceFirstSet`).
|
|
91
|
+
| { tag: 'peek'; parser: Combinator<unknown> }
|
|
92
|
+
| { tag: 'node'; type?: string; parser: Combinator<unknown>; build?: ((children: ReadonlyArray<unknown>, fields: FieldMap | undefined, span: { start: number; end: number }, rawChildren: ReadonlyArray<unknown>, triviaLog: readonly number[], state: unknown) => unknown) | undefined; buildSrc?: string; /** The IDENTIFIER the type argument was written as at the `node()` call site, when it was a plain identifier rather than a literal — ANALYSIS ONLY, never emitted. Lets the inline-`mk` matcher recognise `node(t, …, (…) => mk(t, …))` from a factory, where the two `t`s are provably one binding. */ typeSrc?: string; /** Resolved source of a NAMED `buildSrc` — ANALYSIS ONLY, never emitted. See `buildAnalysisSrc`. */ buildSigSrc?: string; /** Declared positional arity of `build`: author-declared via `node(..., { buildArity })`, or resolved from the reducer's declaration. Wins over source inspection. */ buildArity?: number; /** Why arity could not be resolved, for the diagnostic. */ buildArityUnresolved?: string; buildStaticError?: readonly string[]; unwrap?: boolean; collapse?: boolean; project?: number; captureTrivia?: boolean; trailingTrivia?: boolean; tags?: readonly string[] }
|
|
93
|
+
// `predSrc`/`extraSrc` (set by the macro evaluator): SOURCE TEXT of the guard
|
|
94
|
+
// predicate / the withCtx `extra` value, so codegen inlines them into `_mf`
|
|
95
|
+
// rather than pushing a `null` source. Absent under runtime compile() (the real
|
|
96
|
+
// closures/values live in `predicate`/`extra`).
|
|
97
|
+
| { tag: 'guard'; predicate: (state: unknown) => boolean; predSrc?: string }
|
|
98
|
+
// ADJACENCY assertion — zero-width, zero-children. `polarity: 'adjacent'` asserts
|
|
99
|
+
// that NOTHING sat between the previous term and this position; `'notAdjacent'`
|
|
100
|
+
// asserts that something did. `kinds` (notAdjacent only) narrows the assertion to
|
|
101
|
+
// trivia CATEGORIES from `classifiedTrivia({...})`. See combinators/adjacency.ts.
|
|
102
|
+
| { tag: 'adjacency'; polarity: 'adjacent' | 'notAdjacent'; kinds?: readonly string[] }
|
|
103
|
+
| { tag: 'withCtx'; extra: unknown; parser: Combinator<unknown>; extraSrc?: string }
|
|
104
|
+
| { tag: 'recover'; parser: Combinator<unknown>; sentinel: Combinator<unknown> }
|
|
105
|
+
| { tag: 'expect'; parser: Combinator<unknown>; label: string | undefined; expected: string[] }
|
|
106
|
+
// `skip` is the per-call opaque-unit list; ambient trivia + grammar-level
|
|
107
|
+
// `scanSkip` are PREPENDED at parse/compile time (explicit skip EXTENDS the
|
|
108
|
+
// ambient default). `raw`: hard opt-out — skip nothing ambiently, restoring the
|
|
109
|
+
// pre-ambient raw byte-walk.
|
|
110
|
+
| { tag: 'scanTo'; sentinel: Combinator<unknown>; skip: Combinator<unknown>[]; raw: boolean; orEOF: boolean }
|
|
111
|
+
| { tag: 'keywords'; words: readonly string[]; caseInsensitive: boolean; boundary: string | undefined }
|
|
112
|
+
| { tag: 'unknown' }
|
|
113
|
+
|
|
114
|
+
export type Combinator<T> = {
|
|
115
|
+
readonly _tag: string
|
|
116
|
+
readonly _meta: ParserMeta
|
|
117
|
+
readonly _def: ParserDef
|
|
118
|
+
parse(input: string, pos: number, ctx: ParseContext): ParseResult<T>
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type DispatchCase = {
|
|
122
|
+
keys: readonly string[]
|
|
123
|
+
parser: Combinator<unknown>
|
|
124
|
+
caseInsensitive: boolean
|
|
125
|
+
usesRouted?: boolean | undefined
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type DispatchMatcherKind = 'startsWith' | 'endsWith' | 'matches'
|
|
129
|
+
|
|
130
|
+
export type DispatchMatcherCase = {
|
|
131
|
+
kind: DispatchMatcherKind
|
|
132
|
+
value: string
|
|
133
|
+
flags?: string | undefined
|
|
134
|
+
parser: Combinator<unknown>
|
|
135
|
+
caseInsensitive: boolean
|
|
136
|
+
usesRouted?: boolean | undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
import type { CstCaptureBuf } from './cst/capture-buffer.ts'
|
|
140
|
+
|
|
141
|
+
export type CstCollapsePredicate = (
|
|
142
|
+
type: string,
|
|
143
|
+
child: unknown,
|
|
144
|
+
children: ReadonlyArray<unknown>,
|
|
145
|
+
rawChildren: ReadonlyArray<unknown>,
|
|
146
|
+
) => boolean
|
|
147
|
+
|
|
148
|
+
export type BuildHost = ((
|
|
149
|
+
type: string,
|
|
150
|
+
// Always an array by public contract. When a structural host opts out of the
|
|
151
|
+
// duplicate children collector via `_parsemanReadsChildren === false`, it
|
|
152
|
+
// receives the shared empty array while `rawChildren` retains the full source
|
|
153
|
+
// view. Keeping this non-optional preserves assignability for existing hosts.
|
|
154
|
+
children: ReadonlyArray<unknown>,
|
|
155
|
+
fields: FieldMap | undefined,
|
|
156
|
+
span: { start: number; end: number },
|
|
157
|
+
rawChildren: ReadonlyArray<unknown>,
|
|
158
|
+
triviaLog: readonly number[],
|
|
159
|
+
state: unknown,
|
|
160
|
+
tags?: readonly string[] | undefined,
|
|
161
|
+
) => unknown) & {
|
|
162
|
+
/** Framework-internal: optional syntax-CST wrapper collapse policy. */
|
|
163
|
+
_parsemanCstCollapse?: CstCollapsePredicate | undefined
|
|
164
|
+
/**
|
|
165
|
+
* Framework-internal: `false` when this host builds its node purely from
|
|
166
|
+
* `rawChildren` (arg 4) and never reads the structural `children` (arg 1).
|
|
167
|
+
* Arity-based elision (`_hostReads`) cannot see this: a host that reads a LATER
|
|
168
|
+
* positional arg (`span`/`rawChildren`/`state`) must still DECLARE `children`
|
|
169
|
+
* positionally, so `Function.length` stays high and every arg-gate reports
|
|
170
|
+
* "read". This explicit opt-out lets a structural node skip allocating its
|
|
171
|
+
* per-node `children` array entirely — a pure duplicate of `rawChildren` for a
|
|
172
|
+
* structural grammar. Default (`undefined`) keeps the array (output-neutral).
|
|
173
|
+
* A host that sets this MUST NOT also read `children`, and must not rely on
|
|
174
|
+
* `_parsemanCstCollapse` (which inspects `children`).
|
|
175
|
+
*/
|
|
176
|
+
_parsemanReadsChildren?: boolean | undefined
|
|
177
|
+
/**
|
|
178
|
+
* Framework-internal: node types whose structural host wants triviaLog.
|
|
179
|
+
* This predicate is assembly-specialisation configuration: both its identity
|
|
180
|
+
* and behaviour must remain stable after the host is first used. To change
|
|
181
|
+
* the selection, assign a NEW predicate function; replacing its identity
|
|
182
|
+
* invalidates the host's cached specialisation.
|
|
183
|
+
*/
|
|
184
|
+
_parsemanCaptureTrivia?: ((type: string) => boolean) | undefined
|
|
185
|
+
/**
|
|
186
|
+
* Framework-internal: per-node-type trivia-kind filter for the captured
|
|
187
|
+
* `triviaLog`. Returns a bitmask over the trivia's `triviaKindLabels` (bit `k`
|
|
188
|
+
* = keep kind `k`); `undefined` = keep every kind (default). Lets a host ask
|
|
189
|
+
* one node type for comments-only while another still gets whitespace — e.g.
|
|
190
|
+
* `Ruleset`/`Stylesheet` want comment runs, `CompoundSelector` needs the
|
|
191
|
+
* whitespace that marks a descendant combinator. Scoped to the node and
|
|
192
|
+
* restored on exit. Build a mask with `triviaKindMask(labels, keep)`.
|
|
193
|
+
*/
|
|
194
|
+
_parsemanTriviaKinds?: ((type: string) => number | undefined) | undefined
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export type FieldCapture<T = unknown> = {
|
|
198
|
+
value: T
|
|
199
|
+
span: Span
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type FieldMap = Record<string, FieldCapture | FieldCapture[]>
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Recovery helpers the runtime driver injects into a COMPILED parse's ctx (`_rec`)
|
|
206
|
+
* when tolerant, so the compiled output reuses the exact interpreter recovery
|
|
207
|
+
* functions (`recoverScan`/`matchesAt`/`orSentinel`) — guaranteeing parity without
|
|
208
|
+
* the emitted `new Function` needing module-scope access.
|
|
209
|
+
*/
|
|
210
|
+
export type RecoveryHelpers = {
|
|
211
|
+
scan: (input: string, from: number, ctx: ParseContext, sync: Combinator<unknown>, expected: string[]) => { error: ParseError; end: number }
|
|
212
|
+
at: (sentinel: Combinator<unknown>, input: string, pos: number, ctx: ParseContext) => boolean
|
|
213
|
+
or: (a: Combinator<unknown>, b: Combinator<unknown> | undefined) => Combinator<unknown>
|
|
214
|
+
/** Build a zero-width follow-set sentinel from a first-set. Called from compiled
|
|
215
|
+
* code (via `_ctx`, never `_rp`) so recovery grammars stay macro-inlinable. */
|
|
216
|
+
sentinel: (fs: FirstSet) => Combinator<unknown> | null
|
|
217
|
+
/** Embed a recovered error as a `parseError` CST child at the recovery point
|
|
218
|
+
* (no-op when CST capture is off). Called from both paths so the error lives in
|
|
219
|
+
* the tree — riding reused subtrees across incremental edits — not just the flat
|
|
220
|
+
* `_errors` channel. */
|
|
221
|
+
capture: (ctx: ParseContext, error: ParseError) => void
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export type ParseContext = {
|
|
225
|
+
// `| undefined` (matching captureTrivia/_cst* below): a nested scope may
|
|
226
|
+
// intentionally CLEAR inherited trivia by setting these to undefined (noTrivia).
|
|
227
|
+
trivia?: Combinator<unknown> | undefined
|
|
228
|
+
/**
|
|
229
|
+
* Grammar-level ambient opaque-unit skippers (strings, balanced brackets, …),
|
|
230
|
+
* declared once via `rules({ scanSkip }, factory)` and threaded here at the
|
|
231
|
+
* parse entry — the scan-skip analogue of `trivia`. A `scanTo`/`balanced` with
|
|
232
|
+
* no explicit per-call `skip` (and not `raw`) consults these so a sentinel
|
|
233
|
+
* hidden inside a string/bracket run is never matched. Separate category from
|
|
234
|
+
* `trivia`: trivia is insignificant everywhere; scanSkip is significant but
|
|
235
|
+
* atomic during a scan. Undefined when the grammar declares none.
|
|
236
|
+
*/
|
|
237
|
+
scanSkip?: Combinator<unknown>[] | undefined
|
|
238
|
+
/**
|
|
239
|
+
* Label table for the active trivia parser (`label(name, arm)` strings in
|
|
240
|
+
* choice order). When set, trivia logs include a kind index per entry.
|
|
241
|
+
*/
|
|
242
|
+
triviaKindLabels?: readonly string[] | undefined
|
|
243
|
+
/**
|
|
244
|
+
* When true (and a CST node is collecting children), trivia consumed between
|
|
245
|
+
* terms is recorded into _cstRawChildren as separate CSTTrivia tokens — one
|
|
246
|
+
* per maximal sub-match of the trivia parser (e.g. a whitespace run or a
|
|
247
|
+
* comment). When false/unset, trivia is skipped silently. Default: skip.
|
|
248
|
+
*/
|
|
249
|
+
captureTrivia?: boolean | undefined
|
|
250
|
+
/**
|
|
251
|
+
* Kind-filter for PER-NODE CST trivia capture (`triviaLog` handed to a node's
|
|
252
|
+
* builder). A bitmask over the active `triviaKindLabels` indices: bit `k` set
|
|
253
|
+
* means "record kind `k`"; `undefined` means record every kind (default). Only
|
|
254
|
+
* the per-node CST log is filtered — the global `_triviaLog` stays complete, so
|
|
255
|
+
* a downstream trivia map is unaffected. Lets a host that only consumes, say,
|
|
256
|
+
* comments enable per-node capture WITHOUT paying to log every whitespace run.
|
|
257
|
+
* Requires labeled trivia (indices align with `triviaKindLabels`); with no
|
|
258
|
+
* labels the mask can't apply and all trivia is captured. Build a mask with
|
|
259
|
+
* `triviaKindMask(labels, keep)`.
|
|
260
|
+
*/
|
|
261
|
+
_triviaCaptureMask?: number | undefined
|
|
262
|
+
trackLines: boolean
|
|
263
|
+
/** Grammar-author-provided state, scoped with withCtx() and read in guard(). */
|
|
264
|
+
state?: unknown
|
|
265
|
+
/**
|
|
266
|
+
* Mode host (RULE_ABI_PLAN §7): when set, a linkable/fused grammar's `node()`
|
|
267
|
+
* rules build via `build(type, children, fields, span, rawChildren, triviaLog, state)`
|
|
268
|
+
* instead of their own builder — so ONE grammar serves eval-AST (unset) vs
|
|
269
|
+
* positioned-CST / language-service (set) modes. Ignored by non-linkable output.
|
|
270
|
+
*/
|
|
271
|
+
build?: BuildHost | undefined
|
|
272
|
+
/** When set, recovery (tolerant lists / expect()) pushes each ParseError here in addition to embedding it in the tree. */
|
|
273
|
+
_errors?: ParseError[] | undefined
|
|
274
|
+
/**
|
|
275
|
+
* Framework-internal: layered "C+B" list recovery gate. When true, tolerant
|
|
276
|
+
* `many`/`oneOrMore`/`sepBy` recover from a failed element (skip to a sync point,
|
|
277
|
+
* emit a ParseError, keep parsing) instead of stopping the list. Unset (the
|
|
278
|
+
* default / strict path) ⇒ the list combinators behave byte-identically to before;
|
|
279
|
+
* the only residue is a single cold branch on the element-failure edge.
|
|
280
|
+
*/
|
|
281
|
+
_tolerant?: boolean | undefined
|
|
282
|
+
/**
|
|
283
|
+
* Framework-internal: the recovery sync sentinel in effect for the current
|
|
284
|
+
* subtree, published DOWN by an enclosing `sequence` in tolerant mode. It is a
|
|
285
|
+
* zero-width combinator that matches when the input could start any of the
|
|
286
|
+
* sequence's remaining terms — i.e. the enclosing delimiter/close a nested list
|
|
287
|
+
* should resync to. A nested `many`/`oneOrMore`/`sepBy` reads it as its recovery
|
|
288
|
+
* terminator on element failure. Inferred automatically from grammar structure
|
|
289
|
+
* (the grammar carries no recovery config); `undefined` when nothing is locally
|
|
290
|
+
* inferable. Dynamic scoping through rule refs gives cross-rule inheritance for
|
|
291
|
+
* free (a list at a rule's tail resyncs to whatever delimiter followed the call).
|
|
292
|
+
*/
|
|
293
|
+
_sync?: Combinator<unknown> | undefined
|
|
294
|
+
/**
|
|
295
|
+
* Framework-internal (compiled output only): recovery helpers injected by the
|
|
296
|
+
* runtime driver (`run`) when tolerant, so the compiled parser reuses the EXACT
|
|
297
|
+
* interpreter recovery functions — guaranteeing byte-for-byte parity without the
|
|
298
|
+
* emitted `new Function` needing module-scope access. Unset (strict) ⇒ compiled
|
|
299
|
+
* lists never enter the recovery branch. The interpreter ignores this field.
|
|
300
|
+
*/
|
|
301
|
+
_rec?: RecoveryHelpers | undefined
|
|
302
|
+
/**
|
|
303
|
+
* Framework-internal (compiled/macro output only): the deepest failure recorded
|
|
304
|
+
* while a fallible sub-parser was running — position (`_fe`) and expected set
|
|
305
|
+
* (`_fx`). Composite constructs (node, ref, withCtx, …) read these to propagate
|
|
306
|
+
* the inner failure verbatim instead of a coarse structural placeholder, keeping
|
|
307
|
+
* failure diagnostics at parity with the interpreter. Overwritten on each leaf
|
|
308
|
+
* failure; only meaningful immediately after a sub-parse reports failure.
|
|
309
|
+
*/
|
|
310
|
+
_fe?: number | undefined
|
|
311
|
+
_fx?: string[] | undefined
|
|
312
|
+
/** Framework-internal compiled-output committed-failure flag. */
|
|
313
|
+
_fc?: boolean | undefined
|
|
314
|
+
/**
|
|
315
|
+
* When set by completionsAt(), tracks the highest-position ParseFail seen
|
|
316
|
+
* during parsing up to _probe.offset. Used to return completions at the cursor
|
|
317
|
+
* even when sepBy/many backtracked past the cursor position.
|
|
318
|
+
*/
|
|
319
|
+
_probe?: { offset: number; best: ParseFail | null } | undefined
|
|
320
|
+
/**
|
|
321
|
+
* Framework-internal: current CSTNode rule's child collector.
|
|
322
|
+
* Set by node() during capture; undefined outside an active node parse.
|
|
323
|
+
* CSTNode parsers append themselves here after a successful parse.
|
|
324
|
+
*/
|
|
325
|
+
_cstChildren?: unknown[] | undefined
|
|
326
|
+
/**
|
|
327
|
+
* Framework-internal: collector for CSTLeaf terminals.
|
|
328
|
+
* Usually points to the same array as _cstChildren (both live together).
|
|
329
|
+
* literal() and regex() append a CSTLeaf here when set.
|
|
330
|
+
*/
|
|
331
|
+
_cstLeaves?: unknown[] | undefined
|
|
332
|
+
/**
|
|
333
|
+
* Framework-internal: collector for ALL children including trivia.
|
|
334
|
+
* Set alongside _cstChildren/_cstLeaves. Receives CSTLeaf + CSTNode entries
|
|
335
|
+
* (same as _cstChildren) PLUS CSTTrivia entries for trivia consumed between terms.
|
|
336
|
+
* Passed to buildNode() as rawChildren so grammars can inspect trivia.
|
|
337
|
+
*/
|
|
338
|
+
_cstRawChildren?: unknown[] | undefined
|
|
339
|
+
/**
|
|
340
|
+
* Framework-internal: flat trivia log. When set, scanTrivia records each
|
|
341
|
+
* consumed trivia entry as two numbers [start, end] appended to this
|
|
342
|
+
* array instead of (or in addition to) rawChildren capture. Zero object
|
|
343
|
+
* allocations — just number pushes.
|
|
344
|
+
*/
|
|
345
|
+
_triviaLog?: number[] | undefined
|
|
346
|
+
/**
|
|
347
|
+
* Framework-internal: selected root-trivia rows. Each row is
|
|
348
|
+
* `[gapStart, gapEnd, markerStart, markerEnd, kindIndex]`. Unlike
|
|
349
|
+
* `_triviaLog`, this never records an ordinary whitespace chunk: a row exists
|
|
350
|
+
* only for a selected labeled trivia kind, while its first pair preserves the
|
|
351
|
+
* complete committed gap that owns that marker. The fixed-width numeric log
|
|
352
|
+
* keeps compiler rollback as cheap as the legacy root sink.
|
|
353
|
+
*/
|
|
354
|
+
_rootTriviaLog?: number[] | undefined
|
|
355
|
+
/** Grammar-label → selected-root-table index. Each trivia scope maps its local
|
|
356
|
+
* label through this once-built table, so composed grammars may use different
|
|
357
|
+
* label orders without a per-chunk linear selected-label search. */
|
|
358
|
+
_rootTriviaKindIndex?: Readonly<Record<string, number>> | undefined
|
|
359
|
+
/** Selected-root capture checks local trivia classification once per scope. */
|
|
360
|
+
_rootTriviaStrictScopes?: boolean | undefined
|
|
361
|
+
/**
|
|
362
|
+
* Scoped selected-root capture switch. `parser({ rootCapture: 'opaque' })`
|
|
363
|
+
* turns this off for its explicit trivia region so that region cannot leak
|
|
364
|
+
* selected markers into the document-root capture.
|
|
365
|
+
*/
|
|
366
|
+
_rootTriviaCapture?: boolean | undefined
|
|
367
|
+
/**
|
|
368
|
+
* Framework-internal: flat per-node trivia log for CST capture mode.
|
|
369
|
+
* When set alongside _cstRawChildren, each trivia entry is recorded as three
|
|
370
|
+
* numbers [start, end, insertIdx] appended here (one entry = three numbers) instead of allocating a
|
|
371
|
+
* CSTTrivia object. `insertIdx` is the _cstRawChildren.length at the moment
|
|
372
|
+
* the trivia was consumed, so consumers know where in rawChildren to insert it.
|
|
373
|
+
* Zero object allocations — replaces the CSTTrivia object path entirely.
|
|
374
|
+
*/
|
|
375
|
+
_cstTriviaLog?: number[] | undefined
|
|
376
|
+
/** Framework-internal: active node() field captures, enabled only when needed. */
|
|
377
|
+
_fields?: Array<{ name: string; value: unknown; span: Span }> | undefined
|
|
378
|
+
/** Framework-internal: lazy capture buffer for active node() parse. */
|
|
379
|
+
_cstBuf?: CstCaptureBuf | undefined
|
|
380
|
+
/** Framework-internal: value/span already consumed by an enclosing dispatch(). */
|
|
381
|
+
_routed?: { value: unknown; span: Span } | undefined
|
|
382
|
+
/**
|
|
383
|
+
* Framework-internal optional line-start collector. Compiled parsers emitted
|
|
384
|
+
* with line tracking append newline-derived line starts here while matching
|
|
385
|
+
* terminals; the driver normalizes/dedupes once before annotating spans.
|
|
386
|
+
*/
|
|
387
|
+
_lineStarts?: number[] | undefined
|
|
388
|
+
/** Framework-internal shared line index for interpreter-side line annotation. */
|
|
389
|
+
_lineIndex?: { lineStarts: number[] } | undefined
|
|
390
|
+
/** Framework-internal high-water mark for optional line tracking range scans. */
|
|
391
|
+
_lineScannedTo?: number | undefined
|
|
392
|
+
/**
|
|
393
|
+
* Framework-internal coverage hook. Previously reached `ctx` only via a
|
|
394
|
+
* conditional spread of `RunOptions.instrumentation`, so an instrumented parse
|
|
395
|
+
* gave `ctx` a DIFFERENT hidden class from an ordinary one. Declared here so
|
|
396
|
+
* every `ctx` has one shape; `undefined` when not instrumented.
|
|
397
|
+
*/
|
|
398
|
+
_grammarCoverage?: ((id: string) => void) | undefined
|
|
399
|
+
/** Framework-internal trace sink — same shape rationale as `_grammarCoverage`. */
|
|
400
|
+
_grammarTrace?: {
|
|
401
|
+
write(event: {
|
|
402
|
+
id: string
|
|
403
|
+
phase: 'enter' | 'attempt' | 'selected' | 'success' | 'failure' | 'backtrack' | 'rollback'
|
|
404
|
+
offset: number
|
|
405
|
+
end?: number
|
|
406
|
+
}): void
|
|
407
|
+
} | undefined
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* The recovery value produced when a parse fails at a recoverable point (tolerant
|
|
412
|
+
* list recovery, or expect()). The span covers the skipped/missing input; expected
|
|
413
|
+
* lists what the parser wanted there.
|
|
414
|
+
*/
|
|
415
|
+
export type ParseError = {
|
|
416
|
+
readonly _tag: 'parseError'
|
|
417
|
+
readonly span: Span
|
|
418
|
+
readonly expected: string[]
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export type ParserMeta = {
|
|
422
|
+
/** Character codes / ranges that can start this parser (for choice dispatch) */
|
|
423
|
+
firstSet: FirstSet
|
|
424
|
+
/** Whether this parser can consume a newline character */
|
|
425
|
+
canMatchNewline: boolean
|
|
426
|
+
/** Whether this parser is marked as trivia (auto-skip) */
|
|
427
|
+
isTrivia: boolean
|
|
428
|
+
/** User-defined labels for labeled trivia arms (`label(name, parser)`). */
|
|
429
|
+
triviaKindLabels?: readonly string[]
|
|
430
|
+
/** Set only by `classifiedTrivia()`: each root-visible category is a separate
|
|
431
|
+
* grammar arm rather than an arbitrary label on a broad recognizer. */
|
|
432
|
+
rootTriviaClassified?: true
|
|
433
|
+
/** choice(): true when all alternative first sets are pairwise disjoint */
|
|
434
|
+
disjoint?: boolean
|
|
435
|
+
/**
|
|
436
|
+
* Grammar-level ambient trivia declared via `rules({ trivia }, factory)`. When
|
|
437
|
+
* a rule carrying this is parsed as an ENTRY (run()/parse()/compile with no
|
|
438
|
+
* more-local trivia already active), the framework installs it as `ctx.trivia`
|
|
439
|
+
* so it is ambient for the whole parse — "set once, inherited everywhere",
|
|
440
|
+
* including incremental parsing of a single rule. `parser({ trivia })` /
|
|
441
|
+
* `noTrivia` still override it locally. The compiled path bakes it as the
|
|
442
|
+
* seed `activeTrivia` for every rule in the map.
|
|
443
|
+
*/
|
|
444
|
+
grammarTrivia?: Combinator<unknown> | undefined
|
|
445
|
+
/**
|
|
446
|
+
* Grammar-level ambient scan-skip declared via `rules({ scanSkip }, factory)`.
|
|
447
|
+
* Mirrors `grammarTrivia`: stamped on every non-trivia rule, installed as
|
|
448
|
+
* `ctx.scanSkip` at the parse entry (and baked as the compiled seed) so a
|
|
449
|
+
* `scanTo`/`balanced` with no explicit `skip` consults it ambiently.
|
|
450
|
+
*/
|
|
451
|
+
grammarScanSkip?: Combinator<unknown>[] | undefined
|
|
452
|
+
/**
|
|
453
|
+
* Grammar-level host mode declared via `rules({ hostMode }, factory)`. Stamped on
|
|
454
|
+
* every rule, mirroring the two above. The macro reads it statically to choose what
|
|
455
|
+
* to EMIT; the interpreter routes dynamically and only reads it so `run()` can refuse
|
|
456
|
+
* a mismatched host once per parse. `'ast'` is the default and is never stamped.
|
|
457
|
+
*/
|
|
458
|
+
grammarHostMode?: 'ast' | 'cst' | undefined
|
|
459
|
+
/**
|
|
460
|
+
* Grammar-level line tracking declared via `rules({ trackLines: true }, factory)`.
|
|
461
|
+
* Stamped on every non-trivia rule so runtime compile and macro compile can emit
|
|
462
|
+
* a separate line-aware artifact from the same authored grammar source.
|
|
463
|
+
*/
|
|
464
|
+
grammarTrackLines?: true | undefined
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** A first set is either "any" (unknown/unbounded) or a list of char code ranges */
|
|
468
|
+
export type FirstSet =
|
|
469
|
+
| { kind: 'any' }
|
|
470
|
+
| { kind: 'ranges'; ranges: CharRange[] }
|
|
471
|
+
| { kind: 'empty' }
|
|
472
|
+
|
|
473
|
+
export type CharRange = { lo: number; hi: number }
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Determines how a non-disjoint choice dispatches at runtime/compile-time.
|
|
477
|
+
*
|
|
478
|
+
* greedyClassify: one regex arm subsumes all literal arms — run the regex once,
|
|
479
|
+
* classify the result with string equality. Single parse call, no backtracking.
|
|
480
|
+
* literalsLongestFirst: all arms are literals — try from longest to shortest, no regex,
|
|
481
|
+
* no ambiguity, no backtracking.
|
|
482
|
+
* firstMatch: PEG fallback — try each arm in order; arms with autoNot[] get an inline
|
|
483
|
+
* rejection check so a later arm can "win" without explicit not().
|
|
484
|
+
* sharedPrefix: EVERY arm is a bare `sequence(...)` beginning with the SAME concrete
|
|
485
|
+
* leading literal/regex (a "left factor"). The compiler parses that
|
|
486
|
+
* prefix ONCE, then tries each arm's residual terms in PEG order from
|
|
487
|
+
* the shared end position — no re-parse of the prefix per arm. PEG
|
|
488
|
+
* priority and byte-identical value/CST/diagnostics are preserved; the
|
|
489
|
+
* interpreter treats it exactly as `firstMatch`. Opt-in like
|
|
490
|
+
* greedyClassify (auto-detected only for the narrow shape it can prove).
|
|
491
|
+
*/
|
|
492
|
+
export type ChoiceStrategy =
|
|
493
|
+
| { tag: 'greedyClassify'; superIndex: number }
|
|
494
|
+
| { tag: 'literalsLongestFirst'; sortedIndices: number[] }
|
|
495
|
+
| { tag: 'firstMatch' }
|
|
496
|
+
| { tag: 'sharedPrefix'; prefix: Combinator<unknown>; members: number[] }
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Used only by the 'firstMatch' fallback strategy. Describes what char/string at
|
|
500
|
+
* the END of an arm's match should cause that arm to be rejected so the next arm
|
|
501
|
+
* is tried. Auto-derived from sibling alternatives at construction time.
|
|
502
|
+
*/
|
|
503
|
+
export type AutoNotCheck =
|
|
504
|
+
| { kind: 'firstSet'; set: FirstSet }
|
|
505
|
+
| { kind: 'startsWith'; value: string }
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* A choice arm with an optional gate predicate. When a gate is provided,
|
|
509
|
+
* it is evaluated (cheaply, without parsing) before the arm is attempted.
|
|
510
|
+
* If the gate returns false the arm is skipped entirely.
|
|
511
|
+
*
|
|
512
|
+
* Usage: choice({ gate: s => (s as Ctx).inFn, combinator: returnKw }, ident)
|
|
513
|
+
*/
|
|
514
|
+
export type GatedArm<T = unknown> = {
|
|
515
|
+
gate: (state: unknown) => boolean
|
|
516
|
+
combinator: Combinator<T>
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* WHAT `compile()` HANDS BACK — the contract, not one engine's return type.
|
|
521
|
+
*
|
|
522
|
+
* This lives with the rest of the library's types rather than inside a lowering
|
|
523
|
+
* because it is the shape BOTH lowerings answer to: `table/compile.ts` returns it
|
|
524
|
+
* today and is what `src/index.ts` exports as `compile`. It started in
|
|
525
|
+
* `compiler/codegen.ts`, which made the table import its own public contract from
|
|
526
|
+
* the engine the table replaced — backwards, and a reason the engine could not be
|
|
527
|
+
* deleted.
|
|
528
|
+
*/
|
|
529
|
+
export type CompiledParser<T> = {
|
|
530
|
+
parse(input: string, pos?: number): ParseResult<T>
|
|
531
|
+
/** Like parse(), but with a caller-supplied ParseContext (e.g. `_triviaLog` for CST grammars). */
|
|
532
|
+
parseWithContext(input: string, ctx: ParseContext, pos?: number): ParseResult<T>
|
|
533
|
+
/**
|
|
534
|
+
* Like parse(), but activates the error-collection channel. Recovery points
|
|
535
|
+
* (expect()) collect their ParseErrors into result.errors instead of only
|
|
536
|
+
* embedding them as values. Always returns ParseOk — top-level failures are
|
|
537
|
+
* still ParseFail.
|
|
538
|
+
*/
|
|
539
|
+
parseWithErrors(input: string, pos?: number): ParseResult<T> & { errors: ParseError[] }
|
|
540
|
+
/** The generated source (for inspection / future source maps) */
|
|
541
|
+
source: string
|
|
542
|
+
/**
|
|
543
|
+
* A self-contained JS expression (IIFE) that evaluates to a parse function.
|
|
544
|
+
* Safe to inline directly into transformed source — no external references
|
|
545
|
+
* except for runtime-fallback parsers embedded via closures.
|
|
546
|
+
* Returns null if the parser cannot be fully inlined (e.g. contains user
|
|
547
|
+
* closures that can't be serialized).
|
|
548
|
+
*/
|
|
549
|
+
inlineExpression: string | null
|
|
550
|
+
/**
|
|
551
|
+
* WHY `inlineExpression` IS NULL — one named reason per cause, present only
|
|
552
|
+
* when the artifact could not be PRINTED. A null with no reason is the failure
|
|
553
|
+
* this field exists to make impossible: the caller's fallback is "leave the
|
|
554
|
+
* grammar interpreted", which is a ~5x silent perf regression, so the reason
|
|
555
|
+
* has to reach a warning rather than being inferred from a null.
|
|
556
|
+
*
|
|
557
|
+
* Empty/absent means printable. Set by the table lowering; the source lowering's
|
|
558
|
+
* own unprintable cases predate this channel and still return a bare null.
|
|
559
|
+
*/
|
|
560
|
+
runtimeOnly?: readonly string[]
|
|
561
|
+
/** Present only when compiled with `{ coverage: true }`. */
|
|
562
|
+
coverageDefinitions?: readonly import('./compiler/grammar-coverage-ids.ts').GrammarCoverageDefinition[]
|
|
563
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parseman's version — stamped into every generated-artifact banner and used as the
|
|
3
|
+
* ARTIFACT VERSION LOCK (see `docs/design/artifact-format.md`).
|
|
4
|
+
*
|
|
5
|
+
* ── ARTIFACTS ARE VERSION-LOCKED ────────────────────────────────────────────────
|
|
6
|
+
* A grammar is compiled AND fused/linked by the SAME parseman version. Parseman does
|
|
7
|
+
* NOT read a compiled artifact produced by a different version. The compiled-artifact
|
|
8
|
+
* format (`firstSetRecipes`, `LinkablePieces`, the fused-body shape, …) may therefore
|
|
9
|
+
* change freely between versions and carries NO back-compat shim: `fusedBody` refuses
|
|
10
|
+
* to link a serialized artifact stamped with a different version, and there is no
|
|
11
|
+
* "legacy format" read path. If you find yourself adding one, STOP — it is dead code.
|
|
12
|
+
*
|
|
13
|
+
* Kept in sync with `package.json` by `test/unit/version-sync.test.ts`, which fails
|
|
14
|
+
* the build if this constant drifts from the published version.
|
|
15
|
+
*/
|
|
16
|
+
export const PARSEMAN_VERSION = '0.47.0'
|