parseman 0.16.0 → 0.17.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/dist/combinators/first-set.d.ts +14 -0
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts +28 -0
- package/dist/compiler/ir-serialize.d.ts.map +1 -0
- package/dist/compiler/linker.d.ts +9 -0
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/index.cjs +329 -112
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +329 -112
- package/dist/index.js.map +4 -4
- package/dist/plugin/index.cjs +647 -108
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +647 -108
- package/dist/plugin/index.js.map +4 -4
- package/package.json +1 -1
|
@@ -22,4 +22,18 @@ export declare function matchesEmpty(p: Combinator<unknown>, seen?: Set<Combinat
|
|
|
22
22
|
* and silently breaks first-char dispatch — see the InterpolatedSelector bug.)
|
|
23
23
|
*/
|
|
24
24
|
export declare function sequenceFirstSet(parsers: readonly Combinator<unknown>[]): FirstSet;
|
|
25
|
+
/**
|
|
26
|
+
* Deep first-set that RESOLVES `lazy`/`ref` combinators to their targets. The
|
|
27
|
+
* combinators bake `_meta.firstSet` at CONSTRUCTION, when a `ref()` still reads
|
|
28
|
+
* `any()` (define() never updates it) — so a `choice`/`sequence` built over refs
|
|
29
|
+
* caches a spuriously-`any` first-set and loses first-char dispatch. Recomputing
|
|
30
|
+
* here, following refs, recovers the real set. Over-approximates on cycles /
|
|
31
|
+
* unknown constructs (returns `any`) — always sound: a wider set only means "try
|
|
32
|
+
* this arm for more first chars", never skips a real match.
|
|
33
|
+
*
|
|
34
|
+
* SOUND ONLY where refs are FINAL (monolithic compile). Under compose OVERRIDE a
|
|
35
|
+
* referenced rule can be replaced with a WIDER first-set, so a baked deep set
|
|
36
|
+
* would wrongly skip valid input — the compose path defers dispatch to fuse time.
|
|
37
|
+
*/
|
|
38
|
+
export declare function firstSetOf(p: Combinator<unknown>, seen?: Set<Combinator<unknown>>): FirstSet;
|
|
25
39
|
//# sourceMappingURL=first-set.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"first-set.d.ts","sourceRoot":"","sources":["../../src/combinators/first-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAE7E,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAKxD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAS5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE/C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAE1D;AAED,wBAAgB,GAAG,IAAI,QAAQ,CAE9B;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAEhC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAmCxG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,CAOlF"}
|
|
1
|
+
{"version":3,"file":"first-set.d.ts","sourceRoot":"","sources":["../../src/combinators/first-set.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAE7E,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAKxD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAS5D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE/C;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAE1D;AAED,wBAAgB,GAAG,IAAI,QAAQ,CAE9B;AAED,wBAAgB,KAAK,IAAI,QAAQ,CAEhC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,OAAO,CAmCxG;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,QAAQ,CAOlF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,GAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAa,GAAG,QAAQ,CAoCvG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize a compiled rule map BACK to a compact combinator-construction source
|
|
3
|
+
* expression — the "IR" a composed grammar carries instead of ~1MB of fully
|
|
4
|
+
* lowered `_r_<Name>` function source. At fuse time the expression is evaluated
|
|
5
|
+
* (with the combinator constructors in scope) to reconstruct the rule map, then
|
|
6
|
+
* re-lowered via `compileLinkable` — identical behaviour, a fraction of the bytes.
|
|
7
|
+
*
|
|
8
|
+
* The output mirrors how a grammar is WRITTEN, not how it lowers:
|
|
9
|
+
* - a rule reference (`g.Foo`, a `lazy` carrying `_ruleName`) → `g["Foo"]`
|
|
10
|
+
* - a sub-combinator shared by identity (referenced ≥2×, e.g. a `balanced` const
|
|
11
|
+
* reused across rules) → a hoisted `const _s<N> = …`, referenced by name, so it
|
|
12
|
+
* stays shared through the round trip (and `compileLinkable` re-hoists it)
|
|
13
|
+
* - a self-referential combinator (`balanced`'s internal `self = ref()`) → a
|
|
14
|
+
* `ref()` + `.define()` closure, the same shape the library combinator emits
|
|
15
|
+
* - `transform`/`node` callbacks → their captured source (`fnSrc`/`buildSrc`)
|
|
16
|
+
*
|
|
17
|
+
* Returns null if the map can't be faithfully serialized (a callback without
|
|
18
|
+
* source, or an unsupported construct) — the caller then keeps the lowered source.
|
|
19
|
+
*/
|
|
20
|
+
import type { Combinator } from '../types.ts';
|
|
21
|
+
type Comb = Combinator<unknown>;
|
|
22
|
+
export declare function serializeRuleMap(ruleMap: ReadonlyArray<readonly [string, Comb]>): string | null;
|
|
23
|
+
/** Reconstruct a rule map from serialized IR (the inverse of `serializeRuleMap`) —
|
|
24
|
+
* evaluate the combinator-construction expression with every constructor in scope.
|
|
25
|
+
* Used at fuse time (runtime linker + build-time plugin) to re-lower carried IR. */
|
|
26
|
+
export declare function evalRuleMapIR(ir: string): Array<[string, Comb]>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=ir-serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ir-serialize.d.ts","sourceRoot":"","sources":["../../src/compiler/ir-serialize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,aAAa,CAAA;AAgBxD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;AA0C/B,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,GAC9C,MAAM,GAAG,IAAI,CAUf;AAED;;oFAEoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAgC/D"}
|
|
@@ -40,5 +40,14 @@ export declare function fuseRules(pieces: LinkablePieces[]): Record<string, Fuse
|
|
|
40
40
|
* artifact carries runtime-only callback functions.
|
|
41
41
|
*/
|
|
42
42
|
export declare function emitFusedSource(pieces: LinkablePieces[]): string;
|
|
43
|
+
/** The compact IR form a grammar carries instead of its lowered rule source: the
|
|
44
|
+
* combinator-construction expression, re-lowered here at fuse time. */
|
|
45
|
+
export type IRPiece = {
|
|
46
|
+
ns: string;
|
|
47
|
+
ir: string;
|
|
48
|
+
};
|
|
49
|
+
/** Materialize a carried item to full `LinkablePieces`: an IR piece is evaluated
|
|
50
|
+
* back to a rule map and re-lowered; a full piece passes through. */
|
|
51
|
+
export declare function materializePiece(p: LinkablePieces | IRPiece): LinkablePieces;
|
|
43
52
|
export declare function compose(items: Array<LinkablePieces | Record<string, unknown>>): Record<string, FusedRule>;
|
|
44
53
|
//# sourceMappingURL=linker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linker.d.ts","sourceRoot":"","sources":["../../src/compiler/linker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linker.d.ts","sourceRoot":"","sources":["../../src/compiler/linker.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,aAAa,CAAA;AAavD,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,EAC7C,EAAE,CAAC,EAAE,MAAM,GACV,cAAc,CAIhB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,EAChC,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,EACpC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACpC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,EAC9B,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAIT;AAED,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACzB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAA;AAE3E;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAClB,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,EAC7D,KAAK,EAAE,MAAM,EAAE,GACd,cAAc,CA2BhB;AAmED;qFACqF;AACrF,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAI7E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAMhE;AAqBD;uEACuE;AACvE,MAAM,MAAM,OAAO,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAQhD;qEACqE;AACrE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,GAAG,cAAc,CAK5E;AAeD,wBAAgB,OAAO,CACrB,KAAK,EAAE,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACrD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAK3B"}
|
package/dist/index.cjs
CHANGED
|
@@ -181,6 +181,54 @@ function sequenceFirstSet(parsers) {
|
|
|
181
181
|
}
|
|
182
182
|
return fs;
|
|
183
183
|
}
|
|
184
|
+
function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
|
|
185
|
+
if (seen.has(p)) return any();
|
|
186
|
+
seen.add(p);
|
|
187
|
+
const fs = (c) => firstSetOf(c, seen);
|
|
188
|
+
const d = p._def;
|
|
189
|
+
switch (d.tag) {
|
|
190
|
+
case "literal":
|
|
191
|
+
case "regex":
|
|
192
|
+
case "keywords":
|
|
193
|
+
return p._meta.firstSet;
|
|
194
|
+
// terminals: no refs, cached set is exact
|
|
195
|
+
case "lazy":
|
|
196
|
+
try {
|
|
197
|
+
return fs(d.thunk());
|
|
198
|
+
} catch {
|
|
199
|
+
return any();
|
|
200
|
+
}
|
|
201
|
+
case "choice": {
|
|
202
|
+
let out = empty();
|
|
203
|
+
for (const arm of d.parsers) out = union(out, fs(arm));
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
case "sequence": {
|
|
207
|
+
let out = empty();
|
|
208
|
+
for (const term of d.parsers) {
|
|
209
|
+
out = union(out, fs(term));
|
|
210
|
+
if (!matchesEmpty(term)) return out;
|
|
211
|
+
}
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
case "oneOrMore":
|
|
215
|
+
case "many":
|
|
216
|
+
case "optional":
|
|
217
|
+
case "transform":
|
|
218
|
+
case "label":
|
|
219
|
+
case "trivia":
|
|
220
|
+
case "node":
|
|
221
|
+
case "grammar":
|
|
222
|
+
case "expect":
|
|
223
|
+
return fs(d.parser);
|
|
224
|
+
case "sepBy":
|
|
225
|
+
return fs(d.parser);
|
|
226
|
+
case "skip":
|
|
227
|
+
return fs(d.main);
|
|
228
|
+
default:
|
|
229
|
+
return p._meta.firstSet;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
184
232
|
function mergeRanges(ranges) {
|
|
185
233
|
if (ranges.length === 0) return [];
|
|
186
234
|
const sorted = [...ranges].sort((a, b) => a.lo - b.lo);
|
|
@@ -3121,16 +3169,12 @@ function namedFnPrelude() {
|
|
|
3121
3169
|
function pushNamedFnDecl(ctx, fnName, bodyStmts, valueVar, endVar) {
|
|
3122
3170
|
ctx.namedFnDecls.push([
|
|
3123
3171
|
`function ${fnName}(input, _pos, _ctx) {`,
|
|
3124
|
-
` let _pfok = false, _pfv, _pfe = _pos`,
|
|
3125
3172
|
` _pfail: {`,
|
|
3126
3173
|
...reindentStmts(bodyStmts, 2),
|
|
3127
|
-
`
|
|
3128
|
-
`
|
|
3129
|
-
` _pfok = true`,
|
|
3174
|
+
` ${NAMED_FN_END} = ${endVar}`,
|
|
3175
|
+
` return ${valueVar}`,
|
|
3130
3176
|
` }`,
|
|
3131
|
-
`
|
|
3132
|
-
` ${NAMED_FN_END} = _pfe`,
|
|
3133
|
-
` return _pfv`,
|
|
3177
|
+
` return ${NAMED_FN_FAIL}`,
|
|
3134
3178
|
`}`
|
|
3135
3179
|
].join("\n"));
|
|
3136
3180
|
}
|
|
@@ -3831,11 +3875,16 @@ function emitFirstMatch(def, ctx, pos) {
|
|
|
3831
3875
|
const atStart = failsAtStart(p);
|
|
3832
3876
|
const staticFx = armStaticExpected(ctx, p);
|
|
3833
3877
|
const deferRuleName = ctx.deferFirstSetRefs ? p._ruleName : void 0;
|
|
3834
|
-
const fsGuard = deferRuleName !== void 0 ? `/*@FS:${deferRuleName}:${codeV}@*/true` : needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) :
|
|
3878
|
+
const fsGuard = deferRuleName !== void 0 ? `/*@FS:${deferRuleName}:${codeV}@*/true` : needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) : (() => {
|
|
3879
|
+
if (p._meta.firstSet.kind !== "any" || matchesEmpty(p)) return null;
|
|
3880
|
+
const deep = firstSetOf(p);
|
|
3881
|
+
return deep.kind === "ranges" ? firstSetCond(codeV, deep) : null;
|
|
3882
|
+
})();
|
|
3835
3883
|
let gateCond = null;
|
|
3836
3884
|
if (gate) {
|
|
3837
3885
|
const gateIdx = ctx.mapFns.length;
|
|
3838
3886
|
ctx.mapFns.push(gate);
|
|
3887
|
+
ctx.mapFnSrcs.push(null);
|
|
3839
3888
|
gateCond = `${mfRef(ctx)}[${gateIdx}](_ctx.state)`;
|
|
3840
3889
|
}
|
|
3841
3890
|
const skipCond = gateCond ? `!${resOkV} && ${gateCond}` : `!${resOkV}`;
|
|
@@ -3894,13 +3943,21 @@ function emitNonDisjoint(def, strategy, allExpected, ctx, pos) {
|
|
|
3894
3943
|
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos);
|
|
3895
3944
|
return emitFirstMatch(def, ctx, pos);
|
|
3896
3945
|
}
|
|
3946
|
+
function pushMapFn(ctx, fn, src) {
|
|
3947
|
+
if (src !== null && ctx.mapFns.length === ctx.mapFnSrcs.length) {
|
|
3948
|
+
const hit = ctx.mapFnSrcs.indexOf(src);
|
|
3949
|
+
if (hit !== -1) return hit;
|
|
3950
|
+
}
|
|
3951
|
+
const idx = ctx.mapFns.length;
|
|
3952
|
+
ctx.mapFns.push(fn);
|
|
3953
|
+
ctx.mapFnSrcs.push(src);
|
|
3954
|
+
return idx;
|
|
3955
|
+
}
|
|
3897
3956
|
function emitTransformChain(p, baseValue, endV, startPos, ctx) {
|
|
3898
3957
|
const def = p._def;
|
|
3899
3958
|
if (def.tag === "transform") {
|
|
3900
3959
|
const innerR = emitTransformChain(def.parser, baseValue, endV, startPos, ctx);
|
|
3901
|
-
const fnIdx = ctx.
|
|
3902
|
-
ctx.mapFns.push(def.fn);
|
|
3903
|
-
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
3960
|
+
const fnIdx = pushMapFn(ctx, def.fn, def.fnSrc ?? null);
|
|
3904
3961
|
const vv = v(ctx);
|
|
3905
3962
|
return {
|
|
3906
3963
|
stmts: [...innerR.stmts, `${ind(ctx)}const ${vv} = ${mfRef(ctx)}[${fnIdx}](${innerR.valueVar}, { start: ${startPos}, end: ${endV} })`],
|
|
@@ -4083,7 +4140,7 @@ function emitScanTo(def, ctx, pos) {
|
|
|
4083
4140
|
`${ind(ctx)}while (${curV} < input.length) {`
|
|
4084
4141
|
];
|
|
4085
4142
|
ctx.indent++;
|
|
4086
|
-
const probeCtx = { ...ctx, capturing: false };
|
|
4143
|
+
const probeCtx = { ...ctx, capturing: false, noHoist: true };
|
|
4087
4144
|
const { stmts: sentStmts, okVar: sentOk } = emitFallible(def.sentinel, probeCtx, curV);
|
|
4088
4145
|
stmts.push(...sentStmts, `${ind(ctx)}if (${sentOk}) { ${foundV} = true; break }`);
|
|
4089
4146
|
if (def.skip.length > 0) {
|
|
@@ -4274,6 +4331,32 @@ function emitExpect(def, ctx, pos) {
|
|
|
4274
4331
|
return { stmts, valueVar: valVar, endVar };
|
|
4275
4332
|
}
|
|
4276
4333
|
function emit(p, ctx, pos) {
|
|
4334
|
+
const usage = ctx.lazyUsage;
|
|
4335
|
+
if (usage && !ctx.noHoist && !ctx.capAsTrivia && !ctx.ruleNames?.has(p) && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && // Only hoist subtrees big enough that de-duplicating them beats the call
|
|
4336
|
+
// overhead. A tiny shared wrapper (e.g. `optional(literal(';'))`) inlines
|
|
4337
|
+
// faster than it calls and barely moves the byte count; the size explosion
|
|
4338
|
+
// is all in LARGE choices/sequences referenced from many positions.
|
|
4339
|
+
(usage.sizes.get(p) ?? 0) >= HOIST_MIN_SUBTREE) {
|
|
4340
|
+
const existing = ctx.namedParsers.get(p);
|
|
4341
|
+
if (existing !== void 0) return emitNamedFnCall(ctx, existing, pos);
|
|
4342
|
+
const fnName = `${nsp(ctx)}_pf${ctx.namedParsers.size}`;
|
|
4343
|
+
ctx.namedParsers.set(p, fnName);
|
|
4344
|
+
const savedIndent = ctx.indent;
|
|
4345
|
+
const savedFailLabel = ctx.failLabel;
|
|
4346
|
+
const savedRecord = ctx.recordFail;
|
|
4347
|
+
ctx.indent = 1;
|
|
4348
|
+
ctx.failLabel = "_pfail";
|
|
4349
|
+
ctx.recordFail = true;
|
|
4350
|
+
const r = emitDispatch(p, ctx, "_pos");
|
|
4351
|
+
ctx.indent = savedIndent;
|
|
4352
|
+
ctx.failLabel = savedFailLabel;
|
|
4353
|
+
ctx.recordFail = savedRecord;
|
|
4354
|
+
pushNamedFnDecl(ctx, fnName, r.stmts, r.valueVar, r.endVar);
|
|
4355
|
+
return emitNamedFnCall(ctx, fnName, pos);
|
|
4356
|
+
}
|
|
4357
|
+
return emitDispatch(p, ctx, pos);
|
|
4358
|
+
}
|
|
4359
|
+
function emitDispatch(p, ctx, pos) {
|
|
4277
4360
|
const def = p._def;
|
|
4278
4361
|
switch (def.tag) {
|
|
4279
4362
|
case "literal":
|
|
@@ -4319,9 +4402,7 @@ function emit(p, ctx, pos) {
|
|
|
4319
4402
|
};
|
|
4320
4403
|
}
|
|
4321
4404
|
}
|
|
4322
|
-
const fnIdx = ctx.
|
|
4323
|
-
ctx.mapFns.push(def.fn);
|
|
4324
|
-
ctx.mapFnSrcs.push(def.fnSrc ?? null);
|
|
4405
|
+
const fnIdx = pushMapFn(ctx, def.fn, def.fnSrc ?? null);
|
|
4325
4406
|
const mv = v(ctx, "_mapped");
|
|
4326
4407
|
return {
|
|
4327
4408
|
stmts: [
|
|
@@ -4386,6 +4467,7 @@ function emit(p, ctx, pos) {
|
|
|
4386
4467
|
case "guard": {
|
|
4387
4468
|
const fnIdx = ctx.mapFns.length;
|
|
4388
4469
|
ctx.mapFns.push(def.predicate);
|
|
4470
|
+
ctx.mapFnSrcs.push(null);
|
|
4389
4471
|
const vv = v(ctx);
|
|
4390
4472
|
return {
|
|
4391
4473
|
stmts: [
|
|
@@ -4400,6 +4482,7 @@ function emit(p, ctx, pos) {
|
|
|
4400
4482
|
const evIdx = ctx.mapFns.length;
|
|
4401
4483
|
const extra = def.extra;
|
|
4402
4484
|
ctx.mapFns.push((() => extra));
|
|
4485
|
+
ctx.mapFnSrcs.push(null);
|
|
4403
4486
|
const innerParser = def.parser;
|
|
4404
4487
|
if (!ctx.namedParsers.has(innerParser)) {
|
|
4405
4488
|
const fnName = `_wcf${ctx.namedParsers.size}`;
|
|
@@ -4519,9 +4602,58 @@ function childrenOf(def) {
|
|
|
4519
4602
|
return [];
|
|
4520
4603
|
}
|
|
4521
4604
|
}
|
|
4605
|
+
var HOISTABLE_TAGS = /* @__PURE__ */ new Set([
|
|
4606
|
+
"sequence",
|
|
4607
|
+
"choice",
|
|
4608
|
+
"many",
|
|
4609
|
+
"oneOrMore",
|
|
4610
|
+
"optional",
|
|
4611
|
+
"sepBy",
|
|
4612
|
+
"transform",
|
|
4613
|
+
"node",
|
|
4614
|
+
"not"
|
|
4615
|
+
]);
|
|
4616
|
+
function isHoistableTag(tag) {
|
|
4617
|
+
return HOISTABLE_TAGS.has(tag);
|
|
4618
|
+
}
|
|
4619
|
+
var HOIST_MIN_SUBTREE = 3;
|
|
4522
4620
|
function analyzeLazyUsage(root) {
|
|
4523
4621
|
return analyzeLazyUsageMulti([root]);
|
|
4524
4622
|
}
|
|
4623
|
+
function subtreeSizes(roots) {
|
|
4624
|
+
const sizes = /* @__PURE__ */ new Map();
|
|
4625
|
+
const sz = (p) => {
|
|
4626
|
+
const cached = sizes.get(p);
|
|
4627
|
+
if (cached !== void 0) return cached;
|
|
4628
|
+
const def = p._def;
|
|
4629
|
+
let s = 1;
|
|
4630
|
+
if (def.tag !== "lazy") {
|
|
4631
|
+
for (const child of childrenOf(def)) s += child._def.tag === "lazy" ? 1 : sz(child);
|
|
4632
|
+
}
|
|
4633
|
+
sizes.set(p, s);
|
|
4634
|
+
return s;
|
|
4635
|
+
};
|
|
4636
|
+
const visitedLazy = /* @__PURE__ */ new Set();
|
|
4637
|
+
const visit = (p) => {
|
|
4638
|
+
const def = p._def;
|
|
4639
|
+
if (def.tag === "lazy") {
|
|
4640
|
+
if (visitedLazy.has(p)) return;
|
|
4641
|
+
visitedLazy.add(p);
|
|
4642
|
+
let resolved;
|
|
4643
|
+
try {
|
|
4644
|
+
resolved = def.thunk();
|
|
4645
|
+
} catch {
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
visit(resolved);
|
|
4649
|
+
return;
|
|
4650
|
+
}
|
|
4651
|
+
sz(p);
|
|
4652
|
+
for (const child of childrenOf(def)) visit(child);
|
|
4653
|
+
};
|
|
4654
|
+
for (const root of roots) visit(root);
|
|
4655
|
+
return sizes;
|
|
4656
|
+
}
|
|
4525
4657
|
function analyzeLazyUsageMulti(roots) {
|
|
4526
4658
|
const counts = /* @__PURE__ */ new Map();
|
|
4527
4659
|
const recursive = /* @__PURE__ */ new Set();
|
|
@@ -4548,10 +4680,14 @@ function analyzeLazyUsageMulti(roots) {
|
|
|
4548
4680
|
active.delete(p);
|
|
4549
4681
|
return;
|
|
4550
4682
|
}
|
|
4683
|
+
if (isHoistableTag(def.tag)) {
|
|
4684
|
+
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
4685
|
+
}
|
|
4551
4686
|
for (const child of childrenOf(def)) walk2(child);
|
|
4552
4687
|
}
|
|
4553
|
-
|
|
4554
|
-
|
|
4688
|
+
const rootsArr = [...roots];
|
|
4689
|
+
for (const root of rootsArr) walk2(root);
|
|
4690
|
+
return { counts, recursive, sizes: subtreeSizes(rootsArr) };
|
|
4555
4691
|
}
|
|
4556
4692
|
function ruleDependencies(ruleMap) {
|
|
4557
4693
|
const nameOf = /* @__PURE__ */ new Map();
|
|
@@ -4877,6 +5013,172 @@ function buildInlineExpression(ctx, r, mapFnSources, buildSources) {
|
|
|
4877
5013
|
].join("\n");
|
|
4878
5014
|
}
|
|
4879
5015
|
|
|
5016
|
+
// src/combinators/scanTo.ts
|
|
5017
|
+
function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
5018
|
+
const meta = {
|
|
5019
|
+
firstSet: any(),
|
|
5020
|
+
canMatchNewline: true,
|
|
5021
|
+
isTrivia: false
|
|
5022
|
+
};
|
|
5023
|
+
return {
|
|
5024
|
+
_tag: "scanTo",
|
|
5025
|
+
_meta: meta,
|
|
5026
|
+
_def: { tag: "scanTo", sentinel, skip: skip2, orEOF },
|
|
5027
|
+
parse(input, pos, ctx) {
|
|
5028
|
+
let cur = pos;
|
|
5029
|
+
const probeCtx = {
|
|
5030
|
+
trackLines: ctx.trackLines,
|
|
5031
|
+
state: ctx.state,
|
|
5032
|
+
...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
|
|
5033
|
+
};
|
|
5034
|
+
const emit2 = (end) => {
|
|
5035
|
+
if (end > pos && cstCaptureActive(ctx)) {
|
|
5036
|
+
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
5037
|
+
pushCstLeaf(ctx, leaf);
|
|
5038
|
+
}
|
|
5039
|
+
};
|
|
5040
|
+
while (cur < input.length) {
|
|
5041
|
+
const s = sentinel.parse(input, cur, probeCtx);
|
|
5042
|
+
if (s.ok) {
|
|
5043
|
+
emit2(cur);
|
|
5044
|
+
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5045
|
+
}
|
|
5046
|
+
let advanced = false;
|
|
5047
|
+
for (const skipper of skip2) {
|
|
5048
|
+
const r = skipper.parse(input, cur, probeCtx);
|
|
5049
|
+
if (r.ok && r.span.end > cur) {
|
|
5050
|
+
cur = r.span.end;
|
|
5051
|
+
advanced = true;
|
|
5052
|
+
break;
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
if (!advanced) cur++;
|
|
5056
|
+
}
|
|
5057
|
+
if (orEOF) {
|
|
5058
|
+
emit2(cur);
|
|
5059
|
+
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5060
|
+
}
|
|
5061
|
+
const sentDef = sentinel._def;
|
|
5062
|
+
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|
|
5063
|
+
return { ok: false, expected, span: { start: pos, end: cur } };
|
|
5064
|
+
}
|
|
5065
|
+
};
|
|
5066
|
+
}
|
|
5067
|
+
function balanced(open, close, options = {}) {
|
|
5068
|
+
const self = ref();
|
|
5069
|
+
const skips = options.skip ?? [];
|
|
5070
|
+
const stop = /* @__PURE__ */ new Set([open, close]);
|
|
5071
|
+
let bounded = true;
|
|
5072
|
+
for (const sk of skips) {
|
|
5073
|
+
const cs = firstSetClassChars(sk);
|
|
5074
|
+
if (cs === null) {
|
|
5075
|
+
bounded = false;
|
|
5076
|
+
break;
|
|
5077
|
+
}
|
|
5078
|
+
for (const ch of cs) stop.add(ch);
|
|
5079
|
+
}
|
|
5080
|
+
const cls = [...stop].map(escapeClassChar).join("");
|
|
5081
|
+
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
5082
|
+
const inner = many(choice(self, ...skips, content));
|
|
5083
|
+
const combi = transform(
|
|
5084
|
+
sequence(literal(open), inner, expect(literal(close), close)),
|
|
5085
|
+
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
5086
|
+
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
5087
|
+
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
5088
|
+
);
|
|
5089
|
+
if (combi._def.tag === "transform") {
|
|
5090
|
+
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
5091
|
+
}
|
|
5092
|
+
self.define(combi);
|
|
5093
|
+
return combi;
|
|
5094
|
+
}
|
|
5095
|
+
function firstSetClassChars(c) {
|
|
5096
|
+
const fs = c._meta.firstSet;
|
|
5097
|
+
if (fs.kind === "empty") return [];
|
|
5098
|
+
if (fs.kind !== "ranges") return null;
|
|
5099
|
+
const out = [];
|
|
5100
|
+
for (const { lo, hi } of fs.ranges) {
|
|
5101
|
+
if (hi - lo > 8) return null;
|
|
5102
|
+
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
5103
|
+
}
|
|
5104
|
+
return out;
|
|
5105
|
+
}
|
|
5106
|
+
function escapeClassChar(ch) {
|
|
5107
|
+
return ch.replace(/[\\\]^-]/g, "\\$&");
|
|
5108
|
+
}
|
|
5109
|
+
|
|
5110
|
+
// src/compiler/ir-serialize.ts
|
|
5111
|
+
function evalRuleMapIR(ir) {
|
|
5112
|
+
const _tf = (child, src) => {
|
|
5113
|
+
let fn2;
|
|
5114
|
+
try {
|
|
5115
|
+
fn2 = (0, eval)(`(${src})`);
|
|
5116
|
+
} catch {
|
|
5117
|
+
fn2 = () => {
|
|
5118
|
+
throw new Error("IR transform fn not materialized");
|
|
5119
|
+
};
|
|
5120
|
+
}
|
|
5121
|
+
const t = transform(child, fn2);
|
|
5122
|
+
t._def.fnSrc = src;
|
|
5123
|
+
return t;
|
|
5124
|
+
};
|
|
5125
|
+
const _nd = (type, child, src, opts) => {
|
|
5126
|
+
const n = node(type, child, void 0, opts);
|
|
5127
|
+
n._def.buildSrc = src;
|
|
5128
|
+
return n;
|
|
5129
|
+
};
|
|
5130
|
+
const fn = new Function(
|
|
5131
|
+
"rules",
|
|
5132
|
+
"ref",
|
|
5133
|
+
"regex",
|
|
5134
|
+
"literal",
|
|
5135
|
+
"keywords",
|
|
5136
|
+
"sequence",
|
|
5137
|
+
"choice",
|
|
5138
|
+
"many",
|
|
5139
|
+
"oneOrMore",
|
|
5140
|
+
"optional",
|
|
5141
|
+
"sepBy",
|
|
5142
|
+
"not",
|
|
5143
|
+
"node",
|
|
5144
|
+
"parser",
|
|
5145
|
+
"scanTo",
|
|
5146
|
+
"transform",
|
|
5147
|
+
"skip",
|
|
5148
|
+
"trivia",
|
|
5149
|
+
"label",
|
|
5150
|
+
"expect",
|
|
5151
|
+
"_tf",
|
|
5152
|
+
"_nd",
|
|
5153
|
+
`return (${ir})`
|
|
5154
|
+
);
|
|
5155
|
+
const map = fn(
|
|
5156
|
+
rules,
|
|
5157
|
+
ref,
|
|
5158
|
+
regex,
|
|
5159
|
+
literal,
|
|
5160
|
+
keywords,
|
|
5161
|
+
sequence,
|
|
5162
|
+
choice,
|
|
5163
|
+
many,
|
|
5164
|
+
oneOrMore,
|
|
5165
|
+
optional,
|
|
5166
|
+
sepBy,
|
|
5167
|
+
not,
|
|
5168
|
+
node,
|
|
5169
|
+
parser,
|
|
5170
|
+
scanTo,
|
|
5171
|
+
transform,
|
|
5172
|
+
skip,
|
|
5173
|
+
trivia,
|
|
5174
|
+
label,
|
|
5175
|
+
expect,
|
|
5176
|
+
_tf,
|
|
5177
|
+
_nd
|
|
5178
|
+
);
|
|
5179
|
+
return Object.entries(map);
|
|
5180
|
+
}
|
|
5181
|
+
|
|
4880
5182
|
// src/compiler/linker.ts
|
|
4881
5183
|
var _nsCounter = 0;
|
|
4882
5184
|
function linkable(rulesMap, ns) {
|
|
@@ -4961,9 +5263,18 @@ function fuseRules(pieces) {
|
|
|
4961
5263
|
return new Function("_env", body)(env);
|
|
4962
5264
|
}
|
|
4963
5265
|
var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
|
|
5266
|
+
function isIRPiece(p) {
|
|
5267
|
+
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
|
|
5268
|
+
}
|
|
5269
|
+
function materializePiece(p) {
|
|
5270
|
+
if (!isIRPiece(p)) return p;
|
|
5271
|
+
const pieces = compileLinkable(evalRuleMapIR(p.ir), p.ns);
|
|
5272
|
+
if (!pieces) throw new Error(`compose: carried IR for ns "${p.ns}" could not be re-lowered`);
|
|
5273
|
+
return pieces;
|
|
5274
|
+
}
|
|
4964
5275
|
function itemPieces(item) {
|
|
4965
5276
|
const carried = item[COMPOSED_PIECES];
|
|
4966
|
-
if (Array.isArray(carried)) return carried;
|
|
5277
|
+
if (Array.isArray(carried)) return carried.map(materializePiece);
|
|
4967
5278
|
if (item.ruleFns instanceof Map) return [item];
|
|
4968
5279
|
return [linkable(item)];
|
|
4969
5280
|
}
|
|
@@ -5059,100 +5370,6 @@ function deeperFail(a, b) {
|
|
|
5059
5370
|
return a.span.start >= b.span.start ? a : b;
|
|
5060
5371
|
}
|
|
5061
5372
|
|
|
5062
|
-
// src/combinators/scanTo.ts
|
|
5063
|
-
function scanTo(sentinel, { skip: skip2 = [], orEOF = false } = {}) {
|
|
5064
|
-
const meta = {
|
|
5065
|
-
firstSet: any(),
|
|
5066
|
-
canMatchNewline: true,
|
|
5067
|
-
isTrivia: false
|
|
5068
|
-
};
|
|
5069
|
-
return {
|
|
5070
|
-
_tag: "scanTo",
|
|
5071
|
-
_meta: meta,
|
|
5072
|
-
_def: { tag: "scanTo", sentinel, skip: skip2, orEOF },
|
|
5073
|
-
parse(input, pos, ctx) {
|
|
5074
|
-
let cur = pos;
|
|
5075
|
-
const probeCtx = {
|
|
5076
|
-
trackLines: ctx.trackLines,
|
|
5077
|
-
state: ctx.state,
|
|
5078
|
-
...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
|
|
5079
|
-
};
|
|
5080
|
-
const emit2 = (end) => {
|
|
5081
|
-
if (end > pos && cstCaptureActive(ctx)) {
|
|
5082
|
-
const leaf = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
|
|
5083
|
-
pushCstLeaf(ctx, leaf);
|
|
5084
|
-
}
|
|
5085
|
-
};
|
|
5086
|
-
while (cur < input.length) {
|
|
5087
|
-
const s = sentinel.parse(input, cur, probeCtx);
|
|
5088
|
-
if (s.ok) {
|
|
5089
|
-
emit2(cur);
|
|
5090
|
-
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5091
|
-
}
|
|
5092
|
-
let advanced = false;
|
|
5093
|
-
for (const skipper of skip2) {
|
|
5094
|
-
const r = skipper.parse(input, cur, probeCtx);
|
|
5095
|
-
if (r.ok && r.span.end > cur) {
|
|
5096
|
-
cur = r.span.end;
|
|
5097
|
-
advanced = true;
|
|
5098
|
-
break;
|
|
5099
|
-
}
|
|
5100
|
-
}
|
|
5101
|
-
if (!advanced) cur++;
|
|
5102
|
-
}
|
|
5103
|
-
if (orEOF) {
|
|
5104
|
-
emit2(cur);
|
|
5105
|
-
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
5106
|
-
}
|
|
5107
|
-
const sentDef = sentinel._def;
|
|
5108
|
-
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|
|
5109
|
-
return { ok: false, expected, span: { start: pos, end: cur } };
|
|
5110
|
-
}
|
|
5111
|
-
};
|
|
5112
|
-
}
|
|
5113
|
-
function balanced(open, close, options = {}) {
|
|
5114
|
-
const self = ref();
|
|
5115
|
-
const skips = options.skip ?? [];
|
|
5116
|
-
const stop = /* @__PURE__ */ new Set([open, close]);
|
|
5117
|
-
let bounded = true;
|
|
5118
|
-
for (const sk of skips) {
|
|
5119
|
-
const cs = firstSetClassChars(sk);
|
|
5120
|
-
if (cs === null) {
|
|
5121
|
-
bounded = false;
|
|
5122
|
-
break;
|
|
5123
|
-
}
|
|
5124
|
-
for (const ch of cs) stop.add(ch);
|
|
5125
|
-
}
|
|
5126
|
-
const cls = [...stop].map(escapeClassChar).join("");
|
|
5127
|
-
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
5128
|
-
const inner = many(choice(self, ...skips, content));
|
|
5129
|
-
const combi = transform(
|
|
5130
|
-
sequence(literal(open), inner, expect(literal(close), close)),
|
|
5131
|
-
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
5132
|
-
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
5133
|
-
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
5134
|
-
);
|
|
5135
|
-
if (combi._def.tag === "transform") {
|
|
5136
|
-
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
5137
|
-
}
|
|
5138
|
-
self.define(combi);
|
|
5139
|
-
return combi;
|
|
5140
|
-
}
|
|
5141
|
-
function firstSetClassChars(c) {
|
|
5142
|
-
const fs = c._meta.firstSet;
|
|
5143
|
-
if (fs.kind === "empty") return [];
|
|
5144
|
-
if (fs.kind !== "ranges") return null;
|
|
5145
|
-
const out = [];
|
|
5146
|
-
for (const { lo, hi } of fs.ranges) {
|
|
5147
|
-
if (hi - lo > 8) return null;
|
|
5148
|
-
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
5149
|
-
}
|
|
5150
|
-
return out;
|
|
5151
|
-
}
|
|
5152
|
-
function escapeClassChar(ch) {
|
|
5153
|
-
return ch.replace(/[\\\]^-]/g, "\\$&");
|
|
5154
|
-
}
|
|
5155
|
-
|
|
5156
5373
|
// src/combinators/recover-list.ts
|
|
5157
5374
|
function tolerantElement(item, sentinel, until) {
|
|
5158
5375
|
const el = transform(
|