parseman 0.24.0 → 0.25.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 +1 -1
- package/dist/cst/relative-spans.d.ts +32 -0
- package/dist/cst/relative-spans.d.ts.map +1 -1
- package/dist/functional/doc.d.ts +53 -3
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/index.cjs +319 -100
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +319 -100
- package/dist/index.js.map +4 -4
- package/dist/plugin/index.cjs.map +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/spec/index.cjs +67 -6
- package/dist/spec/index.cjs.map +3 -3
- package/dist/spec/index.d.ts +10 -2
- package/dist/spec/index.d.ts.map +1 -1
- package/dist/spec/index.js +67 -6
- package/dist/spec/index.js.map +3 -3
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/spec/railroad.d.ts +12 -0
- package/dist/spec/railroad.d.ts.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ Parséman includes benchmarks against several JavaScript/TypeScript parser libra
|
|
|
110
110
|
|
|
111
111
|
**When parsing to JS values** — objects, row arrays, AST nodes — **Parséman's macro build is the fastest general-purpose JS parser we benchmark**, beating [Peggy](https://peggyjs.org/), [Parsimmon](https://github.com/jneen/parsimmon), [Chevrotain](https://chevrotain.io/), [Nearley](https://nearley.js.org/), and [Jison](https://github.com/zaach/jison) at every grammar and size. The only thing that edges it out is a purpose-built native like `JSON.parse`; for anything that *doesn't* have a built-in, Parséman is the one to beat.
|
|
112
112
|
|
|
113
|
-
For **syntax tree building**, the compiled CST path (macro build) beats [Lezer](https://lezer.codemirror.net/) on the JSON CST fixture too — while producing a richer object tree with spans and trivia. For **incremental re-parse**,
|
|
113
|
+
For **syntax tree building**, the compiled CST path (macro build) beats [Lezer](https://lezer.codemirror.net/) on the JSON CST fixture too — while producing a richer object tree with spans and trivia. For **incremental re-parse**, Parséman's `parseDoc` stores parent-relative spans so in-place value edits are ~110× faster than a full reparse and ~20× ahead of Lezer; structural edits (inserting/removing a whole list element) reuse the collection's untouched tail and land within a few × of Lezer's buffer reuse rather than at full-reparse cost. Full breakdown in the [benchmarks guide](https://matthew-dean.github.io/parseman/guide/benchmarks).
|
|
114
114
|
|
|
115
115
|
Measured on Apple M4 Pro. Bars show µs per parse — shorter is faster. Refresh: `pnpm bench:svg` (benchmarks chart parsers and updates `assets/bench-*.svg`).
|
|
116
116
|
|
|
@@ -40,6 +40,37 @@ export declare function absoluteSpanAt(root: RelNode, path: readonly number[]):
|
|
|
40
40
|
start: number;
|
|
41
41
|
end: number;
|
|
42
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* A CST child as far as span projection cares: a nested span + optional children.
|
|
45
|
+
* `children` is typed loosely (`unknown[]`) so the real heterogeneous CST unions
|
|
46
|
+
* (nodes, leaves, error nodes — a leaf has no `children`) satisfy it directly.
|
|
47
|
+
*/
|
|
48
|
+
type Spanned = {
|
|
49
|
+
readonly span: {
|
|
50
|
+
readonly start: number;
|
|
51
|
+
readonly end: number;
|
|
52
|
+
};
|
|
53
|
+
readonly children?: readonly unknown[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Rewrite a CST subtree's spans to be RELATIVE to `parentBase` (the absolute
|
|
57
|
+
* start of the node's parent; root base = 0). Each child's own children are
|
|
58
|
+
* relativized against *this* node's absolute start. Preserves every other field
|
|
59
|
+
* (`_tag`, `type`, `state`, leaf `value`, …) by shallow spread.
|
|
60
|
+
*/
|
|
61
|
+
export declare function relativizeCST<T extends Spanned>(node: T, parentBase?: number): T;
|
|
62
|
+
/** Reconstruct absolute CST spans from a relative subtree. Inverse of `relativizeCST`. */
|
|
63
|
+
export declare function absolutizeCST<T extends Spanned>(node: T, parentBase?: number): T;
|
|
64
|
+
/**
|
|
65
|
+
* Absolute span of the CST node at `path` (child indices from the root),
|
|
66
|
+
* accumulating the base as it descends — O(path length), no full absolutize.
|
|
67
|
+
* The relative-form cursor for a positioned CST: query one node's absolute
|
|
68
|
+
* position without materializing the whole tree.
|
|
69
|
+
*/
|
|
70
|
+
export declare function absoluteSpanCST(root: Spanned, path: readonly number[]): {
|
|
71
|
+
start: number;
|
|
72
|
+
end: number;
|
|
73
|
+
};
|
|
43
74
|
/** Naive absolute reshift (baseline): shift every offset >= `at` by `delta`. */
|
|
44
75
|
export declare function shiftAbsolute(node: AbsNode, at: number, delta: number): AbsNode;
|
|
45
76
|
/**
|
|
@@ -53,4 +84,5 @@ export declare function shiftAbsolute(node: AbsNode, at: number, delta: number):
|
|
|
53
84
|
export declare function applyEdit(root: RelNode, at: number, delta: number, stats?: {
|
|
54
85
|
allocated: number;
|
|
55
86
|
}): RelNode;
|
|
87
|
+
export {};
|
|
56
88
|
//# sourceMappingURL=relative-spans.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative-spans.d.ts","sourceRoot":"","sources":["../../src/cst/relative-spans.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,gEAAgE;AAChE,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AAED,qFAAqF;AACrF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,SAAI,GAAG,OAAO,CAMjE;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,SAAI,GAAG,OAAO,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUrG;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ/E;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAGT"}
|
|
1
|
+
{"version":3,"file":"relative-spans.d.ts","sourceRoot":"","sources":["../../src/cst/relative-spans.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,gEAAgE;AAChE,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AAED,qFAAqF;AACrF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AAED,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,SAAI,GAAG,OAAO,CAMjE;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,SAAI,GAAG,OAAO,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUrG;AAYD;;;;GAIG;AACH,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CACvC,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,SAAI,GAAG,CAAC,CAO3E;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,SAAI,GAAG,CAAC,CAO3E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUtG;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ/E;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAGT"}
|
package/dist/functional/doc.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Incremental parse document — incremental re-parse over a rules() registry.
|
|
3
3
|
*/
|
|
4
|
-
import type { ParseContext, ParseFail, ParseResult } from '../types.ts';
|
|
4
|
+
import type { Combinator, ParseContext, ParseFail, ParseResult } from '../types.ts';
|
|
5
5
|
import type { NodeLike, CSTLeaf, CSTError } from '../cst/types.ts';
|
|
6
6
|
/** A single compiled (or interpreted) rule: parse from `pos`, producing node `N`. */
|
|
7
7
|
export type RuleFn<N> = (input: string, pos: number, ctx: ParseContext) => ParseResult<N>;
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Rule name → parser. Each entry is either a bare parse function or a
|
|
10
|
+
* `Combinator` (what `rules()` returns). Passing the `rules()` combinators
|
|
11
|
+
* directly lets `.edit()` inspect the grammar — required for **sound** structural
|
|
12
|
+
* list-reuse (see `structuralReuse`): only a rule the grammar proves is a genuine
|
|
13
|
+
* repetition is ever spliced. A bare-function registry still parses correctly; it
|
|
14
|
+
* just can't be structurally reused (the splice is skipped, never guessed).
|
|
15
|
+
*/
|
|
16
|
+
export type Registry<N> = Record<string, RuleFn<N> | Combinator<N>>;
|
|
10
17
|
export type ParseDocOptions<N extends NodeLike> = {
|
|
11
18
|
/** Initial grammar state threaded into ctx.state for the root parse. */
|
|
12
19
|
state?: unknown;
|
|
@@ -23,11 +30,48 @@ export type ParseDocOptions<N extends NodeLike> = {
|
|
|
23
30
|
* own builders (eval mode).
|
|
24
31
|
*/
|
|
25
32
|
build?: ParseContext['build'];
|
|
33
|
+
/**
|
|
34
|
+
* Enable structural list-reuse: on a length-changing *structural* edit (adding
|
|
35
|
+
* or removing a whole element in a collection) that would otherwise force a full
|
|
36
|
+
* reparse, reparse only the disturbed span and reuse the collection's untouched
|
|
37
|
+
* tail elements by identity — turning an insert near the top of a large list from
|
|
38
|
+
* O(list) into O(edit + trailing siblings).
|
|
39
|
+
*
|
|
40
|
+
* OFF by default because it is sound only when a rule whose CST children form a
|
|
41
|
+
* homogeneous, separator-delimited element list is a genuine REPETITION
|
|
42
|
+
* (`many` / `sepBy` / `oneOrMore`), not a fixed-arity sequence of same-typed
|
|
43
|
+
* tokens (e.g. `Triple = Num ',' Num ',' Num`) — the two are structurally
|
|
44
|
+
* indistinguishable without the grammar, and splicing the latter would accept an
|
|
45
|
+
* element count it shouldn't. Turn it on when your list rules are true
|
|
46
|
+
* repetitions (the common case: JSON arrays/objects, CSS value lists, argument
|
|
47
|
+
* lists). Every splice is still guarded (exact tiling + lookahead probe +
|
|
48
|
+
* stateless-tail check) and falls back to a full, correct reparse when unproven;
|
|
49
|
+
* the flag only authorises *attempting* the reuse.
|
|
50
|
+
*/
|
|
51
|
+
structuralReuse?: boolean;
|
|
26
52
|
};
|
|
27
53
|
export interface ParseDoc<N extends NodeLike> {
|
|
54
|
+
/**
|
|
55
|
+
* The parse tree with PARENT-RELATIVE spans — each node's `span` is relative to
|
|
56
|
+
* its parent's start (root base 0). This is the shareable representation: a
|
|
57
|
+
* length-changing `.edit()` keeps every untouched subtree shared by identity,
|
|
58
|
+
* and reading the tree is O(1) (no offset rewrite). For absolute positions use
|
|
59
|
+
* the O(depth) cursor `spanAt(path)`, or `absolutizeCST(doc.tree)` to
|
|
60
|
+
* materialize the whole absolute tree. A fresh non-incremental `node().parse()`
|
|
61
|
+
* result is unchanged — still absolute.
|
|
62
|
+
*/
|
|
28
63
|
readonly tree: N | null;
|
|
29
64
|
readonly errors: ParseFail[];
|
|
30
65
|
readonly input: string;
|
|
66
|
+
/**
|
|
67
|
+
* Absolute span of the node at `path` (child indices from the root) — O(depth),
|
|
68
|
+
* without materializing the absolute tree. The projection cursor for the
|
|
69
|
+
* relative representation; use it for spot queries on a large incremental doc.
|
|
70
|
+
*/
|
|
71
|
+
spanAt(path: readonly number[]): {
|
|
72
|
+
start: number;
|
|
73
|
+
end: number;
|
|
74
|
+
};
|
|
31
75
|
/**
|
|
32
76
|
* Incrementally re-parse after a text change. `from`/`to` are byte offsets in
|
|
33
77
|
* the OLD input; `replacement` fills that range (editor change-event shape).
|
|
@@ -47,6 +91,12 @@ export interface ParseDoc<N extends NodeLike> {
|
|
|
47
91
|
* probe results with.
|
|
48
92
|
*/
|
|
49
93
|
export declare function structurallyEqual(a: unknown, b: unknown): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* The relative (parent-offset) tree backing a doc. Currently identical to the
|
|
96
|
+
* public `doc.tree` (which is relative); kept as a named internal handle for the
|
|
97
|
+
* reuse-metric tests, which assert on the shareable representation explicitly.
|
|
98
|
+
*/
|
|
99
|
+
export declare function relTreeOf<N extends NodeLike>(doc: ParseDoc<N>): N | null;
|
|
50
100
|
/**
|
|
51
101
|
* Parse `input` from `rootRule` and wrap the result in a ParseDoc that can
|
|
52
102
|
* be incrementally re-parsed via `.edit()`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../src/functional/doc.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"doc.d.ts","sourceRoot":"","sources":["../../src/functional/doc.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAA;AACpG,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAGlE,qFAAqF;AACrF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,CAAA;AAEzF;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;AAiEnE,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,QAAQ,IAAI;IAChD,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,GAAG,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACzE;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;IAC7B;;;;;;;;;;;;;;;;;OAiBG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,QAAQ;IAC1C;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/D;;;;;;;;;OASG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;CACjE;AA6TD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAsBjE;AAwND;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAExE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EACzC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,eAAe,CAAC,CAAC,CAAM,GAC5B,QAAQ,CAAC,CAAC,CAAC,CAWb"}
|