parseman 0.61.0 → 0.61.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/backtrack.d.ts +50 -0
- package/dist/analysis/backtrack.d.ts.map +1 -0
- package/dist/analysis/diagnostics.d.ts +3 -0
- package/dist/analysis/diagnostics.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +1116 -123
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/rebuild.d.ts +17 -1
- package/dist/analysis/rebuild.d.ts.map +1 -1
- package/dist/cli/index.js +307 -34
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/dispatch.d.ts +2 -0
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/index.js +31 -25
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.js +21 -15
- package/dist/plugin/index.js.map +2 -2
- package/dist/table/backtrack-probe.d.ts +41 -0
- package/dist/table/backtrack-probe.d.ts.map +1 -0
- package/dist/table/child-slots.d.ts +10 -0
- package/dist/table/child-slots.d.ts.map +1 -1
- package/dist/table/index.js +21 -15
- package/dist/table/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +5 -1
- package/src/analysis/backtrack.ts +249 -0
- package/src/analysis/diagnostics.ts +4 -0
- package/src/analysis/rebuild.ts +63 -11
- package/src/combinators/dispatch.ts +9 -0
- package/src/coverage.ts +2 -14
- package/src/table/backtrack-probe.ts +326 -0
- package/src/table/child-slots.ts +30 -14
- package/src/version.ts +1 -1
|
@@ -424,13 +424,13 @@ function caseFoldVariants(cp) {
|
|
|
424
424
|
// src/combinators/probe.ts
|
|
425
425
|
function failAt(ctx, expected, pos) {
|
|
426
426
|
const r = { ok: false, expected, span: { start: pos, end: pos } };
|
|
427
|
-
const
|
|
428
|
-
if (
|
|
429
|
-
const best =
|
|
427
|
+
const probe2 = ctx._probe;
|
|
428
|
+
if (probe2 !== void 0 && pos <= probe2.offset) {
|
|
429
|
+
const best = probe2.best;
|
|
430
430
|
if (best === null || pos > best.span.start) {
|
|
431
|
-
|
|
431
|
+
probe2.best = r;
|
|
432
432
|
} else if (pos === best.span.start) {
|
|
433
|
-
|
|
433
|
+
probe2.best = { ...best, expected: [...best.expected, ...expected] };
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
436
|
return r;
|
|
@@ -2610,6 +2610,7 @@ function matchesAt(sentinel, input, pos, ctx) {
|
|
|
2610
2610
|
function captureError(ctx, error) {
|
|
2611
2611
|
if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
|
|
2612
2612
|
}
|
|
2613
|
+
var REC = { scan: recoverScan, at: matchesAt, or: orSentinel, sentinel: firstSetSentinel, capture: captureError };
|
|
2613
2614
|
|
|
2614
2615
|
// src/combinators/expect.ts
|
|
2615
2616
|
function deriveExpected(c) {
|
|
@@ -4063,7 +4064,7 @@ function regex(pattern, flags = "") {
|
|
|
4063
4064
|
}
|
|
4064
4065
|
|
|
4065
4066
|
// src/version.ts
|
|
4066
|
-
var PARSEMAN_VERSION = "0.61.
|
|
4067
|
+
var PARSEMAN_VERSION = "0.61.1";
|
|
4067
4068
|
|
|
4068
4069
|
// src/table/lex-body.ts
|
|
4069
4070
|
function buildLexBodyRecognizer(spec, constants) {
|
|
@@ -4533,7 +4534,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
4533
4534
|
if (!Number.isInteger(spec[2]) || spec[2] < 0) {
|
|
4534
4535
|
throw new TypeError("table balanced lexical program has an invalid scan reference");
|
|
4535
4536
|
}
|
|
4536
|
-
const
|
|
4537
|
+
const run2 = (_input, _pos, ctx, scan) => {
|
|
4537
4538
|
if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
|
|
4538
4539
|
const result = scan.parse(_input, _pos, ctx);
|
|
4539
4540
|
if (!result.ok) {
|
|
@@ -4543,7 +4544,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
4543
4544
|
}
|
|
4544
4545
|
return result.span.end;
|
|
4545
4546
|
};
|
|
4546
|
-
return Object.assign(
|
|
4547
|
+
return Object.assign(run2, { scan: spec[2] });
|
|
4547
4548
|
}
|
|
4548
4549
|
if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
|
|
4549
4550
|
if (spec[0] === 1) {
|
|
@@ -6590,6 +6591,206 @@ function asciiFoldKey(key) {
|
|
|
6590
6591
|
}
|
|
6591
6592
|
return out;
|
|
6592
6593
|
}
|
|
6594
|
+
function matchesDispatchMatcher(value, matcher) {
|
|
6595
|
+
const candidate = matcher.caseInsensitive ? asciiFoldKey(value) : value;
|
|
6596
|
+
const expected = matcher.caseInsensitive ? asciiFoldKey(matcher.value) : matcher.value;
|
|
6597
|
+
switch (matcher.kind) {
|
|
6598
|
+
case "startsWith":
|
|
6599
|
+
return candidate.startsWith(expected);
|
|
6600
|
+
case "endsWith":
|
|
6601
|
+
return candidate.endsWith(expected);
|
|
6602
|
+
case "matches": {
|
|
6603
|
+
const flags = matcher.caseInsensitive && !matcher.flags?.includes("i") ? `${matcher.flags ?? ""}i` : matcher.flags ?? "";
|
|
6604
|
+
return new RegExp(matcher.value, flags).test(value);
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6608
|
+
function isStringMatcher(value) {
|
|
6609
|
+
if (typeof value !== "object" || value === null) return false;
|
|
6610
|
+
const kind = value.kind;
|
|
6611
|
+
return kind === "startsWith" || kind === "endsWith" || kind === "matches";
|
|
6612
|
+
}
|
|
6613
|
+
function fixedMatcher(kind, value) {
|
|
6614
|
+
if (typeof value !== "string") throw new TypeError(`parseman: ${kind}() value must be a string`);
|
|
6615
|
+
if (value.length === 0) throw new RangeError(`parseman: ${kind}() requires a non-empty value`);
|
|
6616
|
+
return { kind, value };
|
|
6617
|
+
}
|
|
6618
|
+
function startsWith(prefix) {
|
|
6619
|
+
return fixedMatcher("startsWith", prefix);
|
|
6620
|
+
}
|
|
6621
|
+
function endsWith(suffix) {
|
|
6622
|
+
return fixedMatcher("endsWith", suffix);
|
|
6623
|
+
}
|
|
6624
|
+
function matches(pattern) {
|
|
6625
|
+
if (!(pattern instanceof RegExp)) throw new TypeError("parseman: matches() requires a RegExp");
|
|
6626
|
+
if (pattern.flags.includes("g") || pattern.flags.includes("y")) {
|
|
6627
|
+
throw new TypeError("parseman: matches() does not accept global or sticky regex flags");
|
|
6628
|
+
}
|
|
6629
|
+
return { kind: "matches", value: pattern.source, flags: pattern.flags };
|
|
6630
|
+
}
|
|
6631
|
+
function dispatchMatcher(entry) {
|
|
6632
|
+
switch (entry.kind) {
|
|
6633
|
+
case "startsWith":
|
|
6634
|
+
return startsWith(entry.value);
|
|
6635
|
+
case "endsWith":
|
|
6636
|
+
return endsWith(entry.value);
|
|
6637
|
+
case "matches":
|
|
6638
|
+
return matches(new RegExp(entry.value, entry.flags));
|
|
6639
|
+
}
|
|
6640
|
+
}
|
|
6641
|
+
function when(key, parser2, opts = {}) {
|
|
6642
|
+
const usesRouted = parserUsesRouted(parser2);
|
|
6643
|
+
if (isStringMatcher(key)) {
|
|
6644
|
+
return { kind: "whenMatcher", matcher: key, parser: parser2, caseInsensitive: opts.caseInsensitive ?? false, usesRouted };
|
|
6645
|
+
}
|
|
6646
|
+
const keys = Array.isArray(key) ? [...key] : [key];
|
|
6647
|
+
if (keys.length === 0) throw new RangeError("parseman: when() requires at least one key");
|
|
6648
|
+
for (const item of keys) {
|
|
6649
|
+
if (typeof item !== "string") throw new TypeError("parseman: when() keys must be strings");
|
|
6650
|
+
}
|
|
6651
|
+
return { kind: "when", keys, parser: parser2, caseInsensitive: opts.caseInsensitive ?? false, usesRouted };
|
|
6652
|
+
}
|
|
6653
|
+
function otherwise(parser2, opts = {}) {
|
|
6654
|
+
const usesRouted = parserUsesRouted(parser2);
|
|
6655
|
+
return opts.commit === false ? { kind: "otherwise", parser: parser2, usesRouted, commit: false } : { kind: "otherwise", parser: parser2, usesRouted };
|
|
6656
|
+
}
|
|
6657
|
+
function routed(fallback) {
|
|
6658
|
+
return {
|
|
6659
|
+
_tag: "routed",
|
|
6660
|
+
_meta: {
|
|
6661
|
+
// The routed token is whatever the selector matched, so the first set stays
|
|
6662
|
+
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
6663
|
+
firstSet: { kind: "any" },
|
|
6664
|
+
canMatchNewline: fallback?._meta.canMatchNewline ?? false,
|
|
6665
|
+
isTrivia: false
|
|
6666
|
+
},
|
|
6667
|
+
_def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
|
|
6668
|
+
parse(_input, pos, ctx) {
|
|
6669
|
+
const item = ctx._routed;
|
|
6670
|
+
if (item === void 0 || pos !== item.span.start) {
|
|
6671
|
+
if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
|
|
6672
|
+
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
6673
|
+
}
|
|
6674
|
+
if (cstCaptureActive(ctx)) {
|
|
6675
|
+
pushCstLeaf(ctx, new PlainLeaf6(item.value, item.span));
|
|
6676
|
+
}
|
|
6677
|
+
return { ok: true, value: item.value, span: item.span };
|
|
6678
|
+
}
|
|
6679
|
+
};
|
|
6680
|
+
}
|
|
6681
|
+
function dispatch(selector, ...arms) {
|
|
6682
|
+
if (parserUsesRouted(selector)) {
|
|
6683
|
+
throw new Error("parseman: routed() can only appear inside a dispatch() branch");
|
|
6684
|
+
}
|
|
6685
|
+
let fallback;
|
|
6686
|
+
let fallbackUsesRouted = false;
|
|
6687
|
+
let fallbackCommits = true;
|
|
6688
|
+
const matchers = [];
|
|
6689
|
+
const cases = [];
|
|
6690
|
+
const seen = [];
|
|
6691
|
+
for (let i = 0; i < arms.length; i++) {
|
|
6692
|
+
const arm = arms[i];
|
|
6693
|
+
if (arm.kind === "otherwise") {
|
|
6694
|
+
if (fallback !== void 0) throw new Error("parseman: dispatch() accepts at most one otherwise() arm");
|
|
6695
|
+
if (i !== arms.length - 1) throw new Error("parseman: otherwise() must be the last dispatch() arm");
|
|
6696
|
+
fallback = arm.parser;
|
|
6697
|
+
fallbackUsesRouted = arm.usesRouted === true;
|
|
6698
|
+
fallbackCommits = arm.commit !== false;
|
|
6699
|
+
continue;
|
|
6700
|
+
}
|
|
6701
|
+
if (arm.kind === "whenMatcher") {
|
|
6702
|
+
const matcher = arm.matcher;
|
|
6703
|
+
matchers.push({
|
|
6704
|
+
kind: matcher.kind,
|
|
6705
|
+
value: matcher.value,
|
|
6706
|
+
...matcher.kind === "matches" ? { flags: matcher.flags } : {},
|
|
6707
|
+
parser: arm.parser,
|
|
6708
|
+
caseInsensitive: arm.caseInsensitive,
|
|
6709
|
+
...arm.usesRouted === true ? { usesRouted: true } : {}
|
|
6710
|
+
});
|
|
6711
|
+
continue;
|
|
6712
|
+
}
|
|
6713
|
+
for (const key of arm.keys) {
|
|
6714
|
+
const folded = asciiFoldKey(key);
|
|
6715
|
+
for (const prior of seen) {
|
|
6716
|
+
const overlaps = arm.caseInsensitive || prior.caseInsensitive ? folded === prior.folded : key === prior.raw;
|
|
6717
|
+
if (overlaps) throw new Error(`parseman: duplicate dispatch key ${JSON.stringify(key)}`);
|
|
6718
|
+
}
|
|
6719
|
+
seen.push({ raw: key, folded, caseInsensitive: arm.caseInsensitive });
|
|
6720
|
+
}
|
|
6721
|
+
cases.push({
|
|
6722
|
+
keys: arm.keys,
|
|
6723
|
+
parser: arm.parser,
|
|
6724
|
+
caseInsensitive: arm.caseInsensitive,
|
|
6725
|
+
...arm.usesRouted === true ? { usesRouted: true } : {}
|
|
6726
|
+
});
|
|
6727
|
+
}
|
|
6728
|
+
const meta = {
|
|
6729
|
+
firstSet: selector._meta.firstSet,
|
|
6730
|
+
canMatchNewline: selector._meta.canMatchNewline || cases.some((entry) => entry.parser._meta.canMatchNewline) || matchers.some((entry) => entry.parser._meta.canMatchNewline) || (fallback?._meta.canMatchNewline ?? false),
|
|
6731
|
+
isTrivia: false
|
|
6732
|
+
};
|
|
6733
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
6734
|
+
const byFoldedKey = /* @__PURE__ */ new Map();
|
|
6735
|
+
for (const entry of cases) {
|
|
6736
|
+
for (const key of entry.keys) {
|
|
6737
|
+
if (entry.caseInsensitive) byFoldedKey.set(asciiFoldKey(key), entry);
|
|
6738
|
+
else byKey.set(key, entry);
|
|
6739
|
+
}
|
|
6740
|
+
}
|
|
6741
|
+
return {
|
|
6742
|
+
_tag: "dispatch",
|
|
6743
|
+
_meta: meta,
|
|
6744
|
+
_def: {
|
|
6745
|
+
tag: "dispatch",
|
|
6746
|
+
selector,
|
|
6747
|
+
cases,
|
|
6748
|
+
...matchers.length === 0 ? {} : { matchers },
|
|
6749
|
+
...fallback === void 0 ? {} : {
|
|
6750
|
+
otherwise: fallback,
|
|
6751
|
+
...fallbackUsesRouted ? { otherwiseUsesRouted: true } : {},
|
|
6752
|
+
...fallbackCommits ? {} : { otherwiseCommit: false }
|
|
6753
|
+
}
|
|
6754
|
+
},
|
|
6755
|
+
parse(input, pos, ctx) {
|
|
6756
|
+
if (parserUsesRouted(selector)) {
|
|
6757
|
+
throw new Error("parseman: routed() can only appear inside a dispatch() branch");
|
|
6758
|
+
}
|
|
6759
|
+
const selectorMark = saveTriviaMark(ctx);
|
|
6760
|
+
const selected = selector.parse(input, pos, ctx);
|
|
6761
|
+
if (!selected.ok) return selected;
|
|
6762
|
+
const chosen = byKey.get(selected.value) ?? (byFoldedKey.size === 0 ? void 0 : byFoldedKey.get(asciiFoldKey(selected.value))) ?? matchers.find((matcher) => matchesDispatchMatcher(selected.value, matcher));
|
|
6763
|
+
const branch = chosen ?? (fallback === void 0 ? void 0 : { keys: [], parser: fallback, caseInsensitive: false, usesRouted: fallbackUsesRouted });
|
|
6764
|
+
if (branch === void 0) {
|
|
6765
|
+
const expected = cases.flatMap((entry) => entry.keys.map((key) => JSON.stringify(key)));
|
|
6766
|
+
return { ok: false, expected, span: { start: selected.span.end, end: selected.span.end } };
|
|
6767
|
+
}
|
|
6768
|
+
const savedRouted = ctx._routed;
|
|
6769
|
+
const usesRouted = branchUsesRouted(branch);
|
|
6770
|
+
let mark = saveTriviaMark(ctx);
|
|
6771
|
+
if (usesRouted) {
|
|
6772
|
+
rollbackTrivia(ctx, selectorMark);
|
|
6773
|
+
mark = saveTriviaMark(ctx);
|
|
6774
|
+
ctx._routed = { value: selected.value, span: selected.span };
|
|
6775
|
+
}
|
|
6776
|
+
let result;
|
|
6777
|
+
try {
|
|
6778
|
+
result = branch.parser.parse(input, usesRouted ? pos : selected.span.end, ctx);
|
|
6779
|
+
} finally {
|
|
6780
|
+
if (usesRouted) ctx._routed = savedRouted;
|
|
6781
|
+
}
|
|
6782
|
+
if (!result.ok) {
|
|
6783
|
+
rollbackTrivia(ctx, mark);
|
|
6784
|
+
return chosen === void 0 && !fallbackCommits ? result : { ...result, committed: true };
|
|
6785
|
+
}
|
|
6786
|
+
return {
|
|
6787
|
+
ok: true,
|
|
6788
|
+
value: [selected.value, result.value],
|
|
6789
|
+
span: { start: pos, end: result.span.end }
|
|
6790
|
+
};
|
|
6791
|
+
}
|
|
6792
|
+
};
|
|
6793
|
+
}
|
|
6593
6794
|
|
|
6594
6795
|
// src/table/ops.ts
|
|
6595
6796
|
var OP_LIT = 1;
|
|
@@ -8644,7 +8845,7 @@ var Encoder = class {
|
|
|
8644
8845
|
const dispCovIds = this.plan?.dispatches.get(p);
|
|
8645
8846
|
let dispCov = 0;
|
|
8646
8847
|
const arms = [];
|
|
8647
|
-
const
|
|
8848
|
+
const routed2 = [];
|
|
8648
8849
|
const key = [], keyArm = [];
|
|
8649
8850
|
const fold = [], foldArm = [];
|
|
8650
8851
|
const match = [];
|
|
@@ -8652,7 +8853,7 @@ var Encoder = class {
|
|
|
8652
8853
|
for (const c of d.cases) {
|
|
8653
8854
|
const arm = arms.length;
|
|
8654
8855
|
arms.push(this.covWrap(this.node(c.parser).ip, dispCovIds?.[dispCov++], 1));
|
|
8655
|
-
|
|
8856
|
+
routed2.push(branchUsesRouted(c) ? 1 : 0);
|
|
8656
8857
|
for (const kk of c.keys) {
|
|
8657
8858
|
expected.push(JSON.stringify(kk));
|
|
8658
8859
|
if (c.caseInsensitive) {
|
|
@@ -8668,7 +8869,7 @@ var Encoder = class {
|
|
|
8668
8869
|
for (const m of d.matchers ?? []) {
|
|
8669
8870
|
const arm = arms.length;
|
|
8670
8871
|
arms.push(this.covWrap(this.node(m.parser).ip, dispCovIds?.[dispCov++], 1));
|
|
8671
|
-
|
|
8872
|
+
routed2.push(branchUsesRouted(m) ? 1 : 0);
|
|
8672
8873
|
if (!m.caseInsensitive) {
|
|
8673
8874
|
match.push([KIND[m.kind], m.value, m.flags ?? "", arm]);
|
|
8674
8875
|
continue;
|
|
@@ -8682,7 +8883,7 @@ var Encoder = class {
|
|
|
8682
8883
|
}
|
|
8683
8884
|
const other = d.otherwise === void 0 ? -1 : this.covWrap(this.node(d.otherwise).ip, dispCovIds?.[dispCov++], 1);
|
|
8684
8885
|
const dspIdx = this.dsp.length;
|
|
8685
|
-
this.dsp.push({ key, keyArm, fold, foldArm, match, routed, expected });
|
|
8886
|
+
this.dsp.push({ key, keyArm, fold, foldArm, match, routed: routed2, expected });
|
|
8686
8887
|
const head = this.emitHead(OP_DISPATCH, 5 + arms.length);
|
|
8687
8888
|
this.code[head + 1] = sel;
|
|
8688
8889
|
this.code[head + 2] = dspIdx;
|
|
@@ -9998,6 +10199,12 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
9998
10199
|
|
|
9999
10200
|
// src/table/child-slots.ts
|
|
10000
10201
|
function childSlots(code, ip, out) {
|
|
10202
|
+
const from = out.length;
|
|
10203
|
+
if (!childSlotOffsets(code, ip, out)) return false;
|
|
10204
|
+
for (let i = from; i < out.length; i++) out[i] = code[out[i]];
|
|
10205
|
+
return true;
|
|
10206
|
+
}
|
|
10207
|
+
function childSlotOffsets(code, ip, out) {
|
|
10001
10208
|
switch (code[ip]) {
|
|
10002
10209
|
// ZERO-WIDTH / TERMINAL ROWS — no successor. `OP_GUARD` and `OP_ADJ` are both
|
|
10003
10210
|
// childless tests. `OP_LIVE` holds a hand-written combinator in `prog.fns`; its
|
|
@@ -10030,7 +10237,7 @@ function childSlots(code, ip, out) {
|
|
|
10030
10237
|
case OP_COV:
|
|
10031
10238
|
case OP_REJECT:
|
|
10032
10239
|
case OP_GAPGATE:
|
|
10033
|
-
out.push(
|
|
10240
|
+
out.push(ip + 1);
|
|
10034
10241
|
return true;
|
|
10035
10242
|
// Single child at `ip + 2`.
|
|
10036
10243
|
case OP_GATE:
|
|
@@ -10047,55 +10254,55 @@ function childSlots(code, ip, out) {
|
|
|
10047
10254
|
case OP_ARMGATE:
|
|
10048
10255
|
case OP_RGATE:
|
|
10049
10256
|
case OP_RGATE2:
|
|
10050
|
-
out.push(
|
|
10257
|
+
out.push(ip + 2);
|
|
10051
10258
|
return true;
|
|
10052
10259
|
// `STRICT strict tolerant` — both encodings are reachable; an assembly keeps one.
|
|
10053
10260
|
case OP_STRICT:
|
|
10054
|
-
out.push(
|
|
10261
|
+
out.push(ip + 1, ip + 2);
|
|
10055
10262
|
return true;
|
|
10056
10263
|
// `ROUTED fallback` — the operand is an offset or −1. The routed token itself is
|
|
10057
10264
|
// data the enclosing `dispatch()` already consumed, so the only edge is the
|
|
10058
10265
|
// fallback.
|
|
10059
10266
|
case OP_ROUTED:
|
|
10060
|
-
if (code[ip + 1] >= 0) out.push(
|
|
10267
|
+
if (code[ip + 1] >= 0) out.push(ip + 1);
|
|
10061
10268
|
return true;
|
|
10062
10269
|
// `DISPATCH sel d other otherRouted n a1 … an` — the SELECTOR is a child on
|
|
10063
10270
|
// exactly the same footing as the arms: it runs inside whatever node and scope
|
|
10064
10271
|
// this site sits in.
|
|
10065
10272
|
case OP_DISPATCH: {
|
|
10066
|
-
out.push(
|
|
10067
|
-
if (code[ip + 3] >= 0) out.push(
|
|
10273
|
+
out.push(ip + 1);
|
|
10274
|
+
if (code[ip + 3] >= 0) out.push(ip + 3);
|
|
10068
10275
|
const n = code[ip + 5];
|
|
10069
|
-
for (let i = 0; i < n; i++) out.push(
|
|
10276
|
+
for (let i = 0; i < n; i++) out.push(ip + 6 + i);
|
|
10070
10277
|
return true;
|
|
10071
10278
|
}
|
|
10072
10279
|
case OP_SEQ:
|
|
10073
10280
|
case OP_SEQV: {
|
|
10074
10281
|
const n = code[ip + 1];
|
|
10075
|
-
for (let i = 0; i < n; i++) out.push(
|
|
10282
|
+
for (let i = 0; i < n; i++) out.push(ip + 2 + i);
|
|
10076
10283
|
return true;
|
|
10077
10284
|
}
|
|
10078
10285
|
case OP_SEQX: {
|
|
10079
10286
|
const n = code[ip + 2];
|
|
10080
|
-
for (let i = 0; i < n; i++) out.push(
|
|
10287
|
+
for (let i = 0; i < n; i++) out.push(ip + 3 + i);
|
|
10081
10288
|
return true;
|
|
10082
10289
|
}
|
|
10083
10290
|
case OP_CHOICE: {
|
|
10084
10291
|
const n = code[ip + 2];
|
|
10085
|
-
for (let i = 0; i < n; i++) out.push(
|
|
10292
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + i);
|
|
10086
10293
|
return true;
|
|
10087
10294
|
}
|
|
10088
10295
|
// Arms are stride-2 from `ip + 4` — the gate word sits beside each arm offset.
|
|
10089
10296
|
case OP_GREEDY: {
|
|
10090
|
-
out.push(
|
|
10297
|
+
out.push(ip + 1);
|
|
10091
10298
|
const n = code[ip + 2];
|
|
10092
|
-
for (let i = 0; i < n; i++) out.push(
|
|
10299
|
+
for (let i = 0; i < n; i++) out.push(ip + 4 + 2 * i);
|
|
10093
10300
|
return true;
|
|
10094
10301
|
}
|
|
10095
10302
|
case OP_REP:
|
|
10096
10303
|
case OP_REPV:
|
|
10097
|
-
out.push(
|
|
10098
|
-
if (code[ip + 4] >= 0) out.push(
|
|
10304
|
+
out.push(ip + 1);
|
|
10305
|
+
if (code[ip + 4] >= 0) out.push(ip + 4);
|
|
10099
10306
|
return true;
|
|
10100
10307
|
default:
|
|
10101
10308
|
return false;
|
|
@@ -10910,7 +11117,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
10910
11117
|
const swapLegal = !cfg.trackLines;
|
|
10911
11118
|
const hostCst = cfg.hostCst;
|
|
10912
11119
|
const LOGS = (prog.triviaSpecs?.length ?? 0) > 0 || cfg.inheritedTrivia === true;
|
|
10913
|
-
const
|
|
11120
|
+
const REC2 = prog.rec === 1 && cfg.tolerant;
|
|
10914
11121
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
10915
11122
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
10916
11123
|
const reachable = [...reachableSites(code, roots)];
|
|
@@ -10983,7 +11190,7 @@ function emitAssemblySource(t2, prog, cfg, extraIps = [], staticBuild = false, s
|
|
|
10983
11190
|
const op = code[ip];
|
|
10984
11191
|
sinkBits.set(
|
|
10985
11192
|
ip,
|
|
10986
|
-
op === OP_SCAN || !scanSinkNeutral && op === OP_LEX_PROGRAM && t2.lexPrograms[code[ip + 1]].scan !== void 0 ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT ||
|
|
11193
|
+
op === OP_SCAN || !scanSinkNeutral && op === OP_LEX_PROGRAM && t2.lexPrograms[code[ip + 1]].scan !== void 0 ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
|
|
10987
11194
|
);
|
|
10988
11195
|
}
|
|
10989
11196
|
const sinkKids = [];
|
|
@@ -11508,7 +11715,7 @@ if(v!==FAIL)return v
|
|
|
11508
11715
|
const err={_tag:'parseError',span:${prog.lines === 1 ? "spanLines(ctx,pos,pos)" : "new _SP(pos,pos)"},expected:${xf}}
|
|
11509
11716
|
const es=ctx._errors
|
|
11510
11717
|
if(es!==undefined)es.push(err)
|
|
11511
|
-
${
|
|
11718
|
+
${REC2 ? "if(ctx._tolerant===true)captureError(ctx,err)\n" : ""}ctx._fc=false
|
|
11512
11719
|
EC.e=pos
|
|
11513
11720
|
return err
|
|
11514
11721
|
}`;
|
|
@@ -11638,7 +11845,7 @@ return v
|
|
|
11638
11845
|
}
|
|
11639
11846
|
case OP_LEX_PROGRAM: {
|
|
11640
11847
|
const programId = code[ip + 1];
|
|
11641
|
-
const
|
|
11848
|
+
const run2 = hoist("lexProgram", `LEXPROG[${programId}]`);
|
|
11642
11849
|
const scanId = t2.lexPrograms[programId].scan;
|
|
11643
11850
|
if (scanId !== void 0) return `${head}
|
|
11644
11851
|
const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
|
|
@@ -11656,7 +11863,7 @@ ctx._cstTriviaLog=undefined
|
|
|
11656
11863
|
ctx._triviaLog=undefined
|
|
11657
11864
|
ctx._rootTriviaLog=undefined
|
|
11658
11865
|
let e
|
|
11659
|
-
try{e=${
|
|
11866
|
+
try{e=${run2}(input,pos,ctx,SCANS[${scanId}])}finally{
|
|
11660
11867
|
_pfScan=sScan
|
|
11661
11868
|
ctx.trivia=sTri
|
|
11662
11869
|
ctx.triviaKindLabels=sKinds
|
|
@@ -11675,7 +11882,7 @@ EC.e=e
|
|
|
11675
11882
|
return v
|
|
11676
11883
|
}`;
|
|
11677
11884
|
return `${head}
|
|
11678
|
-
const e=${
|
|
11885
|
+
const e=${run2}(input,pos,ctx)
|
|
11679
11886
|
if(e<0)return FAIL
|
|
11680
11887
|
const v=input.slice(pos,e)
|
|
11681
11888
|
if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,new _LF(v,new _SP(pos,e)))
|
|
@@ -11686,7 +11893,7 @@ return v
|
|
|
11686
11893
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
11687
11894
|
case OP_ATTEMPT: {
|
|
11688
11895
|
const child = link(code[ip + 1]);
|
|
11689
|
-
const clean = !
|
|
11896
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
11690
11897
|
const logs = clean && LOGS && failureLogRollback(prog, ip);
|
|
11691
11898
|
const p = tmp();
|
|
11692
11899
|
return `${head}
|
|
@@ -11752,7 +11959,7 @@ return null
|
|
|
11752
11959
|
}
|
|
11753
11960
|
case OP_OPT: {
|
|
11754
11961
|
const child = link(code[ip + 1]);
|
|
11755
|
-
const clean = !
|
|
11962
|
+
const clean = !REC2 && failureRollbackClean(prog, ip);
|
|
11756
11963
|
const logs = clean && LOGS && failureLogRollback(prog, ip);
|
|
11757
11964
|
const p = tmp();
|
|
11758
11965
|
return `${head}
|
|
@@ -11783,15 +11990,15 @@ return v
|
|
|
11783
11990
|
const childIp = code[base + i];
|
|
11784
11991
|
kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
|
|
11785
11992
|
}
|
|
11786
|
-
const sy =
|
|
11993
|
+
const sy = REC2 ? `${tmp()}sy` : "";
|
|
11787
11994
|
const pub = (i) => {
|
|
11788
11995
|
const s = sentRef(code[base + n + i]);
|
|
11789
11996
|
return s === "undefined" ? `ctx._sync=${sy}` : `ctx._sync=${s}??${sy}`;
|
|
11790
11997
|
};
|
|
11791
11998
|
const parts = [head];
|
|
11792
|
-
if (
|
|
11999
|
+
if (REC2) parts.push(`const ${sy}=ctx._sync`, "try{", pub(0));
|
|
11793
12000
|
parts.push(`const v0=${kids[0]}(input,pos,ctx)`, "if(v0===FAIL)return FAIL");
|
|
11794
|
-
const close = () =>
|
|
12001
|
+
const close = () => REC2 ? `${parts.join("\n")}
|
|
11795
12002
|
}finally{ctx._sync=${sy}}
|
|
11796
12003
|
}` : `${parts.join("\n")}
|
|
11797
12004
|
}`;
|
|
@@ -11804,7 +12011,7 @@ return v
|
|
|
11804
12011
|
for (let i = 1; i < n; i++) {
|
|
11805
12012
|
const vn = `v${i}`;
|
|
11806
12013
|
parts.push(`let ${vn}`);
|
|
11807
|
-
if (
|
|
12014
|
+
if (REC2) parts.push(pub(i));
|
|
11808
12015
|
const childIp = code[base + i];
|
|
11809
12016
|
if (code[childIp] === OP_ADJ) {
|
|
11810
12017
|
const negated = code[childIp + 1] === 1;
|
|
@@ -11909,7 +12116,7 @@ return FAIL
|
|
|
11909
12116
|
if (maskable) maskPlan.push(~di);
|
|
11910
12117
|
const p = tmp();
|
|
11911
12118
|
const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
|
|
11912
|
-
const rollbackMask =
|
|
12119
|
+
const rollbackMask = REC2 ? -1 : encodedRollbackMask;
|
|
11913
12120
|
const hasRollback = rollbackMask !== 0;
|
|
11914
12121
|
const logMask = rollbackMask === -1 || !LOGS ? 0 : choiceLogRollbackMask(prog, ip);
|
|
11915
12122
|
const choiceMark = hasRollback ? emitMark(p, L.buf, L.raw, sinks) : "";
|
|
@@ -12162,7 +12369,7 @@ return [key,v]
|
|
|
12162
12369
|
const collect = op === OP_REP;
|
|
12163
12370
|
let itemCls;
|
|
12164
12371
|
let itemAscii = false;
|
|
12165
|
-
if (!
|
|
12372
|
+
if (!REC2) {
|
|
12166
12373
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
12167
12374
|
if (itemClassIndex >= 0) {
|
|
12168
12375
|
const resolved = t2.cc[itemClassIndex];
|
|
@@ -12175,14 +12382,14 @@ return [key,v]
|
|
|
12175
12382
|
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
12176
12383
|
let sepCls;
|
|
12177
12384
|
let sepAscii = false;
|
|
12178
|
-
if (!
|
|
12385
|
+
if (!REC2 && sepIp >= 0 && (code[ip + 5] & 8) !== 0 && !leadingTriviaFieldAt(code, k, sepIp) && !rowNullable(code, k, sepIp, nullable2)) {
|
|
12179
12386
|
const resolved = t2.cc[code[ip + 8]];
|
|
12180
12387
|
const ci = classes.push([resolved]) - 1;
|
|
12181
12388
|
classPlan.push([code[ip + 8]]);
|
|
12182
12389
|
sepCls = hoist("rs", `CLS[${ci}][0]`);
|
|
12183
12390
|
sepAscii = isAsciiOnlyClass(resolved);
|
|
12184
12391
|
}
|
|
12185
|
-
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !
|
|
12392
|
+
const gapIp = !gapNeutral && sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
12186
12393
|
let gapCode = (_rb) => "";
|
|
12187
12394
|
if (gapIp >= 0) {
|
|
12188
12395
|
const row = code[gapIp + 2];
|
|
@@ -12267,11 +12474,11 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
12267
12474
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
12268
12475
|
}`;
|
|
12269
12476
|
const my = `${p}my`;
|
|
12270
|
-
const recFx = !
|
|
12271
|
-
const sepSent =
|
|
12477
|
+
const recFx = !REC2 ? "" : (flags & 16) !== 0 ? "[]" : fxRef(code[ip + 6]);
|
|
12478
|
+
const sepSent = REC2 ? sentRef(code[ip + 7]) : "undefined";
|
|
12272
12479
|
const recSent = sep === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
12273
12480
|
const recGate = sep !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
12274
|
-
const recBranch = !
|
|
12481
|
+
const recBranch = !REC2 ? "" : `if(ctx._tolerant===true&&${my}!==undefined&&${recGate}!matchesAt(${my},input,itemStart,ctx)){
|
|
12275
12482
|
${sep === void 0 ? `${rb}
|
|
12276
12483
|
` : ""}const rr=recoverScan(input,itemStart,ctx,${recSent},${recFx})
|
|
12277
12484
|
${collect ? "out.push(rr.error)\n" : ""}captureError(ctx,rr.error)
|
|
@@ -12282,7 +12489,7 @@ continue
|
|
|
12282
12489
|
`;
|
|
12283
12490
|
return `${head}
|
|
12284
12491
|
const out=${collect ? "[]" : "undefined"}
|
|
12285
|
-
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${
|
|
12492
|
+
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
|
|
12286
12493
|
` : ""}${itemCls === void 0 && sepCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
12287
12494
|
`}let cur=pos
|
|
12288
12495
|
let count=0
|
|
@@ -12325,7 +12532,7 @@ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
|
12325
12532
|
`}${gapCode(rb)}ctx._fc=false
|
|
12326
12533
|
const v=${child}(input,itemStart,ctx)
|
|
12327
12534
|
${gapIp >= 0 ? "if(gapped)GAP.at=-1\n" : ""}if(v===FAIL){
|
|
12328
|
-
${
|
|
12535
|
+
${REC2 ? `if(ctx._fc===true){
|
|
12329
12536
|
${rb}
|
|
12330
12537
|
return FAIL
|
|
12331
12538
|
}
|
|
@@ -12551,13 +12758,13 @@ return nd
|
|
|
12551
12758
|
}
|
|
12552
12759
|
}
|
|
12553
12760
|
const served = (ip) => select === void 0 || select.has(resolveAlias(ip));
|
|
12554
|
-
const
|
|
12761
|
+
const ruleEntries2 = [];
|
|
12555
12762
|
for (const [rname, entryIp] of Object.entries(prog.rules)) {
|
|
12556
12763
|
if (!served(entryIp)) continue;
|
|
12557
12764
|
const target = link(entryIp);
|
|
12558
12765
|
const rn = `_r_${rname.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
12559
12766
|
bodies.push(`const ${rn}=${target}`);
|
|
12560
|
-
|
|
12767
|
+
ruleEntries2.push(`${q(rname)}:${rn}`);
|
|
12561
12768
|
}
|
|
12562
12769
|
const extra = [];
|
|
12563
12770
|
const exported = /* @__PURE__ */ new Set();
|
|
@@ -12623,7 +12830,7 @@ _pfHost=prior[1]
|
|
|
12623
12830
|
EC.e=prior[2]
|
|
12624
12831
|
}
|
|
12625
12832
|
return{
|
|
12626
|
-
pieces:{${
|
|
12833
|
+
pieces:{${ruleEntries2.join(",")}},
|
|
12627
12834
|
byIp:{${extra.join(",")}},
|
|
12628
12835
|
end:function(){return EC.e},
|
|
12629
12836
|
begin:_begin,
|
|
@@ -12732,31 +12939,31 @@ function lines(prefix, body, options = {}) {
|
|
|
12732
12939
|
_def: { tag: "lines", prefix, body, ...first === void 0 ? {} : { first }, ...lazy === void 0 ? {} : { lazy } },
|
|
12733
12940
|
parse(input, pos, ctx) {
|
|
12734
12941
|
const c = ctx;
|
|
12735
|
-
const
|
|
12736
|
-
|
|
12737
|
-
const
|
|
12942
|
+
const probe2 = createDetachedParseContext(false, ctx.state);
|
|
12943
|
+
probe2.lineView = c.lineView;
|
|
12944
|
+
const run2 = [];
|
|
12738
12945
|
const parts = [];
|
|
12739
12946
|
let offset = 0;
|
|
12740
12947
|
for (let start = pos; start < input.length || start === pos; ) {
|
|
12741
12948
|
let end2 = input.indexOf("\n", start);
|
|
12742
12949
|
if (end2 < 0) end2 = input.length;
|
|
12743
|
-
|
|
12744
|
-
const head = (
|
|
12950
|
+
probe2._columnsSplit = void 0;
|
|
12951
|
+
const head = (run2.length === 0 ? opening : prefix).parse(input, start, probe2);
|
|
12745
12952
|
let content;
|
|
12746
12953
|
let joined;
|
|
12747
12954
|
if (head.ok && head.span.end <= end2) {
|
|
12748
12955
|
content = head.span.end;
|
|
12749
12956
|
joined = "prefix";
|
|
12750
|
-
} else if (
|
|
12957
|
+
} else if (run2.length === 0) {
|
|
12751
12958
|
return { ok: false, expected: head.ok ? ["line prefix"] : head.expected, span: { start, end: start } };
|
|
12752
|
-
} else if (lazy !== void 0 && lazy.parse(input, start,
|
|
12959
|
+
} else if (lazy !== void 0 && lazy.parse(input, start, probe2).ok) {
|
|
12753
12960
|
content = start;
|
|
12754
12961
|
joined = "lazy";
|
|
12755
12962
|
} else break;
|
|
12756
|
-
const mark =
|
|
12963
|
+
const mark = probe2._columnsSplit;
|
|
12757
12964
|
const here = columnAt(input, content, c);
|
|
12758
12965
|
const split = joined === "prefix" && mark !== void 0 && mark.at === content ? mark.split : here.split;
|
|
12759
|
-
|
|
12966
|
+
run2.push({ offset, source: content, end: end2, column: here.column + (split - here.split), split, lazy: joined === "lazy" });
|
|
12760
12967
|
const text = input.slice(content, end2);
|
|
12761
12968
|
const newline = end2 < input.length;
|
|
12762
12969
|
parts.push(newline ? `${text}
|
|
@@ -12765,11 +12972,11 @@ function lines(prefix, body, options = {}) {
|
|
|
12765
12972
|
start = end2 + 1;
|
|
12766
12973
|
if (!newline) break;
|
|
12767
12974
|
}
|
|
12768
|
-
const view = { lines:
|
|
12975
|
+
const view = { lines: run2, parent: c.lineView };
|
|
12769
12976
|
const saved = c.lineView, starts = c._lineStarts, lineIndex = c._lineIndex, scanned = c._lineScannedTo, probing = c._probe;
|
|
12770
12977
|
const errors = c._errors?.length ?? 0;
|
|
12771
12978
|
let cursor = -1;
|
|
12772
|
-
if (probing !== void 0) for (const line2 of
|
|
12979
|
+
if (probing !== void 0) for (const line2 of run2) {
|
|
12773
12980
|
if (probing.offset >= line2.source && probing.offset <= line2.end) {
|
|
12774
12981
|
cursor = line2.offset + probing.offset - line2.source;
|
|
12775
12982
|
break;
|
|
@@ -12802,8 +13009,8 @@ function lines(prefix, body, options = {}) {
|
|
|
12802
13009
|
}
|
|
12803
13010
|
const stop = result.span.end;
|
|
12804
13011
|
const index = lineIndexAt(view, stop);
|
|
12805
|
-
const line =
|
|
12806
|
-
const end = stop === line.offset && index > 0 ?
|
|
13012
|
+
const line = run2[index];
|
|
13013
|
+
const end = stop === line.offset && index > 0 ? run2[index - 1].end + 1 : stop - line.offset > line.end - line.source ? line.end + 1 : line.source + (stop - line.offset);
|
|
12807
13014
|
recordLineRangeFromContext(c, input, pos, end);
|
|
12808
13015
|
return { ok: true, value: result.value, span: { start: pos, end } };
|
|
12809
13016
|
}
|
|
@@ -12912,12 +13119,12 @@ function literal(value, opts = {}) {
|
|
|
12912
13119
|
}
|
|
12913
13120
|
|
|
12914
13121
|
// src/combinators/ref.ts
|
|
12915
|
-
function withRuleTrivia(trivia2, ctx,
|
|
13122
|
+
function withRuleTrivia(trivia2, ctx, run2) {
|
|
12916
13123
|
const savedLabels = ctx.triviaKindLabels;
|
|
12917
13124
|
ctx.trivia = trivia2;
|
|
12918
13125
|
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
12919
13126
|
try {
|
|
12920
|
-
return
|
|
13127
|
+
return run2();
|
|
12921
13128
|
} finally {
|
|
12922
13129
|
ctx.trivia = void 0;
|
|
12923
13130
|
ctx.triviaKindLabels = savedLabels;
|
|
@@ -13419,6 +13626,19 @@ function failCleanAnalysis(code) {
|
|
|
13419
13626
|
// src/cst/host-mode.ts
|
|
13420
13627
|
var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
|
|
13421
13628
|
var FUSED_HOST_ELIDED = /* @__PURE__ */ Symbol.for("parseman.fusedHostElided");
|
|
13629
|
+
function assertHostModeCompatible(mode, build, hostBranchElided = true) {
|
|
13630
|
+
const isCstHost = build?._parsemanCstOutput === true;
|
|
13631
|
+
if (mode === "ast" && isCstHost && hostBranchElided) {
|
|
13632
|
+
throw new Error(
|
|
13633
|
+
"parseman: this parser was compiled for host mode \"ast\" (the default), so its nodes build through their own `build` callbacks and no positioned-CST branch was emitted. It cannot be driven with a positioned-CST host (cstBuildHost / a language-service host). Compile a second artifact from the SAME grammar with `compile(grammar, { hostMode: 'cst' })` \u2014 or, under the macro, a second `rules({ hostMode: 'cst' }, factory)` call site \u2014 and drive that one instead."
|
|
13634
|
+
);
|
|
13635
|
+
}
|
|
13636
|
+
if (mode === "cst" && !isCstHost) {
|
|
13637
|
+
throw new Error(
|
|
13638
|
+
'parseman: this parser was compiled for host mode "cst", so every node builds through a positioned-CST `ctx.build` host. Pass one (e.g. `{ build: cstBuildHost }`), or use an artifact compiled with the default `hostMode: "ast"` to get the grammar\'s own AST.'
|
|
13639
|
+
);
|
|
13640
|
+
}
|
|
13641
|
+
}
|
|
13422
13642
|
|
|
13423
13643
|
// src/grammar-metadata.ts
|
|
13424
13644
|
var GRAMMAR_COVERAGE_DEFINITIONS = /* @__PURE__ */ Symbol.for("parseman.grammarCoverageDefinitions");
|
|
@@ -13553,8 +13773,8 @@ function linkMatcher(m) {
|
|
|
13553
13773
|
}
|
|
13554
13774
|
var NO_COVERAGE = (_id) => {
|
|
13555
13775
|
};
|
|
13556
|
-
function cfgKeyOf(hostCst, trackLines, tolerant, coverage,
|
|
13557
|
-
return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (
|
|
13776
|
+
function cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe2, hostReadsChildren = true, inheritedTrivia = false) {
|
|
13777
|
+
return (hostCst ? 1 : 0) | (trackLines ? 2 : 0) | (tolerant ? 4 : 0) | (coverage ? 8 : 0) | (probe2 ? 16 : 0) | (hostReadsChildren ? 0 : 32) | (inheritedTrivia ? 64 : 0);
|
|
13558
13778
|
}
|
|
13559
13779
|
function cfgKey(c) {
|
|
13560
13780
|
return cfgKeyOf(c.hostCst, c.trackLines, c.tolerant, c.coverage, c.probe, c.hostReadsChildren, c.inheritedTrivia);
|
|
@@ -13571,7 +13791,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13571
13791
|
const triviaScan = t2.triviaScan;
|
|
13572
13792
|
const swapLegal = !cfg.trackLines;
|
|
13573
13793
|
const hostCst = cfg.hostCst;
|
|
13574
|
-
const
|
|
13794
|
+
const REC2 = prog.rec === 1 && cfg.tolerant;
|
|
13575
13795
|
const PROBE = cfg.probe;
|
|
13576
13796
|
const sentinels = /* @__PURE__ */ new Map();
|
|
13577
13797
|
function sentinelFor(cls) {
|
|
@@ -13621,7 +13841,7 @@ function assemble(t2, prog, cfg) {
|
|
|
13621
13841
|
const memo = /* @__PURE__ */ new Map();
|
|
13622
13842
|
const reached = /* @__PURE__ */ new Set();
|
|
13623
13843
|
const NULLABLE = /* @__PURE__ */ new Map();
|
|
13624
|
-
const CLEAN =
|
|
13844
|
+
const CLEAN = REC2 ? () => false : failCleanAnalysis(code);
|
|
13625
13845
|
function pushLeaf(ctx, value, s, e) {
|
|
13626
13846
|
const lf = new PlainLeaf9(value, new PlainSpan10(s, e));
|
|
13627
13847
|
pushCstLeaf(ctx, lf);
|
|
@@ -14332,7 +14552,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14332
14552
|
};
|
|
14333
14553
|
function lookaheadLedNode(ip) {
|
|
14334
14554
|
const op = code[ip];
|
|
14335
|
-
if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst ||
|
|
14555
|
+
if (op !== OP_NODE && op !== OP_NODE_TRACK || hostCst || REC2 || cfg.probe || cfg.coverage || cfg.trackLines) return void 0;
|
|
14336
14556
|
if (passCollapse(code, ip, hostCst) || gatedPassCollapse(code, ip, hostCst) !== void 0) return void 0;
|
|
14337
14557
|
const body = code[ip + 2];
|
|
14338
14558
|
const bop = code[body];
|
|
@@ -14708,7 +14928,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14708
14928
|
const child = link(code[ip + 1]);
|
|
14709
14929
|
const xf = fx[code[ip + 2]];
|
|
14710
14930
|
const expectSpan = (ctx, pos) => prog.lines === 1 ? spanLines(ctx, pos, pos) : new PlainSpan10(pos, pos);
|
|
14711
|
-
if (
|
|
14931
|
+
if (REC2) {
|
|
14712
14932
|
return (input, pos, ctx) => {
|
|
14713
14933
|
const v = child(input, pos, ctx);
|
|
14714
14934
|
if (v !== FAIL) return v;
|
|
@@ -15105,8 +15325,8 @@ function assemble(t2, prog, cfg) {
|
|
|
15105
15325
|
};
|
|
15106
15326
|
}
|
|
15107
15327
|
case OP_LEX_PROGRAM: {
|
|
15108
|
-
const
|
|
15109
|
-
const scanId =
|
|
15328
|
+
const run2 = t2.lexPrograms[code[ip + 1]];
|
|
15329
|
+
const scanId = run2.scan;
|
|
15110
15330
|
if (scanId !== void 0) {
|
|
15111
15331
|
return (input, pos, ctx) => {
|
|
15112
15332
|
const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
|
|
@@ -15127,7 +15347,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15127
15347
|
ctx._rootTriviaLog = void 0;
|
|
15128
15348
|
let end;
|
|
15129
15349
|
try {
|
|
15130
|
-
end =
|
|
15350
|
+
end = run2(input, pos, ctx, scans[scanId]);
|
|
15131
15351
|
} finally {
|
|
15132
15352
|
SCAN = sScan;
|
|
15133
15353
|
ctx.trivia = sTrivia;
|
|
@@ -15148,7 +15368,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15148
15368
|
};
|
|
15149
15369
|
}
|
|
15150
15370
|
return (input, pos, ctx) => {
|
|
15151
|
-
const end =
|
|
15371
|
+
const end = run2(input, pos, ctx);
|
|
15152
15372
|
if (end < 0) return FAIL;
|
|
15153
15373
|
const value = input.slice(pos, end);
|
|
15154
15374
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, new PlainLeaf9(value, new PlainSpan10(pos, end)));
|
|
@@ -15249,7 +15469,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15249
15469
|
return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
|
|
15250
15470
|
};
|
|
15251
15471
|
};
|
|
15252
|
-
if (
|
|
15472
|
+
if (REC2) {
|
|
15253
15473
|
const first2 = linkFirst();
|
|
15254
15474
|
const firstSync = sentinelFor(code[base + n]);
|
|
15255
15475
|
const runnerAt = (i) => {
|
|
@@ -15738,7 +15958,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15738
15958
|
if (n === 2 || n === 3) {
|
|
15739
15959
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
15740
15960
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
15741
|
-
const predecide = !
|
|
15961
|
+
const predecide = !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
15742
15962
|
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
15743
15963
|
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
15744
15964
|
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
@@ -15968,7 +16188,7 @@ function assemble(t2, prog, cfg) {
|
|
|
15968
16188
|
const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
|
|
15969
16189
|
const pBit = [];
|
|
15970
16190
|
const pRec = [];
|
|
15971
|
-
if (!
|
|
16191
|
+
if (!REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
|
|
15972
16192
|
for (let i = 0; i < n; i++) {
|
|
15973
16193
|
for (const terminal of largeChoiceLiteralPretest(code, k, code[base + i]) ?? []) {
|
|
15974
16194
|
pBit.push(1 << i);
|
|
@@ -16256,18 +16476,18 @@ function assemble(t2, prog, cfg) {
|
|
|
16256
16476
|
const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
|
|
16257
16477
|
const collect = op === OP_REP;
|
|
16258
16478
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
16259
|
-
const itemClass = !
|
|
16479
|
+
const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
16260
16480
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
16261
16481
|
const sepClassIndex = sepIp >= 0 && !sepLeads && (flags & 8) !== 0 ? code[ip + 8] : -1;
|
|
16262
|
-
const sepClass = !
|
|
16263
|
-
const gapIp = sepIp < 0 && min === 0 && !
|
|
16482
|
+
const sepClass = !REC2 && sepClassIndex >= 0 && !rowNullable(code, k, sepIp, NULLABLE) ? cc[sepClassIndex] : void 0;
|
|
16483
|
+
const gapIp = sepIp < 0 && min === 0 && !REC2 && code[code[ip + 1]] === OP_GAPGATE ? code[ip + 1] : -1;
|
|
16264
16484
|
const gapRow = gapIp >= 0 ? code[gapIp + 2] : -1;
|
|
16265
16485
|
const gapRe = gapIp >= 0 ? k[code[gapRow + 1]] : void 0;
|
|
16266
16486
|
const gapFollow = gapIp >= 0 ? cc[code[gapIp + 3]] : void 0;
|
|
16267
16487
|
const gapOther = gapIp >= 0 && code[gapIp + 4] >= 0 ? cc[code[gapIp + 4]] : void 0;
|
|
16268
16488
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
16269
16489
|
const itemClean = sepIp < 0 && CLEAN(code[ip + 1]) && !rowNullable(code, k, code[ip + 1], NULLABLE);
|
|
16270
|
-
if (
|
|
16490
|
+
if (REC2) {
|
|
16271
16491
|
const itemFx2 = fx[code[ip + 6]];
|
|
16272
16492
|
const recFx = (flags & 16) !== 0 ? EMPTY_FX2 : itemFx2;
|
|
16273
16493
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
@@ -16477,10 +16697,10 @@ function assemble(t2, prog, cfg) {
|
|
|
16477
16697
|
const hasFold = spec.byFold.size > 0;
|
|
16478
16698
|
const match = spec.match;
|
|
16479
16699
|
const matchN = match.length;
|
|
16480
|
-
const
|
|
16700
|
+
const routed2 = spec.routed;
|
|
16481
16701
|
const expected = spec.expected;
|
|
16482
16702
|
const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
|
|
16483
|
-
if (
|
|
16703
|
+
if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
|
|
16484
16704
|
for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
|
|
16485
16705
|
for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
|
|
16486
16706
|
for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
|
|
@@ -16505,7 +16725,7 @@ function assemble(t2, prog, cfg) {
|
|
|
16505
16725
|
const classify = hasFold ? matchBlock === void 0 ? (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) : (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) ?? matchBlock(key) : matchBlock === void 0 ? (key) => byKey.get(key) : (key) => byKey.get(key) ?? matchBlock(key);
|
|
16506
16726
|
const neverBranch = () => FAIL;
|
|
16507
16727
|
const bindArms = (start) => {
|
|
16508
|
-
const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]),
|
|
16728
|
+
const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
|
|
16509
16729
|
const next = start + 4 < n ? bindArms(start + 4) : void 0;
|
|
16510
16730
|
return dispatchArmBlock(
|
|
16511
16731
|
start,
|
|
@@ -16820,7 +17040,7 @@ function assemble(t2, prog, cfg) {
|
|
|
16820
17040
|
lead,
|
|
16821
17041
|
asciiFoldKey,
|
|
16822
17042
|
ROUTED_FX,
|
|
16823
|
-
|
|
17043
|
+
REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
16824
17044
|
matchesAt,
|
|
16825
17045
|
recoverScan,
|
|
16826
17046
|
orSentinel,
|
|
@@ -16909,7 +17129,7 @@ function assemble(t2, prog, cfg) {
|
|
|
16909
17129
|
// — a strict one emits no reader — and through the SAME `sentinelFor` memo
|
|
16910
17130
|
// the closure pieces use, so both engines resync to the same combinator
|
|
16911
17131
|
// object rather than to two separately constructed ones.
|
|
16912
|
-
|
|
17132
|
+
REC2 ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
16913
17133
|
matchesAt,
|
|
16914
17134
|
recoverScan,
|
|
16915
17135
|
orSentinel,
|
|
@@ -17124,9 +17344,9 @@ var AssemblyCache = class {
|
|
|
17124
17344
|
const trackLines = ctx.trackLines === true;
|
|
17125
17345
|
const tolerant = ctx._tolerant === true;
|
|
17126
17346
|
const coverage = ctx._grammarCoverage !== void 0;
|
|
17127
|
-
const
|
|
17347
|
+
const probe2 = ctx._probe !== void 0;
|
|
17128
17348
|
const inheritedTrivia = this.noOwnTrivia && ctx.trivia !== void 0;
|
|
17129
|
-
const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage,
|
|
17349
|
+
const key = cfgKeyOf(hostCst, trackLines, tolerant, coverage, probe2, hostReadsChildren, inheritedTrivia);
|
|
17130
17350
|
let cache = this.byCfg;
|
|
17131
17351
|
if (hostCaptureTrivia !== void 0) {
|
|
17132
17352
|
if (this.hostPredicate === hostCaptureTrivia) {
|
|
@@ -17146,7 +17366,7 @@ var AssemblyCache = class {
|
|
|
17146
17366
|
trackLines,
|
|
17147
17367
|
tolerant,
|
|
17148
17368
|
coverage,
|
|
17149
|
-
probe,
|
|
17369
|
+
probe: probe2,
|
|
17150
17370
|
inheritedTrivia
|
|
17151
17371
|
});
|
|
17152
17372
|
cache[key] = made;
|
|
@@ -18058,36 +18278,36 @@ function findRegexFragments(visited) {
|
|
|
18058
18278
|
if (branches.length >= 2) runs.add(branches.join("|"));
|
|
18059
18279
|
for (let i = 0; i < branches.length; i++) {
|
|
18060
18280
|
for (let n = 2; n <= Math.min(MAX_RUN, branches.length - i); n++) {
|
|
18061
|
-
const
|
|
18062
|
-
if (
|
|
18063
|
-
runs.add(
|
|
18281
|
+
const run2 = branches.slice(i, i + n).join("|");
|
|
18282
|
+
if (run2.length < 4) continue;
|
|
18283
|
+
runs.add(run2);
|
|
18064
18284
|
}
|
|
18065
18285
|
}
|
|
18066
18286
|
}
|
|
18067
|
-
for (const
|
|
18068
|
-
let e = byRun.get(
|
|
18287
|
+
for (const run2 of runs) {
|
|
18288
|
+
let e = byRun.get(run2);
|
|
18069
18289
|
if (e === void 0) {
|
|
18070
|
-
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches:
|
|
18071
|
-
byRun.set(
|
|
18290
|
+
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches: run2.split("|").length };
|
|
18291
|
+
byRun.set(run2, e);
|
|
18072
18292
|
}
|
|
18073
18293
|
if (e.nodes.has(v.p)) continue;
|
|
18074
18294
|
e.nodes.add(v.p);
|
|
18075
18295
|
e.occ.push({ site: v.site, source: d.source });
|
|
18076
18296
|
}
|
|
18077
18297
|
}
|
|
18078
|
-
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([
|
|
18298
|
+
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([run2, e]) => ({ run: run2, e, savings: (e.occ.length - 1) * run2.length })).sort((a, b) => b.e.occ.length - a.e.occ.length || b.savings - a.savings || b.run.length - a.run.length);
|
|
18079
18299
|
const kept = [];
|
|
18080
18300
|
for (const c of candidates) {
|
|
18081
18301
|
if (kept.some((k) => k.e.occ.length >= c.e.occ.length && `|${k.run}|`.includes(`|${c.run}|`))) continue;
|
|
18082
18302
|
kept.push(c);
|
|
18083
18303
|
}
|
|
18084
|
-
return kept.map(({ run, e }) => ({
|
|
18304
|
+
return kept.map(({ run: run2, e }) => ({
|
|
18085
18305
|
kind: "regex-fragment",
|
|
18086
|
-
id: `regex-fragment:${
|
|
18087
|
-
fragment:
|
|
18306
|
+
id: `regex-fragment:${run2}`,
|
|
18307
|
+
fragment: run2,
|
|
18088
18308
|
branches: e.branches,
|
|
18089
18309
|
count: e.occ.length,
|
|
18090
|
-
savings: (e.occ.length - 1) *
|
|
18310
|
+
savings: (e.occ.length - 1) * run2.length,
|
|
18091
18311
|
sources: e.occ.map((o) => `/${o.source}/`),
|
|
18092
18312
|
sites: e.occ.map((o) => o.site),
|
|
18093
18313
|
suggestion: `this ${e.branches}-branch alternation is re-spelled in ${e.occ.length} DISTINCT regex() terminals. Hoist it to one shared source string and interpolate it (\`new RegExp(\\\`\u2026\\\${OP}\u2026\\\`)\`) or lift the shared part into its own terminal \u2014 an edit to the operator set currently has to land in ${e.occ.length} places, and the analysis cannot tell you when one of them drifts.`
|
|
@@ -18941,9 +19161,9 @@ function withAmbient(ruleMap, opts) {
|
|
|
18941
19161
|
const addTrivia = opts.trivia !== void 0 && rule2._meta.grammarTrivia === void 0;
|
|
18942
19162
|
const addScanSkip = opts.scanSkip !== void 0 && rule2._meta.grammarScanSkip === void 0;
|
|
18943
19163
|
if (!addTrivia && !addScanSkip) return [name, rule2];
|
|
18944
|
-
let
|
|
18945
|
-
if (
|
|
18946
|
-
|
|
19164
|
+
let wrapped2 = wrappers.get(rule2);
|
|
19165
|
+
if (wrapped2 === void 0) {
|
|
19166
|
+
wrapped2 = {
|
|
18947
19167
|
...rule2,
|
|
18948
19168
|
_meta: {
|
|
18949
19169
|
...rule2._meta,
|
|
@@ -18951,9 +19171,9 @@ function withAmbient(ruleMap, opts) {
|
|
|
18951
19171
|
...addScanSkip ? { grammarScanSkip: opts.scanSkip } : {}
|
|
18952
19172
|
}
|
|
18953
19173
|
};
|
|
18954
|
-
wrappers.set(rule2,
|
|
19174
|
+
wrappers.set(rule2, wrapped2);
|
|
18955
19175
|
}
|
|
18956
|
-
return [name,
|
|
19176
|
+
return [name, wrapped2];
|
|
18957
19177
|
});
|
|
18958
19178
|
}
|
|
18959
19179
|
function compileRuleMapRunnable(ruleMap, opts = {}) {
|
|
@@ -19135,7 +19355,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
19135
19355
|
const emitOpts = { fnSources: sources };
|
|
19136
19356
|
const source = printable ? emitTableModule(artifact, { name: "grammar", ...emitOpts }) : "";
|
|
19137
19357
|
const inlineExpression = printable ? emitTableExpression(artifact, { entry: ENTRY, runtimeRef: opts.runtimeRef ?? "tableRules", ...emitOpts }) : null;
|
|
19138
|
-
const
|
|
19358
|
+
const runOnce2 = (input, pos, ctx) => entry(input, pos, ctx);
|
|
19139
19359
|
return {
|
|
19140
19360
|
source,
|
|
19141
19361
|
inlineExpression,
|
|
@@ -19149,10 +19369,10 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
19149
19369
|
// parser runs where a combinator does. A caller probing many positions
|
|
19150
19370
|
// passes one context and pays for none per call.
|
|
19151
19371
|
parse(input, pos = 0, ctx) {
|
|
19152
|
-
return
|
|
19372
|
+
return runOnce2(input, pos, ctx ?? createParseContext());
|
|
19153
19373
|
},
|
|
19154
19374
|
parseWithContext(input, parseCtx, pos = 0) {
|
|
19155
|
-
return
|
|
19375
|
+
return runOnce2(input, pos, parseCtx);
|
|
19156
19376
|
},
|
|
19157
19377
|
/**
|
|
19158
19378
|
* NO LONGER REFUSES. It used to throw unless the caller passed
|
|
@@ -19168,7 +19388,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
19168
19388
|
const errors = [];
|
|
19169
19389
|
ctx._errors = errors;
|
|
19170
19390
|
ctx._tolerant = true;
|
|
19171
|
-
const r =
|
|
19391
|
+
const r = runOnce2(input, pos, ctx);
|
|
19172
19392
|
return { ...r, errors };
|
|
19173
19393
|
}
|
|
19174
19394
|
};
|
|
@@ -19413,6 +19633,38 @@ function not(combinator) {
|
|
|
19413
19633
|
};
|
|
19414
19634
|
}
|
|
19415
19635
|
|
|
19636
|
+
// src/combinators/withCtx.ts
|
|
19637
|
+
function withCtx(extra, combinator) {
|
|
19638
|
+
const meta = {
|
|
19639
|
+
firstSet: combinator._meta.firstSet,
|
|
19640
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
19641
|
+
isTrivia: false
|
|
19642
|
+
};
|
|
19643
|
+
const parse2 = typeof extra === "function" ? (input, pos, ctx) => {
|
|
19644
|
+
const saved = ctx.state;
|
|
19645
|
+
ctx.state = extra(saved);
|
|
19646
|
+
try {
|
|
19647
|
+
return combinator.parse(input, pos, ctx);
|
|
19648
|
+
} finally {
|
|
19649
|
+
ctx.state = saved;
|
|
19650
|
+
}
|
|
19651
|
+
} : (input, pos, ctx) => {
|
|
19652
|
+
const saved = ctx.state;
|
|
19653
|
+
ctx.state = extra;
|
|
19654
|
+
try {
|
|
19655
|
+
return combinator.parse(input, pos, ctx);
|
|
19656
|
+
} finally {
|
|
19657
|
+
ctx.state = saved;
|
|
19658
|
+
}
|
|
19659
|
+
};
|
|
19660
|
+
return {
|
|
19661
|
+
_tag: "withCtx",
|
|
19662
|
+
_meta: meta,
|
|
19663
|
+
_def: { tag: "withCtx", extra, parser: combinator },
|
|
19664
|
+
parse: parse2
|
|
19665
|
+
};
|
|
19666
|
+
}
|
|
19667
|
+
|
|
19416
19668
|
// src/analysis/rebuild.ts
|
|
19417
19669
|
var FROZEN_TAGS = /* @__PURE__ */ new Set([
|
|
19418
19670
|
"dispatch",
|
|
@@ -19426,6 +19678,7 @@ var FROZEN_TAGS = /* @__PURE__ */ new Set([
|
|
|
19426
19678
|
"lines",
|
|
19427
19679
|
"columns"
|
|
19428
19680
|
]);
|
|
19681
|
+
var THAWED_TAGS = /* @__PURE__ */ new Set(["dispatch", "withCtx", "routed", "guard"]);
|
|
19429
19682
|
var CARRIED_META = [
|
|
19430
19683
|
"grammarTrivia",
|
|
19431
19684
|
"grammarScanSkip",
|
|
@@ -19464,7 +19717,9 @@ function subtreeContains(p, targets) {
|
|
|
19464
19717
|
walk(p);
|
|
19465
19718
|
return hit;
|
|
19466
19719
|
}
|
|
19467
|
-
function rebuildCombinator(root, replacements) {
|
|
19720
|
+
function rebuildCombinator(root, replacements, options = {}) {
|
|
19721
|
+
const thaw = options.thaw === true;
|
|
19722
|
+
const after = options.after ?? ((_p, out) => out);
|
|
19468
19723
|
const memo = /* @__PURE__ */ new Map();
|
|
19469
19724
|
const frozenKeys = /* @__PURE__ */ new Set();
|
|
19470
19725
|
const frozen = [];
|
|
@@ -19484,15 +19739,16 @@ function rebuildCombinator(root, replacements) {
|
|
|
19484
19739
|
return p;
|
|
19485
19740
|
}
|
|
19486
19741
|
const here = p._ruleName ?? rule2;
|
|
19487
|
-
if (FROZEN_TAGS.has(d.tag)) {
|
|
19742
|
+
if (FROZEN_TAGS.has(d.tag) && !(thaw && THAWED_TAGS.has(d.tag))) {
|
|
19488
19743
|
const key = JSON.stringify([here, d.tag]);
|
|
19489
19744
|
if (!frozenKeys.has(key)) {
|
|
19490
19745
|
frozenKeys.add(key);
|
|
19491
19746
|
frozen.push({ tag: d.tag, rule: here });
|
|
19492
19747
|
}
|
|
19493
19748
|
for (const t2 of subtreeContains(p, targets)) if (!unapplied.includes(t2)) unapplied.push(t2);
|
|
19494
|
-
|
|
19495
|
-
|
|
19749
|
+
const kept = after(p, p);
|
|
19750
|
+
memo.set(p, kept);
|
|
19751
|
+
return kept;
|
|
19496
19752
|
}
|
|
19497
19753
|
if (d.tag === "lazy") {
|
|
19498
19754
|
let target;
|
|
@@ -19529,6 +19785,14 @@ function rebuildCombinator(root, replacements) {
|
|
|
19529
19785
|
break;
|
|
19530
19786
|
}
|
|
19531
19787
|
case "choice": {
|
|
19788
|
+
if (d.gates.some((g) => g !== null) && thaw) {
|
|
19789
|
+
const unsafeChoice = choice;
|
|
19790
|
+
out = unsafeChoice(...d.parsers.map((arm, i) => {
|
|
19791
|
+
const gate = d.gates[i];
|
|
19792
|
+
return gate ? { combinator: one(arm), gate } : one(arm);
|
|
19793
|
+
}));
|
|
19794
|
+
break;
|
|
19795
|
+
}
|
|
19532
19796
|
if (d.gates.some((g) => g !== null)) {
|
|
19533
19797
|
const key = JSON.stringify([here, "choice(gated)"]);
|
|
19534
19798
|
if (!frozenKeys.has(key)) {
|
|
@@ -19536,8 +19800,9 @@ function rebuildCombinator(root, replacements) {
|
|
|
19536
19800
|
frozen.push({ tag: "choice(gated)", rule: here });
|
|
19537
19801
|
}
|
|
19538
19802
|
for (const t2 of subtreeContains(p, targets)) if (!unapplied.includes(t2)) unapplied.push(t2);
|
|
19539
|
-
|
|
19540
|
-
|
|
19803
|
+
const kept = after(p, p);
|
|
19804
|
+
memo.set(p, kept);
|
|
19805
|
+
return kept;
|
|
19541
19806
|
}
|
|
19542
19807
|
const kids = d.parsers.map(one);
|
|
19543
19808
|
out = choice(...kids);
|
|
@@ -19615,13 +19880,33 @@ function rebuildCombinator(root, replacements) {
|
|
|
19615
19880
|
frozen.push({ tag: "node(untyped+build+opts)", rule: here });
|
|
19616
19881
|
}
|
|
19617
19882
|
for (const t2 of subtreeContains(p, targets)) if (!unapplied.includes(t2)) unapplied.push(t2);
|
|
19618
|
-
|
|
19619
|
-
|
|
19883
|
+
const kept = after(p, p);
|
|
19884
|
+
memo.set(p, kept);
|
|
19885
|
+
return kept;
|
|
19620
19886
|
}
|
|
19621
19887
|
out = d.type === void 0 ? d.build === void 0 ? node(one(d.parser), opts) : node(one(d.parser), d.build) : node(d.type, one(d.parser), d.build, opts);
|
|
19622
19888
|
if (d.buildRawUnused === true && out._def.tag === "node") out._def.buildRawUnused = true;
|
|
19623
19889
|
break;
|
|
19624
19890
|
}
|
|
19891
|
+
case "dispatch": {
|
|
19892
|
+
const arms = d.cases.map((e) => when(e.keys, one(e.parser), e.caseInsensitive ? { caseInsensitive: true } : void 0));
|
|
19893
|
+
for (const e of d.matchers ?? []) {
|
|
19894
|
+
arms.push(when(dispatchMatcher(e), one(e.parser), e.caseInsensitive ? { caseInsensitive: true } : void 0));
|
|
19895
|
+
}
|
|
19896
|
+
if (d.otherwise) arms.push(otherwise(one(d.otherwise), d.otherwiseCommit === false ? { commit: false } : void 0));
|
|
19897
|
+
const unsafeDispatch = dispatch;
|
|
19898
|
+
out = unsafeDispatch(one(d.selector), ...arms);
|
|
19899
|
+
break;
|
|
19900
|
+
}
|
|
19901
|
+
case "withCtx":
|
|
19902
|
+
out = withCtx(d.extra, one(d.parser));
|
|
19903
|
+
break;
|
|
19904
|
+
case "routed":
|
|
19905
|
+
out = d.fallback === void 0 ? routed() : routed(one(d.fallback));
|
|
19906
|
+
break;
|
|
19907
|
+
case "guard":
|
|
19908
|
+
out = p;
|
|
19909
|
+
break;
|
|
19625
19910
|
case "grammar": {
|
|
19626
19911
|
const inner = one(d.parser);
|
|
19627
19912
|
out = parser({
|
|
@@ -19639,13 +19924,15 @@ function rebuildCombinator(root, replacements) {
|
|
|
19639
19924
|
frozen.push({ tag: d.tag, rule: here });
|
|
19640
19925
|
}
|
|
19641
19926
|
for (const t2 of subtreeContains(p, targets)) if (!unapplied.includes(t2)) unapplied.push(t2);
|
|
19642
|
-
|
|
19643
|
-
|
|
19927
|
+
const kept = after(p, p);
|
|
19928
|
+
memo.set(p, kept);
|
|
19929
|
+
return kept;
|
|
19644
19930
|
}
|
|
19645
19931
|
}
|
|
19646
19932
|
carryStamps(p, out);
|
|
19647
|
-
|
|
19648
|
-
|
|
19933
|
+
const done = after(p, out);
|
|
19934
|
+
memo.set(p, done);
|
|
19935
|
+
return done;
|
|
19649
19936
|
};
|
|
19650
19937
|
const rebuilt = go(root, root._ruleName ?? "<entry>");
|
|
19651
19938
|
frozen.sort((a, b) => a.rule < b.rule ? -1 : a.rule > b.rule ? 1 : a.tag < b.tag ? -1 : a.tag > b.tag ? 1 : 0);
|
|
@@ -20882,9 +21169,715 @@ function measureChoiceCost(c, samples, arms) {
|
|
|
20882
21169
|
function armFirstSets(choiceArms2) {
|
|
20883
21170
|
return choiceArms2.map((a) => ({ firstSet: firstSetOf(a) }));
|
|
20884
21171
|
}
|
|
21172
|
+
|
|
21173
|
+
// src/cst/trivia-entries.ts
|
|
21174
|
+
var EMPTY_INDICES = Object.freeze([]);
|
|
21175
|
+
var EMPTY_GAPS = Object.freeze([]);
|
|
21176
|
+
var SELECTED_ROOT_STRIDE = 5;
|
|
21177
|
+
function buildRootTriviaIndex(log, labels) {
|
|
21178
|
+
const length = Math.floor(log.length / SELECTED_ROOT_STRIDE);
|
|
21179
|
+
const markerOffset = (i) => i * SELECTED_ROOT_STRIDE;
|
|
21180
|
+
const ownedRangeStart = (i) => log[markerOffset(i)];
|
|
21181
|
+
const ownedRangeEnd = (i) => log[markerOffset(i) + 1];
|
|
21182
|
+
const markerStart = (i) => log[markerOffset(i) + 2];
|
|
21183
|
+
const markerEnd = (i) => log[markerOffset(i) + 3];
|
|
21184
|
+
const markerKind = (i) => log[markerOffset(i) + 4];
|
|
21185
|
+
const entries = {
|
|
21186
|
+
length,
|
|
21187
|
+
labels,
|
|
21188
|
+
stride: SELECTED_ROOT_STRIDE,
|
|
21189
|
+
start: markerStart,
|
|
21190
|
+
end: markerEnd,
|
|
21191
|
+
insertIndex: () => void 0,
|
|
21192
|
+
kindIndex: markerKind,
|
|
21193
|
+
kind(i) {
|
|
21194
|
+
return labels[markerKind(i)];
|
|
21195
|
+
},
|
|
21196
|
+
text(i, input) {
|
|
21197
|
+
return input.slice(markerStart(i), markerEnd(i));
|
|
21198
|
+
}
|
|
21199
|
+
};
|
|
21200
|
+
const lowerBound = (offset, by) => {
|
|
21201
|
+
let lo = 0;
|
|
21202
|
+
let hi = length;
|
|
21203
|
+
while (lo < hi) {
|
|
21204
|
+
const mid = lo + hi >>> 1;
|
|
21205
|
+
if (by(mid) < offset) lo = mid + 1;
|
|
21206
|
+
else hi = mid;
|
|
21207
|
+
}
|
|
21208
|
+
return lo;
|
|
21209
|
+
};
|
|
21210
|
+
const gapRowsAt = (offset, direction) => {
|
|
21211
|
+
const edge = direction === "before" ? ownedRangeEnd : ownedRangeStart;
|
|
21212
|
+
let first = lowerBound(offset, edge);
|
|
21213
|
+
if (first === length || edge(first) !== offset) return void 0;
|
|
21214
|
+
const start = ownedRangeStart(first);
|
|
21215
|
+
const end = ownedRangeEnd(first);
|
|
21216
|
+
while (first > 0 && ownedRangeStart(first - 1) === start && ownedRangeEnd(first - 1) === end) first--;
|
|
21217
|
+
let last = first + 1;
|
|
21218
|
+
while (last < length && ownedRangeStart(last) === start && ownedRangeEnd(last) === end) last++;
|
|
21219
|
+
return [first, last];
|
|
21220
|
+
};
|
|
21221
|
+
const indices = (first, last) => {
|
|
21222
|
+
const out = [];
|
|
21223
|
+
for (let i = first; i < last; i++) out.push(i);
|
|
21224
|
+
return out;
|
|
21225
|
+
};
|
|
21226
|
+
const makeGap = (first, last) => {
|
|
21227
|
+
const start = ownedRangeStart(first);
|
|
21228
|
+
const end = ownedRangeEnd(first);
|
|
21229
|
+
let entryIndices;
|
|
21230
|
+
return {
|
|
21231
|
+
start,
|
|
21232
|
+
end,
|
|
21233
|
+
get entryIndices() {
|
|
21234
|
+
return entryIndices ??= indices(first, last);
|
|
21235
|
+
},
|
|
21236
|
+
hasKind(kind) {
|
|
21237
|
+
for (let i = first; i < last; i++) {
|
|
21238
|
+
if (labels[markerKind(i)] === kind) return true;
|
|
21239
|
+
}
|
|
21240
|
+
return false;
|
|
21241
|
+
},
|
|
21242
|
+
text(input) {
|
|
21243
|
+
return input.slice(start, end);
|
|
21244
|
+
}
|
|
21245
|
+
};
|
|
21246
|
+
};
|
|
21247
|
+
let maps;
|
|
21248
|
+
const getMaps = () => {
|
|
21249
|
+
if (maps !== void 0) return maps;
|
|
21250
|
+
const before = /* @__PURE__ */ new Map();
|
|
21251
|
+
const after = /* @__PURE__ */ new Map();
|
|
21252
|
+
const beforeGaps = /* @__PURE__ */ new Map();
|
|
21253
|
+
const afterGaps = /* @__PURE__ */ new Map();
|
|
21254
|
+
const gaps = [];
|
|
21255
|
+
for (let first = 0; first < length; ) {
|
|
21256
|
+
let last = first + 1;
|
|
21257
|
+
while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
|
|
21258
|
+
const gap = makeGap(first, last);
|
|
21259
|
+
gaps.push(gap);
|
|
21260
|
+
afterGaps.set(gap.start, gap);
|
|
21261
|
+
beforeGaps.set(gap.end, gap);
|
|
21262
|
+
after.set(gap.start, [...gap.entryIndices]);
|
|
21263
|
+
before.set(gap.end, [...gap.entryIndices]);
|
|
21264
|
+
first = last;
|
|
21265
|
+
}
|
|
21266
|
+
maps = { before, after, beforeGaps, afterGaps, gaps };
|
|
21267
|
+
return maps;
|
|
21268
|
+
};
|
|
21269
|
+
return {
|
|
21270
|
+
entries,
|
|
21271
|
+
labels,
|
|
21272
|
+
get before() {
|
|
21273
|
+
return getMaps().before;
|
|
21274
|
+
},
|
|
21275
|
+
get after() {
|
|
21276
|
+
return getMaps().after;
|
|
21277
|
+
},
|
|
21278
|
+
entryIndicesBefore(offset) {
|
|
21279
|
+
const rows = gapRowsAt(offset, "before");
|
|
21280
|
+
return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
|
|
21281
|
+
},
|
|
21282
|
+
entryIndicesAfter(offset) {
|
|
21283
|
+
const rows = gapRowsAt(offset, "after");
|
|
21284
|
+
return rows ? indices(rows[0], rows[1]) : EMPTY_INDICES;
|
|
21285
|
+
},
|
|
21286
|
+
gapBefore(offset) {
|
|
21287
|
+
const rows = gapRowsAt(offset, "before");
|
|
21288
|
+
return rows ? makeGap(rows[0], rows[1]) : void 0;
|
|
21289
|
+
},
|
|
21290
|
+
gapAfter(offset) {
|
|
21291
|
+
const rows = gapRowsAt(offset, "after");
|
|
21292
|
+
return rows ? makeGap(rows[0], rows[1]) : void 0;
|
|
21293
|
+
},
|
|
21294
|
+
gaps() {
|
|
21295
|
+
return getMaps().gaps;
|
|
21296
|
+
},
|
|
21297
|
+
gapsWithKind(kind) {
|
|
21298
|
+
const kinds = typeof kind === "string" ? [kind] : kind;
|
|
21299
|
+
const matches2 = [];
|
|
21300
|
+
for (let first = 0; first < length; ) {
|
|
21301
|
+
let last = first + 1;
|
|
21302
|
+
while (last < length && ownedRangeStart(last) === ownedRangeStart(first) && ownedRangeEnd(last) === ownedRangeEnd(first)) last++;
|
|
21303
|
+
let matched = false;
|
|
21304
|
+
for (let i = first; i < last && !matched; i++) {
|
|
21305
|
+
const label2 = labels[markerKind(i)];
|
|
21306
|
+
for (const kind2 of kinds) {
|
|
21307
|
+
if (label2 === kind2) {
|
|
21308
|
+
matched = true;
|
|
21309
|
+
break;
|
|
21310
|
+
}
|
|
21311
|
+
}
|
|
21312
|
+
}
|
|
21313
|
+
if (matched) matches2.push(makeGap(first, last));
|
|
21314
|
+
first = last;
|
|
21315
|
+
}
|
|
21316
|
+
return matches2.length === 0 ? EMPTY_GAPS : matches2;
|
|
21317
|
+
}
|
|
21318
|
+
};
|
|
21319
|
+
}
|
|
21320
|
+
|
|
21321
|
+
// src/functional/run.ts
|
|
21322
|
+
var SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })";
|
|
21323
|
+
var REMOVED_RUN_RESULT_FIELDS = [
|
|
21324
|
+
[
|
|
21325
|
+
"triviaMap",
|
|
21326
|
+
`It was a dense root-trivia index built on every parse; root trivia is now an OPT-IN sparse capture, because most grammars paid for an index they never read. Migration: name the trivia labels your grammar defines \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia\`, whose \`.index\` carries the labels and gap lookups \`triviaMap\` exposed.`
|
|
21327
|
+
],
|
|
21328
|
+
[
|
|
21329
|
+
"triviaLog",
|
|
21330
|
+
`It was the flat \`start, end[, kindIndex]\` log every other trivia view was derived from, and it is no longer allocated at all \u2014 not empty, absent. Migration: request the labels you need \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia.rows\`. Do NOT reuse a stride-2/3 reader: rows are a different width and a different unit (one row per SELECTED marker, not one per trivia chunk), so an old loop reads confidently wrong offsets rather than failing.`
|
|
21331
|
+
],
|
|
21332
|
+
[
|
|
21333
|
+
"triviaKindLabels",
|
|
21334
|
+
`It was already optional, so nothing ever flagged its disappearance \u2014 and \`triviaKindMask(undefined, \u2026)\` means "capture everything", so reading it now silently WIDENS capture instead of erroring. Migration: request labels \u2014 ${SELECT_EXAMPLE} \u2014 then the set you asked for is \`RunResult.rootTrivia.select\` and the resolved table is \`RunResult.rootTrivia.index.labels\`.`
|
|
21335
|
+
]
|
|
21336
|
+
];
|
|
21337
|
+
var RunResultRecord = class {
|
|
21338
|
+
constructor(ok, value, span, expected, errors, unconsumedFrom) {
|
|
21339
|
+
this.ok = ok;
|
|
21340
|
+
this.value = value;
|
|
21341
|
+
this.span = span;
|
|
21342
|
+
this.expected = expected;
|
|
21343
|
+
this.errors = errors;
|
|
21344
|
+
this.unconsumedFrom = unconsumedFrom;
|
|
21345
|
+
}
|
|
21346
|
+
};
|
|
21347
|
+
var RunResultWithRootTrivia = class {
|
|
21348
|
+
constructor(ok, value, span, expected, errors, rootTrivia, unconsumedFrom) {
|
|
21349
|
+
this.ok = ok;
|
|
21350
|
+
this.value = value;
|
|
21351
|
+
this.span = span;
|
|
21352
|
+
this.expected = expected;
|
|
21353
|
+
this.errors = errors;
|
|
21354
|
+
this.rootTrivia = rootTrivia;
|
|
21355
|
+
this.unconsumedFrom = unconsumedFrom;
|
|
21356
|
+
}
|
|
21357
|
+
};
|
|
21358
|
+
for (const proto of [RunResultRecord.prototype, RunResultWithRootTrivia.prototype]) {
|
|
21359
|
+
for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
|
|
21360
|
+
Object.defineProperty(proto, name, {
|
|
21361
|
+
configurable: true,
|
|
21362
|
+
enumerable: false,
|
|
21363
|
+
get() {
|
|
21364
|
+
throw new TypeError(
|
|
21365
|
+
`RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`
|
|
21366
|
+
);
|
|
21367
|
+
}
|
|
21368
|
+
});
|
|
21369
|
+
}
|
|
21370
|
+
}
|
|
21371
|
+
var invoke = (r, input, pos, ctx) => typeof r === "function" ? r(input, pos, ctx) : r.parse(input, pos, ctx);
|
|
21372
|
+
function ambientTriviaFromRunnable(r) {
|
|
21373
|
+
if (!r) return void 0;
|
|
21374
|
+
if (typeof r === "function") return r._meta?.grammarTrivia;
|
|
21375
|
+
if (r._meta.isTrivia) return void 0;
|
|
21376
|
+
return r._meta.grammarTrivia ?? (r._def.tag === "grammar" ? r._def.triviaParser : void 0);
|
|
21377
|
+
}
|
|
21378
|
+
function triviaKindLabelsFromRunnable(r) {
|
|
21379
|
+
if (!r) return void 0;
|
|
21380
|
+
if (typeof r === "function") return r._meta?.triviaKindLabels;
|
|
21381
|
+
const grammarTrivia = r._meta.grammarTrivia;
|
|
21382
|
+
return grammarTrivia?._meta.triviaKindLabels ?? r._meta.triviaKindLabels ?? (r._def.tag === "grammar" ? r._def.triviaParser?._meta.triviaKindLabels : void 0);
|
|
21383
|
+
}
|
|
21384
|
+
function rootTriviaClassifiedFromRunnable(r) {
|
|
21385
|
+
if (!r) return false;
|
|
21386
|
+
if (typeof r === "function") return r._meta?.rootTriviaClassified === true;
|
|
21387
|
+
const grammarTrivia = r._meta.grammarTrivia;
|
|
21388
|
+
return grammarTrivia?._meta.rootTriviaClassified === true || r._meta.rootTriviaClassified === true;
|
|
21389
|
+
}
|
|
21390
|
+
function makeSelectedRootLabelIndex(labels) {
|
|
21391
|
+
const index = /* @__PURE__ */ Object.create(null);
|
|
21392
|
+
for (let i = 0; i < labels.length; i++) {
|
|
21393
|
+
if (index[labels[i]] === void 0) index[labels[i]] = i;
|
|
21394
|
+
}
|
|
21395
|
+
return index;
|
|
21396
|
+
}
|
|
21397
|
+
function growSpanEnd(span, input, end) {
|
|
21398
|
+
if (span.endLine === void 0 || span.endColumn === void 0) {
|
|
21399
|
+
return { start: span.start, end };
|
|
21400
|
+
}
|
|
21401
|
+
let line = span.endLine;
|
|
21402
|
+
let column = span.endColumn;
|
|
21403
|
+
for (let i = span.end; i < end; i++) {
|
|
21404
|
+
if (input.charCodeAt(i) === 10) {
|
|
21405
|
+
line++;
|
|
21406
|
+
column = 1;
|
|
21407
|
+
} else {
|
|
21408
|
+
column++;
|
|
21409
|
+
}
|
|
21410
|
+
}
|
|
21411
|
+
return { ...span, end, endLine: line, endColumn: column };
|
|
21412
|
+
}
|
|
21413
|
+
function runOnce(entry, input, options) {
|
|
21414
|
+
if (typeof entry !== "function" && typeof entry?.parse !== "function") {
|
|
21415
|
+
throw new TypeError(
|
|
21416
|
+
`run(): start production is ${entry === null ? "null" : typeof entry}, not a rule \u2014 the requested grammar rule does not exist (check the rule name).`
|
|
21417
|
+
);
|
|
21418
|
+
}
|
|
21419
|
+
const rootTriviaSelection = options.rootTrivia?.select;
|
|
21420
|
+
const captureRootTrivia = rootTriviaSelection !== void 0 && rootTriviaSelection.length > 0;
|
|
21421
|
+
const selectedRootLog = captureRootTrivia ? [] : void 0;
|
|
21422
|
+
const selectedRootLabelIndex = captureRootTrivia ? makeSelectedRootLabelIndex(rootTriviaSelection) : void 0;
|
|
21423
|
+
const errors = [];
|
|
21424
|
+
const grammarTrivia = typeof entry !== "function" ? entry._meta.grammarTrivia : void 0;
|
|
21425
|
+
const grammarScanSkip = typeof entry !== "function" ? entry._meta.grammarScanSkip : void 0;
|
|
21426
|
+
const triviaKindLabels = triviaKindLabelsFromRunnable(entry) ?? triviaKindLabelsFromRunnable(options.trivia);
|
|
21427
|
+
if (captureRootTrivia && triviaKindLabels === void 0) {
|
|
21428
|
+
throw new TypeError("run(): rootTrivia.select requires labeled grammar trivia.");
|
|
21429
|
+
}
|
|
21430
|
+
if (captureRootTrivia) {
|
|
21431
|
+
for (const label2 of rootTriviaSelection) {
|
|
21432
|
+
if (!triviaKindLabels.includes(label2)) {
|
|
21433
|
+
throw new TypeError(`run(): rootTrivia.select contains unknown trivia label ${JSON.stringify(label2)}.`);
|
|
21434
|
+
}
|
|
21435
|
+
}
|
|
21436
|
+
}
|
|
21437
|
+
if (captureRootTrivia && !rootTriviaClassifiedFromRunnable(entry) && !rootTriviaClassifiedFromRunnable(options.trivia)) {
|
|
21438
|
+
throw new TypeError(
|
|
21439
|
+
"run(): rootTrivia.select requires classifiedTrivia() at the root."
|
|
21440
|
+
);
|
|
21441
|
+
}
|
|
21442
|
+
const stamped = entry;
|
|
21443
|
+
assertHostModeCompatible(
|
|
21444
|
+
typeof entry === "function" ? stamped[FUSED_HOST_MODE] ?? "ast" : entry._meta.grammarHostMode ?? "ast",
|
|
21445
|
+
options.build,
|
|
21446
|
+
typeof entry === "function" && stamped[FUSED_HOST_ELIDED] === true
|
|
21447
|
+
);
|
|
21448
|
+
const ctx = createParseContext();
|
|
21449
|
+
if (captureRootTrivia) {
|
|
21450
|
+
ctx._rootTriviaLog = selectedRootLog;
|
|
21451
|
+
ctx._rootTriviaKindIndex = selectedRootLabelIndex;
|
|
21452
|
+
ctx._rootTriviaStrictScopes = true;
|
|
21453
|
+
}
|
|
21454
|
+
ctx._errors = errors;
|
|
21455
|
+
ctx.build = options.build;
|
|
21456
|
+
ctx.state = options.state;
|
|
21457
|
+
if (grammarTrivia !== void 0) ctx.trivia = grammarTrivia;
|
|
21458
|
+
if (triviaKindLabels) ctx.triviaKindLabels = triviaKindLabels;
|
|
21459
|
+
if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
|
|
21460
|
+
if (options.triviaCaptureMask !== void 0) ctx._triviaCaptureMask = options.triviaCaptureMask;
|
|
21461
|
+
if (options.tolerant) {
|
|
21462
|
+
ctx._tolerant = true;
|
|
21463
|
+
ctx._rec = REC;
|
|
21464
|
+
}
|
|
21465
|
+
if (options.instrumentation !== void 0) {
|
|
21466
|
+
ctx._grammarCoverage = options.instrumentation._grammarCoverage;
|
|
21467
|
+
ctx._grammarTrace = options.instrumentation._grammarTrace;
|
|
21468
|
+
}
|
|
21469
|
+
const r = invoke(entry, input, 0, ctx);
|
|
21470
|
+
const value = r.ok ? r.value : void 0;
|
|
21471
|
+
let span = r.span ?? { start: 0, end: 0 };
|
|
21472
|
+
const expected = r.ok ? [] : [...new Set(r.expected ?? [])];
|
|
21473
|
+
let unconsumedFrom = null;
|
|
21474
|
+
if (r.ok) {
|
|
21475
|
+
let pos = span.end;
|
|
21476
|
+
const tail = options.trivia ?? ambientTriviaFromRunnable(entry);
|
|
21477
|
+
if (tail !== void 0 && pos < input.length) {
|
|
21478
|
+
const t2 = invoke(tail, input, pos, createParseContext());
|
|
21479
|
+
if (t2.ok && t2.span.end > pos) {
|
|
21480
|
+
span = growSpanEnd(span, input, t2.span.end);
|
|
21481
|
+
pos = t2.span.end;
|
|
21482
|
+
}
|
|
21483
|
+
}
|
|
21484
|
+
unconsumedFrom = pos < input.length ? pos : null;
|
|
21485
|
+
}
|
|
21486
|
+
return selectedRootLog !== void 0 && selectedRootLog.length > 0 ? new RunResultWithRootTrivia(
|
|
21487
|
+
r.ok,
|
|
21488
|
+
value,
|
|
21489
|
+
span,
|
|
21490
|
+
expected,
|
|
21491
|
+
errors,
|
|
21492
|
+
{
|
|
21493
|
+
rows: selectedRootLog,
|
|
21494
|
+
select: rootTriviaSelection,
|
|
21495
|
+
index: buildRootTriviaIndex(selectedRootLog, rootTriviaSelection)
|
|
21496
|
+
},
|
|
21497
|
+
unconsumedFrom
|
|
21498
|
+
) : new RunResultRecord(r.ok, value, span, expected, errors, unconsumedFrom);
|
|
21499
|
+
}
|
|
21500
|
+
function run(entry, input, options = {}) {
|
|
21501
|
+
return runOnce(entry, input, options);
|
|
21502
|
+
}
|
|
21503
|
+
|
|
21504
|
+
// src/table/backtrack-probe.ts
|
|
21505
|
+
var LOOKAROUND = /(?<!\\)\(\?<?[=!]/;
|
|
21506
|
+
function hasLookaround(re) {
|
|
21507
|
+
return LOOKAROUND.test(re.source);
|
|
21508
|
+
}
|
|
21509
|
+
function lookaroundExtent(re, input, start, end) {
|
|
21510
|
+
const probe2 = new RegExp(re.source, re.flags.includes("y") ? re.flags : `${re.flags}y`);
|
|
21511
|
+
const same = (n) => {
|
|
21512
|
+
probe2.lastIndex = start;
|
|
21513
|
+
return probe2.test(input.slice(0, end + n)) && probe2.lastIndex === end;
|
|
21514
|
+
};
|
|
21515
|
+
let lo = 0;
|
|
21516
|
+
let hi = input.length - end;
|
|
21517
|
+
while (lo < hi) {
|
|
21518
|
+
const mid = lo + hi >>> 1;
|
|
21519
|
+
if (same(mid)) hi = mid;
|
|
21520
|
+
else lo = mid + 1;
|
|
21521
|
+
}
|
|
21522
|
+
return lo;
|
|
21523
|
+
}
|
|
21524
|
+
var BacktrackRecorder = class {
|
|
21525
|
+
input = "";
|
|
21526
|
+
counts = zeroCounts();
|
|
21527
|
+
look = 0;
|
|
21528
|
+
opaque = 0;
|
|
21529
|
+
last = 0;
|
|
21530
|
+
furthest = 0;
|
|
21531
|
+
begin(input) {
|
|
21532
|
+
this.input = input;
|
|
21533
|
+
this.counts = zeroCounts();
|
|
21534
|
+
this.look = 0;
|
|
21535
|
+
this.opaque = 0;
|
|
21536
|
+
this.last = 0;
|
|
21537
|
+
this.furthest = 0;
|
|
21538
|
+
}
|
|
21539
|
+
/** The counts for the parse `begin` opened. Throws if a region was left open. */
|
|
21540
|
+
end() {
|
|
21541
|
+
if (this.look !== 0 || this.opaque !== 0) {
|
|
21542
|
+
throw new Error(`backtrack probe: unbalanced region (lookahead ${this.look}, opaque ${this.opaque})`);
|
|
21543
|
+
}
|
|
21544
|
+
return this.counts;
|
|
21545
|
+
}
|
|
21546
|
+
consume(start, end) {
|
|
21547
|
+
if (this.opaque > 0 || end <= start) return;
|
|
21548
|
+
const c = this.counts;
|
|
21549
|
+
if (this.look > 0) {
|
|
21550
|
+
c.lookaheadBytes += end - start;
|
|
21551
|
+
return;
|
|
21552
|
+
}
|
|
21553
|
+
if (start < this.last) c.rewinds++;
|
|
21554
|
+
if (start < this.furthest) c.bytesReread += Math.min(end, this.furthest) - start;
|
|
21555
|
+
this.last = end;
|
|
21556
|
+
if (end > this.furthest) this.furthest = end;
|
|
21557
|
+
}
|
|
21558
|
+
enterLookahead() {
|
|
21559
|
+
if (this.opaque === 0) this.counts.lookaheads++;
|
|
21560
|
+
this.look++;
|
|
21561
|
+
}
|
|
21562
|
+
exitLookahead() {
|
|
21563
|
+
this.look--;
|
|
21564
|
+
}
|
|
21565
|
+
regexAttempt() {
|
|
21566
|
+
if (this.opaque === 0) this.counts.regexLookarounds++;
|
|
21567
|
+
}
|
|
21568
|
+
regexMatch(re, start, end) {
|
|
21569
|
+
if (this.opaque === 0) this.counts.regexLookaroundBytes += lookaroundExtent(re, this.input, start, end);
|
|
21570
|
+
this.consume(start, end);
|
|
21571
|
+
}
|
|
21572
|
+
/** A read whose inner steps are not the grammar's (the interpreter's scans). */
|
|
21573
|
+
enterOpaque() {
|
|
21574
|
+
this.opaque++;
|
|
21575
|
+
}
|
|
21576
|
+
exitOpaque() {
|
|
21577
|
+
this.opaque--;
|
|
21578
|
+
}
|
|
21579
|
+
};
|
|
21580
|
+
function zeroCounts() {
|
|
21581
|
+
return { rewinds: 0, bytesReread: 0, lookaheads: 0, lookaheadBytes: 0, regexLookarounds: 0, regexLookaroundBytes: 0 };
|
|
21582
|
+
}
|
|
21583
|
+
function rowStarts(code, roots) {
|
|
21584
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21585
|
+
const stack = [...roots];
|
|
21586
|
+
const kids = [];
|
|
21587
|
+
while (stack.length > 0) {
|
|
21588
|
+
const ip = stack.pop();
|
|
21589
|
+
if (seen.has(ip)) continue;
|
|
21590
|
+
seen.add(ip);
|
|
21591
|
+
kids.length = 0;
|
|
21592
|
+
childSlots(code, ip, kids);
|
|
21593
|
+
for (const c of kids) stack.push(c);
|
|
21594
|
+
}
|
|
21595
|
+
return [...seen, code.length].sort((a, b) => a - b);
|
|
21596
|
+
}
|
|
21597
|
+
function probeProgram(source, rec) {
|
|
21598
|
+
const prog = expandCompact(source);
|
|
21599
|
+
const code = [...prog.code];
|
|
21600
|
+
const fns = [...prog.fns];
|
|
21601
|
+
const fx = [...prog.fx, []];
|
|
21602
|
+
const noFx = fx.length - 1;
|
|
21603
|
+
const row = (...words) => {
|
|
21604
|
+
const ip = code.length;
|
|
21605
|
+
code.push(...words);
|
|
21606
|
+
return ip;
|
|
21607
|
+
};
|
|
21608
|
+
const fn = (f) => fns.push(f) - 1;
|
|
21609
|
+
const slots = [];
|
|
21610
|
+
const extraIps = assemblyExtraIps(prog);
|
|
21611
|
+
const starts = rowStarts(prog.code, [...Object.values(prog.rules), ...extraIps]);
|
|
21612
|
+
const copies = /* @__PURE__ */ new Map();
|
|
21613
|
+
function copyOf(ip) {
|
|
21614
|
+
const hit = copies.get(ip);
|
|
21615
|
+
if (hit !== void 0) return hit;
|
|
21616
|
+
slots.length = 0;
|
|
21617
|
+
childSlotOffsets(prog.code, ip, slots);
|
|
21618
|
+
if (slots.length === 0) {
|
|
21619
|
+
copies.set(ip, ip);
|
|
21620
|
+
return ip;
|
|
21621
|
+
}
|
|
21622
|
+
const next = starts[starts.findIndex((s) => s > ip)];
|
|
21623
|
+
const at = code.length;
|
|
21624
|
+
copies.set(ip, at);
|
|
21625
|
+
for (let i = ip; i < next; i++) code.push(prog.code[i]);
|
|
21626
|
+
const own = slots.map((s) => s - ip);
|
|
21627
|
+
for (const o of own) code[at + o] = copyOf(prog.code[ip + o]);
|
|
21628
|
+
return at;
|
|
21629
|
+
}
|
|
21630
|
+
const ref2 = (r) => [copyOf(r[0]), r[1]];
|
|
21631
|
+
const scans = prog.scans?.map((s) => ({
|
|
21632
|
+
...s,
|
|
21633
|
+
skip: s.skip.map(ref2),
|
|
21634
|
+
...s.sentinel === void 0 ? {} : { sentinel: ref2(s.sentinel) },
|
|
21635
|
+
...s.recoverAt === void 0 ? {} : { recoverAt: ref2(s.recoverAt) },
|
|
21636
|
+
...s.stopAt === void 0 ? {} : { stopAt: ref2(s.stopAt) },
|
|
21637
|
+
...s.prefix === void 0 ? {} : { prefix: ref2(s.prefix) },
|
|
21638
|
+
...s.body === void 0 ? {} : { body: ref2(s.body) },
|
|
21639
|
+
...s.first === void 0 ? {} : { first: ref2(s.first) },
|
|
21640
|
+
...s.lazy === void 0 ? {} : { lazy: ref2(s.lazy) }
|
|
21641
|
+
}));
|
|
21642
|
+
const scanSkip = prog.scanSkip?.map((set) => set.map(ref2));
|
|
21643
|
+
const report = fn((v, span) => {
|
|
21644
|
+
rec.consume(span.start, span.end);
|
|
21645
|
+
return v;
|
|
21646
|
+
});
|
|
21647
|
+
const lookIn = fn(() => {
|
|
21648
|
+
rec.enterLookahead();
|
|
21649
|
+
return true;
|
|
21650
|
+
});
|
|
21651
|
+
const lookOut = fn((v) => {
|
|
21652
|
+
rec.exitLookahead();
|
|
21653
|
+
return v;
|
|
21654
|
+
});
|
|
21655
|
+
const regexTry = fn(() => {
|
|
21656
|
+
rec.regexAttempt();
|
|
21657
|
+
return true;
|
|
21658
|
+
});
|
|
21659
|
+
const lookahead = (child, fxi) => row(
|
|
21660
|
+
OP_ARMGATE,
|
|
21661
|
+
lookIn,
|
|
21662
|
+
row(OP_XFORM, lookOut, row(OP_NOT, row(OP_XFORM, lookOut, replacement(child) ?? child), fxi)),
|
|
21663
|
+
noFx
|
|
21664
|
+
);
|
|
21665
|
+
const replaced = /* @__PURE__ */ new Map();
|
|
21666
|
+
function replacement(c) {
|
|
21667
|
+
const hit = replaced.get(c);
|
|
21668
|
+
if (hit !== void 0) return hit;
|
|
21669
|
+
let r;
|
|
21670
|
+
switch (code[c]) {
|
|
21671
|
+
case OP_LIT:
|
|
21672
|
+
case OP_LIT_TRACK:
|
|
21673
|
+
case OP_LIT_CI:
|
|
21674
|
+
case OP_LIT_CI_TRACK:
|
|
21675
|
+
case OP_LEX_BODY:
|
|
21676
|
+
case OP_LEX_PROGRAM:
|
|
21677
|
+
case OP_SCAN:
|
|
21678
|
+
case OP_LIVE:
|
|
21679
|
+
r = row(OP_XFORM, report, c);
|
|
21680
|
+
break;
|
|
21681
|
+
case OP_RX:
|
|
21682
|
+
case OP_RX_TRACK: {
|
|
21683
|
+
const re = prog.k[code[c + 1]];
|
|
21684
|
+
r = hasLookaround(re) ? row(
|
|
21685
|
+
OP_ARMGATE,
|
|
21686
|
+
regexTry,
|
|
21687
|
+
row(OP_XFORM, fn((v, span) => {
|
|
21688
|
+
rec.regexMatch(re, span.start, span.end);
|
|
21689
|
+
return v;
|
|
21690
|
+
}), c),
|
|
21691
|
+
noFx
|
|
21692
|
+
) : row(OP_XFORM, report, c);
|
|
21693
|
+
break;
|
|
21694
|
+
}
|
|
21695
|
+
case OP_NOT:
|
|
21696
|
+
r = lookahead(code[c + 1], code[c + 2]);
|
|
21697
|
+
break;
|
|
21698
|
+
case OP_PEEK:
|
|
21699
|
+
r = row(OP_NOT, lookahead(code[c + 1], code[c + 2]), code[c + 2]);
|
|
21700
|
+
break;
|
|
21701
|
+
}
|
|
21702
|
+
if (r !== void 0) replaced.set(c, r);
|
|
21703
|
+
return r;
|
|
21704
|
+
}
|
|
21705
|
+
const rules = {};
|
|
21706
|
+
const stack = [];
|
|
21707
|
+
for (const [name, ip] of Object.entries(prog.rules)) {
|
|
21708
|
+
rules[name] = replacement(ip) ?? ip;
|
|
21709
|
+
stack.push(ip);
|
|
21710
|
+
}
|
|
21711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21712
|
+
while (stack.length > 0) {
|
|
21713
|
+
const ip = stack.pop();
|
|
21714
|
+
if (seen.has(ip)) continue;
|
|
21715
|
+
seen.add(ip);
|
|
21716
|
+
slots.length = 0;
|
|
21717
|
+
if (!childSlotOffsets(code, ip, slots)) throw new Error(`backtrack probe: unknown opcode ${String(code[ip])} at ${ip}`);
|
|
21718
|
+
for (let i = 0; i < slots.length; i++) {
|
|
21719
|
+
const s = slots[i];
|
|
21720
|
+
const c = code[s];
|
|
21721
|
+
stack.push(c);
|
|
21722
|
+
if (code[ip] === OP_GREEDY && i > 0) continue;
|
|
21723
|
+
const r = replacement(c);
|
|
21724
|
+
if (r !== void 0) code[s] = r;
|
|
21725
|
+
}
|
|
21726
|
+
}
|
|
21727
|
+
const out = Object.fromEntries(Object.entries(prog));
|
|
21728
|
+
return {
|
|
21729
|
+
...out,
|
|
21730
|
+
code,
|
|
21731
|
+
fns,
|
|
21732
|
+
fx,
|
|
21733
|
+
rules,
|
|
21734
|
+
asm: [],
|
|
21735
|
+
...scans === void 0 ? {} : { scans },
|
|
21736
|
+
...scanSkip === void 0 ? {} : { scanSkip }
|
|
21737
|
+
};
|
|
21738
|
+
}
|
|
21739
|
+
|
|
21740
|
+
// src/analysis/backtrack.ts
|
|
21741
|
+
function isCombinator3(x) {
|
|
21742
|
+
return typeof x === "object" && x !== null && "_def" in x && typeof x.parse === "function";
|
|
21743
|
+
}
|
|
21744
|
+
function isProgram(x) {
|
|
21745
|
+
return Array.isArray(x.code) || Array.isArray(x.c);
|
|
21746
|
+
}
|
|
21747
|
+
function ruleEntries(grammar) {
|
|
21748
|
+
const out = [];
|
|
21749
|
+
for (const [name, value] of Object.entries(grammar)) {
|
|
21750
|
+
if (!isCombinator3(value)) continue;
|
|
21751
|
+
if (value._def.tag === "lazy") {
|
|
21752
|
+
try {
|
|
21753
|
+
value._def.thunk();
|
|
21754
|
+
} catch {
|
|
21755
|
+
continue;
|
|
21756
|
+
}
|
|
21757
|
+
}
|
|
21758
|
+
out.push([name, value]);
|
|
21759
|
+
}
|
|
21760
|
+
return out;
|
|
21761
|
+
}
|
|
21762
|
+
function outcome(r) {
|
|
21763
|
+
return digestValue({ ok: r.ok, value: r.value, span: r.span, unconsumedFrom: r.unconsumedFrom });
|
|
21764
|
+
}
|
|
21765
|
+
function tableOf(grammar) {
|
|
21766
|
+
if (isProgram(grammar)) return expandCompact(grammar);
|
|
21767
|
+
const refusals = [];
|
|
21768
|
+
const compiled = compileRuleMapRunnable(ruleEntries(grammar), { refusals });
|
|
21769
|
+
if (compiled === null) throw new Error(`backtrackProbe: this grammar could not be encoded to a table: ${refusals.join("; ")}`);
|
|
21770
|
+
return compiled.prog;
|
|
21771
|
+
}
|
|
21772
|
+
function backtrackProbe(grammar, engine = "closure") {
|
|
21773
|
+
const rec = new BacktrackRecorder();
|
|
21774
|
+
if (engine === "interpreter") {
|
|
21775
|
+
if (isProgram(grammar)) throw new TypeError("backtrackProbe: the interpreter runs a rule map of combinators, not a table program");
|
|
21776
|
+
const rules2 = Object.fromEntries(ruleEntries(grammar));
|
|
21777
|
+
const built = /* @__PURE__ */ new Map();
|
|
21778
|
+
const instrument = instrumentFor(rec);
|
|
21779
|
+
return probe(rec, "interpreter", (entry) => ruleOf(rules2, entry), (entry) => {
|
|
21780
|
+
let hit = built.get(entry);
|
|
21781
|
+
if (hit === void 0) {
|
|
21782
|
+
hit = rebuildCombinator(ruleOf(rules2, entry), /* @__PURE__ */ new Map(), { thaw: true, after: instrument }).root;
|
|
21783
|
+
built.set(entry, hit);
|
|
21784
|
+
}
|
|
21785
|
+
return hit;
|
|
21786
|
+
});
|
|
21787
|
+
}
|
|
21788
|
+
if (engine !== "closure") throw new TypeError(`backtrackProbe: no engine ${JSON.stringify(engine)}; it runs 'closure' or 'interpreter'`);
|
|
21789
|
+
const prog = tableOf(grammar);
|
|
21790
|
+
const base = tableRules({ ...prog, asm: [] });
|
|
21791
|
+
const rules = tableRules(probeProgram(prog, rec));
|
|
21792
|
+
return probe(rec, "closure", (entry) => ruleOf(base, entry), (entry) => ruleOf(rules, entry));
|
|
21793
|
+
}
|
|
21794
|
+
function probe(rec, ran, plain2, probed) {
|
|
21795
|
+
return {
|
|
21796
|
+
engine: { ran },
|
|
21797
|
+
measure(entry, input, options = {}) {
|
|
21798
|
+
const result = run(plain2(entry), input, options);
|
|
21799
|
+
rec.begin(input);
|
|
21800
|
+
const probedResult = run(probed(entry), input, options);
|
|
21801
|
+
const counts = rec.end();
|
|
21802
|
+
if (outcome(probedResult) !== outcome(result)) {
|
|
21803
|
+
throw new Error(`backtrackProbe: the probed ${ran} parse of rule ${JSON.stringify(entry)} differs from the plain one; its counts would describe another parse`);
|
|
21804
|
+
}
|
|
21805
|
+
return { result, counts };
|
|
21806
|
+
}
|
|
21807
|
+
};
|
|
21808
|
+
}
|
|
21809
|
+
function ruleOf(rules, entry) {
|
|
21810
|
+
if (!Object.hasOwn(rules, entry)) throw new Error(`backtrackProbe: the grammar has no rule ${JSON.stringify(entry)}`);
|
|
21811
|
+
return rules[entry];
|
|
21812
|
+
}
|
|
21813
|
+
function wrapped(out, parse2) {
|
|
21814
|
+
const w = { _tag: out._tag, _meta: out._meta, _def: out._def, parse: parse2 };
|
|
21815
|
+
const name = out._ruleName;
|
|
21816
|
+
if (name !== void 0) w._ruleName = name;
|
|
21817
|
+
return w;
|
|
21818
|
+
}
|
|
21819
|
+
function instrumentFor(rec) {
|
|
21820
|
+
return (_original, out) => {
|
|
21821
|
+
const d = out._def;
|
|
21822
|
+
switch (d.tag) {
|
|
21823
|
+
case "literal":
|
|
21824
|
+
case "keywords":
|
|
21825
|
+
return wrapped(out, (input, pos, ctx) => {
|
|
21826
|
+
const r = out.parse(input, pos, ctx);
|
|
21827
|
+
if (r.ok) rec.consume(r.span.start, r.span.end);
|
|
21828
|
+
return r;
|
|
21829
|
+
});
|
|
21830
|
+
case "regex": {
|
|
21831
|
+
const re = new RegExp(d.source, d.flags);
|
|
21832
|
+
if (!hasLookaround(re)) {
|
|
21833
|
+
return wrapped(out, (input, pos, ctx) => {
|
|
21834
|
+
const r = out.parse(input, pos, ctx);
|
|
21835
|
+
if (r.ok) rec.consume(r.span.start, r.span.end);
|
|
21836
|
+
return r;
|
|
21837
|
+
});
|
|
21838
|
+
}
|
|
21839
|
+
return wrapped(out, (input, pos, ctx) => {
|
|
21840
|
+
rec.regexAttempt();
|
|
21841
|
+
const r = out.parse(input, pos, ctx);
|
|
21842
|
+
if (r.ok) rec.regexMatch(re, r.span.start, r.span.end);
|
|
21843
|
+
return r;
|
|
21844
|
+
});
|
|
21845
|
+
}
|
|
21846
|
+
case "scanTo":
|
|
21847
|
+
case "lines":
|
|
21848
|
+
case "columns":
|
|
21849
|
+
case "recover":
|
|
21850
|
+
case "unknown":
|
|
21851
|
+
return wrapped(out, (input, pos, ctx) => {
|
|
21852
|
+
rec.enterOpaque();
|
|
21853
|
+
let r;
|
|
21854
|
+
try {
|
|
21855
|
+
r = out.parse(input, pos, ctx);
|
|
21856
|
+
} finally {
|
|
21857
|
+
rec.exitOpaque();
|
|
21858
|
+
}
|
|
21859
|
+
if (r.ok) rec.consume(r.span.start, r.span.end);
|
|
21860
|
+
return r;
|
|
21861
|
+
});
|
|
21862
|
+
case "not":
|
|
21863
|
+
case "peek":
|
|
21864
|
+
return wrapped(out, (input, pos, ctx) => {
|
|
21865
|
+
rec.enterLookahead();
|
|
21866
|
+
try {
|
|
21867
|
+
return out.parse(input, pos, ctx);
|
|
21868
|
+
} finally {
|
|
21869
|
+
rec.exitLookahead();
|
|
21870
|
+
}
|
|
21871
|
+
});
|
|
21872
|
+
default:
|
|
21873
|
+
return out;
|
|
21874
|
+
}
|
|
21875
|
+
};
|
|
21876
|
+
}
|
|
20885
21877
|
export {
|
|
20886
21878
|
applyFixEdits,
|
|
20887
21879
|
armFirstSets,
|
|
21880
|
+
backtrackProbe,
|
|
20888
21881
|
diagnosisLines,
|
|
20889
21882
|
fixReportLines,
|
|
20890
21883
|
groupDigits,
|