parseman 0.54.0 → 0.55.1
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/analysis/diagnostics.js +102 -61
- package/dist/analysis/diagnostics.js.map +2 -2
- package/dist/cli/index.js +102 -61
- package/dist/cli/index.js.map +2 -2
- package/dist/combinators/withCtx.d.ts +22 -7
- package/dist/combinators/withCtx.d.ts.map +1 -1
- package/dist/index.js +121 -71
- package/dist/index.js.map +2 -2
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +126 -73
- package/dist/plugin/index.js.map +2 -2
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +102 -61
- package/dist/table/index.js.map +2 -2
- package/dist/table/ops.d.ts +3 -1
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/combinators/withCtx.ts +61 -28
- package/src/plugin/evaluator.ts +12 -2
- package/src/table/assemble.ts +11 -1
- package/src/table/encode.ts +94 -65
- package/src/table/exec.ts +2 -1
- package/src/table/ops.ts +3 -1
- package/src/types.ts +2 -0
- package/src/version.ts +1 -1
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import type { Combinator } from '../types.ts';
|
|
2
2
|
/**
|
|
3
|
-
* Runs `combinator`
|
|
4
|
-
* The outer user context is restored on exit (lexical scoping).
|
|
3
|
+
* Runs `combinator` under a scoped `ctx.state`, restored on exit (lexical scoping).
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* sequence(literal('{'), many(statement), literal('}'))
|
|
8
|
-
* )
|
|
5
|
+
* Two forms, told apart by whether the first argument is a function:
|
|
9
6
|
*
|
|
10
|
-
*
|
|
7
|
+
* - **Replace** — `withCtx(extra, c)`: the subtree's state IS `extra`.
|
|
8
|
+
*
|
|
9
|
+
* const functionBody = withCtx({ inFn: true },
|
|
10
|
+
* sequence(literal('{'), many(statement), literal('}'))
|
|
11
|
+
* )
|
|
12
|
+
*
|
|
13
|
+
* - **Derive** — `withCtx(state => next, c)`: the subtree's state is computed
|
|
14
|
+
* FROM the state in force at entry, once per entry. Use it to add or override
|
|
15
|
+
* a field while every outer field (options, document-wide sinks) stays visible
|
|
16
|
+
* to the gates and reducers inside:
|
|
17
|
+
*
|
|
18
|
+
* const argument = withCtx(s => ({ ...s, stop: 'comparison' }), value)
|
|
19
|
+
*
|
|
20
|
+
* Because a function argument always selects the derive form, a state that is
|
|
21
|
+
* itself a function cannot be installed with the replace form; wrap it
|
|
22
|
+
* (`withCtx(() => fn, c)`).
|
|
23
|
+
*
|
|
24
|
+
* Read back with gate() or from within a transform's span argument.
|
|
11
25
|
*/
|
|
12
|
-
export declare function withCtx<U, T>(
|
|
26
|
+
export declare function withCtx<S = Readonly<Record<string, unknown>> | undefined, U = unknown, T = unknown>(derive: (state: S) => U, combinator: Combinator<T>): Combinator<T>;
|
|
27
|
+
export declare function withCtx<U, T>(extra: U extends (...args: never[]) => unknown ? never : U, combinator: Combinator<T>): Combinator<T>;
|
|
13
28
|
//# sourceMappingURL=withCtx.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withCtx.d.ts","sourceRoot":"","sources":["../../src/combinators/withCtx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,aAAa,CAAA;AAEpF
|
|
1
|
+
{"version":3,"file":"withCtx.d.ts","sourceRoot":"","sources":["../../src/combinators/withCtx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,aAAa,CAAA;AAEpF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,wBAAgB,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;AAKvK,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -7259,19 +7259,11 @@ var Encoder = class {
|
|
|
7259
7259
|
nonCommittingChoiceSites = /* @__PURE__ */ new Set();
|
|
7260
7260
|
failureRollbackCleanSites = /* @__PURE__ */ new Set();
|
|
7261
7261
|
/**
|
|
7262
|
-
* `
|
|
7263
|
-
* for the lifetime of this `Encoder`.
|
|
7264
|
-
*
|
|
7265
|
-
*
|
|
7266
|
-
*
|
|
7267
|
-
* (as a local inside `failureNeedsRollback`) was correct but discarded that
|
|
7268
|
-
* fact after every arm, so a grammar with many ordered-choice arms / optional
|
|
7269
|
-
* / attempt sites re-walked the SAME shared rule graph from scratch for each
|
|
7270
|
-
* site — O(sites × graph size) instead of O(graph size). Measured on the
|
|
7271
|
-
* scss-parser grammar (composed CSS-base superset, the deepest/largest of the
|
|
7272
|
-
* four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
|
|
7273
|
-
* versus the whole macro transform completing in under a second once this
|
|
7274
|
-
* memo is hoisted here.
|
|
7262
|
+
* `reachesSideWriter`'s answers, shared by every `failureNeedsRollback` call
|
|
7263
|
+
* for the lifetime of this `Encoder`. Every entry is exact — it depends only on
|
|
7264
|
+
* the node's own reachable subgraph, never on which root's walk asked — so each
|
|
7265
|
+
* combinator is walked once per encode however many choice arms, optionals and
|
|
7266
|
+
* attempt sites reach it.
|
|
7275
7267
|
*/
|
|
7276
7268
|
sideWriterMemo = /* @__PURE__ */ new Map();
|
|
7277
7269
|
labels = void 0;
|
|
@@ -7704,63 +7696,96 @@ var Encoder = class {
|
|
|
7704
7696
|
* writer census covers the side sinks that proof deliberately does not model:
|
|
7705
7697
|
* fields, recovered errors, and interpreted scanners. Strict assemblies do
|
|
7706
7698
|
* not run repeat recovery, but these rows can still publish through a caller's
|
|
7707
|
-
* context.
|
|
7708
|
-
* discover a writer the first traversal did not already reach.
|
|
7699
|
+
* context.
|
|
7709
7700
|
*/
|
|
7710
7701
|
failureNeedsRollback(p, autoNot) {
|
|
7711
7702
|
const refName = p._ruleName;
|
|
7712
7703
|
const winner = refName === void 0 ? void 0 : this.winners?.[refName];
|
|
7713
7704
|
const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7705
|
+
return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || this.reachesSideWriter(root) || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
|
|
7706
|
+
}
|
|
7707
|
+
/**
|
|
7708
|
+
* Whether a field, recovered error, interpreted scanner or unresolvable shape
|
|
7709
|
+
* is reachable from `root` — the writer census of `failureNeedsRollback`.
|
|
7710
|
+
*
|
|
7711
|
+
* Reachability over a cyclic graph, decided with Tarjan's strongly connected
|
|
7712
|
+
* components so that every node the walk enters leaves with its exact answer
|
|
7713
|
+
* memoized: the members of one component reach each other, so they share one
|
|
7714
|
+
* answer, settled when the walk returns to the component's first node. A DFS
|
|
7715
|
+
* that instead cuts a cycle at its own ancestor path learns nothing it can
|
|
7716
|
+
* keep about a node whose walk hit the cut, and re-walks that node along
|
|
7717
|
+
* every path that reaches it — exponential over recursive value rules (linking
|
|
7718
|
+
* jess's SCSS grammar cost ~290G instructions). This walk enters each node
|
|
7719
|
+
* once per `Encoder`.
|
|
7720
|
+
*/
|
|
7721
|
+
reachesSideWriter(root) {
|
|
7722
|
+
const memo = this.sideWriterMemo;
|
|
7723
|
+
const known = memo.get(root);
|
|
7724
|
+
if (known !== void 0) return known;
|
|
7725
|
+
const order = /* @__PURE__ */ new Map();
|
|
7726
|
+
const low = [];
|
|
7727
|
+
const found = [];
|
|
7728
|
+
const stack = [];
|
|
7729
|
+
const visit = (node2) => {
|
|
7730
|
+
const at = low.length;
|
|
7731
|
+
order.set(node2, at);
|
|
7732
|
+
low.push(at);
|
|
7733
|
+
found.push(false);
|
|
7734
|
+
stack.push(node2);
|
|
7735
|
+
const next = this.sideWriterSuccessors(node2);
|
|
7736
|
+
if (next === true) found[at] = true;
|
|
7737
|
+
else {
|
|
7738
|
+
for (const child of next) {
|
|
7739
|
+
const hit = memo.get(child);
|
|
7740
|
+
if (hit !== void 0) {
|
|
7741
|
+
if (hit) found[at] = true;
|
|
7742
|
+
continue;
|
|
7742
7743
|
}
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
result = { found: false, complete: true };
|
|
7748
|
-
for (const child of childrenOf2(def)) {
|
|
7749
|
-
const childResult = hasSideWriter(child);
|
|
7750
|
-
if (childResult.found) {
|
|
7751
|
-
result = { found: true, complete: true };
|
|
7752
|
-
break;
|
|
7753
|
-
}
|
|
7754
|
-
complete &&= childResult.complete;
|
|
7744
|
+
const seen = order.get(child);
|
|
7745
|
+
if (seen !== void 0) {
|
|
7746
|
+
if (seen < low[at]) low[at] = seen;
|
|
7747
|
+
continue;
|
|
7755
7748
|
}
|
|
7756
|
-
|
|
7749
|
+
const k = visit(child);
|
|
7750
|
+
if (low[k] < low[at]) low[at] = low[k];
|
|
7751
|
+
if (found[k]) found[at] = true;
|
|
7757
7752
|
}
|
|
7758
7753
|
}
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7754
|
+
if (low[at] === at) {
|
|
7755
|
+
const answer = found[at];
|
|
7756
|
+
let member;
|
|
7757
|
+
do {
|
|
7758
|
+
member = stack.pop();
|
|
7759
|
+
memo.set(member, answer);
|
|
7760
|
+
} while (member !== node2);
|
|
7761
|
+
}
|
|
7762
|
+
return at;
|
|
7762
7763
|
};
|
|
7763
|
-
return
|
|
7764
|
+
return found[visit(root)];
|
|
7765
|
+
}
|
|
7766
|
+
/** The census's edges out of `node`, or `true` when `node` is itself a writer. */
|
|
7767
|
+
sideWriterSuccessors(node2) {
|
|
7768
|
+
const def = node2._def;
|
|
7769
|
+
switch (def.tag) {
|
|
7770
|
+
case "field":
|
|
7771
|
+
case "expect":
|
|
7772
|
+
case "recover":
|
|
7773
|
+
case "scanTo":
|
|
7774
|
+
case "unknown":
|
|
7775
|
+
return true;
|
|
7776
|
+
case "lazy": {
|
|
7777
|
+
const name = node2._ruleName;
|
|
7778
|
+
const winner = name === void 0 ? void 0 : this.winners?.[name];
|
|
7779
|
+
if (winner !== void 0 && !winnerWrapsReference2(winner, node2)) return [winner];
|
|
7780
|
+
try {
|
|
7781
|
+
return [def.thunk()];
|
|
7782
|
+
} catch {
|
|
7783
|
+
return true;
|
|
7784
|
+
}
|
|
7785
|
+
}
|
|
7786
|
+
default:
|
|
7787
|
+
return childrenOf2(def);
|
|
7788
|
+
}
|
|
7764
7789
|
}
|
|
7765
7790
|
/** A first set becomes a char class string, or −1 for `any`. */
|
|
7766
7791
|
charClass(fs) {
|
|
@@ -8277,6 +8302,9 @@ var Encoder = class {
|
|
|
8277
8302
|
this.expected([adjacencyExpected(d)])
|
|
8278
8303
|
);
|
|
8279
8304
|
case "withCtx": {
|
|
8305
|
+
if (typeof d.extra === "function") {
|
|
8306
|
+
return this.emit(OP_WITHCTX, ~this.fn(d.extra, d.extraSrc ?? null), this.node(d.parser).ip);
|
|
8307
|
+
}
|
|
8280
8308
|
if (!emittableConst(d.extra)) {
|
|
8281
8309
|
this.runtimeOnly.add("withCtx(extra) \u2014 the state object is not serialisable");
|
|
8282
8310
|
}
|
|
@@ -13233,8 +13261,21 @@ function assemble(t, prog, cfg) {
|
|
|
13233
13261
|
};
|
|
13234
13262
|
}
|
|
13235
13263
|
case OP_WITHCTX: {
|
|
13236
|
-
const
|
|
13264
|
+
const ki = code[ip + 1];
|
|
13237
13265
|
const child = link(code[ip + 2]);
|
|
13266
|
+
if (ki < 0) {
|
|
13267
|
+
const derive2 = fns[~ki];
|
|
13268
|
+
return (input, pos, ctx) => {
|
|
13269
|
+
const saved = ctx.state;
|
|
13270
|
+
ctx.state = derive2(saved);
|
|
13271
|
+
try {
|
|
13272
|
+
return child(input, pos, ctx);
|
|
13273
|
+
} finally {
|
|
13274
|
+
ctx.state = saved;
|
|
13275
|
+
}
|
|
13276
|
+
};
|
|
13277
|
+
}
|
|
13278
|
+
const extra = k[ki];
|
|
13238
13279
|
return (input, pos, ctx) => {
|
|
13239
13280
|
const saved = ctx.state;
|
|
13240
13281
|
ctx.state = extra;
|
|
@@ -17725,7 +17766,7 @@ function fieldOptionsSrc(def) {
|
|
|
17725
17766
|
}
|
|
17726
17767
|
|
|
17727
17768
|
// src/version.ts
|
|
17728
|
-
var PARSEMAN_VERSION = "0.
|
|
17769
|
+
var PARSEMAN_VERSION = "0.55.1";
|
|
17729
17770
|
|
|
17730
17771
|
// src/compiler/compile-linkable-table.ts
|
|
17731
17772
|
function isLocal(rule) {
|
|
@@ -19313,19 +19354,28 @@ function withCtx(extra, combinator) {
|
|
|
19313
19354
|
canMatchNewline: combinator._meta.canMatchNewline,
|
|
19314
19355
|
isTrivia: false
|
|
19315
19356
|
};
|
|
19357
|
+
const parse2 = typeof extra === "function" ? (input, pos, ctx) => {
|
|
19358
|
+
const saved = ctx.state;
|
|
19359
|
+
ctx.state = extra(saved);
|
|
19360
|
+
try {
|
|
19361
|
+
return combinator.parse(input, pos, ctx);
|
|
19362
|
+
} finally {
|
|
19363
|
+
ctx.state = saved;
|
|
19364
|
+
}
|
|
19365
|
+
} : (input, pos, ctx) => {
|
|
19366
|
+
const saved = ctx.state;
|
|
19367
|
+
ctx.state = extra;
|
|
19368
|
+
try {
|
|
19369
|
+
return combinator.parse(input, pos, ctx);
|
|
19370
|
+
} finally {
|
|
19371
|
+
ctx.state = saved;
|
|
19372
|
+
}
|
|
19373
|
+
};
|
|
19316
19374
|
return {
|
|
19317
19375
|
_tag: "withCtx",
|
|
19318
19376
|
_meta: meta,
|
|
19319
19377
|
_def: { tag: "withCtx", extra, parser: combinator },
|
|
19320
|
-
parse
|
|
19321
|
-
const saved = ctx.state;
|
|
19322
|
-
ctx.state = extra;
|
|
19323
|
-
try {
|
|
19324
|
-
return combinator.parse(input, pos, ctx);
|
|
19325
|
-
} finally {
|
|
19326
|
-
ctx.state = saved;
|
|
19327
|
-
}
|
|
19328
|
-
}
|
|
19378
|
+
parse: parse2
|
|
19329
19379
|
};
|
|
19330
19380
|
}
|
|
19331
19381
|
|