parseman 0.28.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts +11 -0
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts +7 -0
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +24 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +10 -0
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/index.cjs +256 -17
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +256 -17
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.cjs.map +2 -2
- package/dist/language-service/index.js.map +2 -2
- package/dist/plugin/index.cjs +257 -18
- package/dist/plugin/index.cjs.map +3 -3
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +257 -18
- package/dist/plugin/index.js.map +3 -3
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAwBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAkBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;;;AAgSD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AA0CD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,GACtB,oBAAoB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAwBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAkBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;;;AAgSD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AA0CD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,GACtB,oBAAoB,GAAG,IAAI,CAi8B7B"}
|
package/dist/plugin/index.js
CHANGED
|
@@ -26,6 +26,15 @@ function intersects(a, b) {
|
|
|
26
26
|
function fromChar(code) {
|
|
27
27
|
return { kind: "ranges", ranges: [{ lo: code, hi: code }] };
|
|
28
28
|
}
|
|
29
|
+
function startsFirstSet(combinator, input, pos) {
|
|
30
|
+
const fs2 = combinator._meta.firstSet;
|
|
31
|
+
if (fs2.kind === "any") return true;
|
|
32
|
+
if (fs2.kind === "empty") return false;
|
|
33
|
+
const code = input.codePointAt(pos);
|
|
34
|
+
if (code === void 0) return false;
|
|
35
|
+
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
29
38
|
function fromRange(lo, hi) {
|
|
30
39
|
return { kind: "ranges", ranges: [{ lo, hi }] };
|
|
31
40
|
}
|
|
@@ -985,6 +994,17 @@ function deriveExpected(c) {
|
|
|
985
994
|
return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
|
|
986
995
|
case "attempt":
|
|
987
996
|
return deriveExpected(def.parser);
|
|
997
|
+
// Delegating wrappers whose first-token failure is their inner parser's — must
|
|
998
|
+
// pass through so a start-failure (and the first-set-miss fast-path in attempt/
|
|
999
|
+
// node, which reads this) names the real expected token, not the wrapper tag.
|
|
1000
|
+
case "field":
|
|
1001
|
+
case "withCtx":
|
|
1002
|
+
case "recover":
|
|
1003
|
+
return deriveExpected(def.parser);
|
|
1004
|
+
case "skip":
|
|
1005
|
+
return deriveExpected(def.main);
|
|
1006
|
+
case "expect":
|
|
1007
|
+
return def.expected;
|
|
988
1008
|
case "node":
|
|
989
1009
|
case "grammar":
|
|
990
1010
|
case "trivia":
|
|
@@ -1045,7 +1065,7 @@ function choice(...args) {
|
|
|
1045
1065
|
disjoint
|
|
1046
1066
|
};
|
|
1047
1067
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
1048
|
-
const autoNot = !disjoint && !hasGates && strategy?.tag === "firstMatch" ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
1068
|
+
const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
1049
1069
|
let greedyLitMap = null;
|
|
1050
1070
|
let sortedParsers = null;
|
|
1051
1071
|
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
@@ -1171,8 +1191,47 @@ function detectStrategy(parsers) {
|
|
|
1171
1191
|
);
|
|
1172
1192
|
return { tag: "literalsLongestFirst", sortedIndices };
|
|
1173
1193
|
}
|
|
1194
|
+
const shared = detectSharedPrefix(parsers);
|
|
1195
|
+
if (shared !== null) return shared;
|
|
1174
1196
|
return { tag: "firstMatch" };
|
|
1175
1197
|
}
|
|
1198
|
+
function bareLeadingTermKey(term) {
|
|
1199
|
+
const d = term._def;
|
|
1200
|
+
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
1201
|
+
if (d.tag === "regex") return `R:${d.source}\0${d.flags}`;
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
function detectSharedPrefix(parsers) {
|
|
1205
|
+
if (parsers.length < 2) return null;
|
|
1206
|
+
let key = null;
|
|
1207
|
+
let prefix = null;
|
|
1208
|
+
const members = [];
|
|
1209
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1210
|
+
const term0 = leadingTermOfArm(parsers[i]);
|
|
1211
|
+
if (term0 === null) return null;
|
|
1212
|
+
const k = bareLeadingTermKey(term0);
|
|
1213
|
+
if (k === null) return null;
|
|
1214
|
+
if (key === null) {
|
|
1215
|
+
key = k;
|
|
1216
|
+
prefix = term0;
|
|
1217
|
+
} else if (k !== key) return null;
|
|
1218
|
+
members.push(i);
|
|
1219
|
+
}
|
|
1220
|
+
if (prefix === null || members.length < 2) return null;
|
|
1221
|
+
return { tag: "sharedPrefix", prefix, members };
|
|
1222
|
+
}
|
|
1223
|
+
function leadingTermOfArm(arm) {
|
|
1224
|
+
let d = arm._def;
|
|
1225
|
+
for (; ; ) {
|
|
1226
|
+
if (d.tag === "node" || d.tag === "grammar" || d.tag === "transform" || d.tag === "label") {
|
|
1227
|
+
d = d.parser._def;
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
break;
|
|
1231
|
+
}
|
|
1232
|
+
if (d.tag !== "sequence" || d.parsers.length < 2) return null;
|
|
1233
|
+
return d.parsers[0];
|
|
1234
|
+
}
|
|
1176
1235
|
function computeAutoNot(parsers) {
|
|
1177
1236
|
return parsers.map((p, i) => {
|
|
1178
1237
|
const litVal = getCoreLiteralValue(p);
|
|
@@ -1766,11 +1825,20 @@ function sequence(...parsers) {
|
|
|
1766
1825
|
|
|
1767
1826
|
// src/combinators/attempt.ts
|
|
1768
1827
|
function attempt(parser2) {
|
|
1828
|
+
const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
|
|
1829
|
+
let failExpected;
|
|
1769
1830
|
return {
|
|
1770
1831
|
_tag: "attempt",
|
|
1771
1832
|
_meta: parser2._meta,
|
|
1772
1833
|
_def: { tag: "attempt", parser: parser2 },
|
|
1773
1834
|
parse(input, pos, ctx) {
|
|
1835
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
|
|
1836
|
+
if (failExpected === void 0) {
|
|
1837
|
+
const e = deriveExpected(parser2);
|
|
1838
|
+
failExpected = e.length > 0 ? e : [parser2._tag];
|
|
1839
|
+
}
|
|
1840
|
+
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
1841
|
+
}
|
|
1774
1842
|
const mark = saveCstMark(ctx);
|
|
1775
1843
|
const log = ctx._triviaLog?.length;
|
|
1776
1844
|
const result = parser2.parse(input, pos, ctx);
|
|
@@ -1783,7 +1851,7 @@ function attempt(parser2) {
|
|
|
1783
1851
|
}
|
|
1784
1852
|
|
|
1785
1853
|
// src/combinators/repeat.ts
|
|
1786
|
-
function repItem(combinator, input, cur, ctx) {
|
|
1854
|
+
function repItem(combinator, input, cur, ctx, guardable) {
|
|
1787
1855
|
const mark = saveTriviaMark(ctx);
|
|
1788
1856
|
let pos = cur;
|
|
1789
1857
|
if (ctx.trivia) {
|
|
@@ -1799,6 +1867,10 @@ function repItem(combinator, input, cur, ctx) {
|
|
|
1799
1867
|
rollbackTrivia(ctx, mark);
|
|
1800
1868
|
return "stop";
|
|
1801
1869
|
}
|
|
1870
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
1871
|
+
rollbackTrivia(ctx, mark);
|
|
1872
|
+
return "stop";
|
|
1873
|
+
}
|
|
1802
1874
|
const result = combinator.parse(input, pos, ctx);
|
|
1803
1875
|
if (!result.ok) {
|
|
1804
1876
|
rollbackTrivia(ctx, mark);
|
|
@@ -1818,6 +1890,7 @@ function many(combinator) {
|
|
|
1818
1890
|
};
|
|
1819
1891
|
const def = { tag: "many", parser: combinator, min: 0 };
|
|
1820
1892
|
let expected;
|
|
1893
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
1821
1894
|
return {
|
|
1822
1895
|
_tag: "many",
|
|
1823
1896
|
_meta: meta,
|
|
@@ -1826,7 +1899,7 @@ function many(combinator) {
|
|
|
1826
1899
|
const values = def.valueUnused ? void 0 : [];
|
|
1827
1900
|
let cur = pos;
|
|
1828
1901
|
while (cur < input.length) {
|
|
1829
|
-
const item = repItem(combinator, input, cur, ctx);
|
|
1902
|
+
const item = repItem(combinator, input, cur, ctx, guardable);
|
|
1830
1903
|
if (item === "stop") break;
|
|
1831
1904
|
if ("fail" in item) {
|
|
1832
1905
|
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
@@ -1854,6 +1927,7 @@ function oneOrMore(combinator) {
|
|
|
1854
1927
|
};
|
|
1855
1928
|
const def = { tag: "oneOrMore", parser: combinator, min: 1 };
|
|
1856
1929
|
let expected;
|
|
1930
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
1857
1931
|
return {
|
|
1858
1932
|
_tag: "oneOrMore",
|
|
1859
1933
|
_meta: meta,
|
|
@@ -1864,7 +1938,7 @@ function oneOrMore(combinator) {
|
|
|
1864
1938
|
const values = def.valueUnused ? void 0 : [first.value];
|
|
1865
1939
|
let cur = first.span.end;
|
|
1866
1940
|
while (cur < input.length) {
|
|
1867
|
-
const item = repItem(combinator, input, cur, ctx);
|
|
1941
|
+
const item = repItem(combinator, input, cur, ctx, guardable);
|
|
1868
1942
|
if (item === "stop") break;
|
|
1869
1943
|
if ("fail" in item) {
|
|
1870
1944
|
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
@@ -1907,15 +1981,6 @@ function optional(combinator) {
|
|
|
1907
1981
|
}
|
|
1908
1982
|
};
|
|
1909
1983
|
}
|
|
1910
|
-
function startsFirstSet(combinator, input, pos) {
|
|
1911
|
-
const fs2 = combinator._meta.firstSet;
|
|
1912
|
-
if (fs2.kind === "any") return true;
|
|
1913
|
-
if (fs2.kind === "empty") return false;
|
|
1914
|
-
const code = input.codePointAt(pos);
|
|
1915
|
-
if (code === void 0) return false;
|
|
1916
|
-
for (const r of fs2.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1917
|
-
return false;
|
|
1918
|
-
}
|
|
1919
1984
|
function sepBy(combinator, separator) {
|
|
1920
1985
|
const meta = {
|
|
1921
1986
|
firstSet: combinator._meta.firstSet,
|
|
@@ -2412,11 +2477,20 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2412
2477
|
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
|
|
2413
2478
|
const clonesState = build ? buildReadsState(def) : true;
|
|
2414
2479
|
const capturesFields = parserHasOwnFields(combinator) && (build ? buildReadsFields(def) : true);
|
|
2480
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
2481
|
+
let failExpected;
|
|
2415
2482
|
return {
|
|
2416
2483
|
_tag: "node",
|
|
2417
2484
|
_meta: meta,
|
|
2418
2485
|
_def: def,
|
|
2419
2486
|
parse(input, pos, ctx) {
|
|
2487
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
2488
|
+
if (failExpected === void 0) {
|
|
2489
|
+
const e = deriveExpected(combinator);
|
|
2490
|
+
failExpected = e.length > 0 ? e : [combinator._tag];
|
|
2491
|
+
}
|
|
2492
|
+
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
2493
|
+
}
|
|
2420
2494
|
const saved = beginCstNodeCapture(ctx);
|
|
2421
2495
|
const savedFields = ctx._fields;
|
|
2422
2496
|
ctx._fields = capturesFields ? [] : void 0;
|
|
@@ -4116,6 +4190,61 @@ function tryInlineDestructureTransform(src, valueVars) {
|
|
|
4116
4190
|
}
|
|
4117
4191
|
|
|
4118
4192
|
// src/compiler/codegen.ts
|
|
4193
|
+
function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
|
|
4194
|
+
if (seen.has(p)) return { concrete: empty(), refs: [] };
|
|
4195
|
+
seen.add(p);
|
|
4196
|
+
const d = p._def;
|
|
4197
|
+
const rec = (c) => leadingFirstSetRecipe(c, seen);
|
|
4198
|
+
const merge = (a, b) => ({ concrete: union(a.concrete, b.concrete), refs: [...a.refs, ...b.refs] });
|
|
4199
|
+
switch (d.tag) {
|
|
4200
|
+
case "lazy": {
|
|
4201
|
+
const name = p._ruleName;
|
|
4202
|
+
if (name !== void 0) return { concrete: empty(), refs: [name] };
|
|
4203
|
+
try {
|
|
4204
|
+
return rec(d.thunk());
|
|
4205
|
+
} catch {
|
|
4206
|
+
return { concrete: any(), refs: [] };
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
case "literal":
|
|
4210
|
+
case "regex":
|
|
4211
|
+
case "keywords":
|
|
4212
|
+
return { concrete: p._meta.firstSet, refs: [] };
|
|
4213
|
+
case "choice": {
|
|
4214
|
+
let out = { concrete: empty(), refs: [] };
|
|
4215
|
+
for (const arm of d.parsers) out = merge(out, rec(arm));
|
|
4216
|
+
return out;
|
|
4217
|
+
}
|
|
4218
|
+
case "sequence": {
|
|
4219
|
+
let out = { concrete: empty(), refs: [] };
|
|
4220
|
+
for (const term of d.parsers) {
|
|
4221
|
+
out = merge(out, rec(term));
|
|
4222
|
+
if (!matchesEmpty(term)) return out;
|
|
4223
|
+
}
|
|
4224
|
+
return out;
|
|
4225
|
+
}
|
|
4226
|
+
case "oneOrMore":
|
|
4227
|
+
case "many":
|
|
4228
|
+
case "optional":
|
|
4229
|
+
case "transform":
|
|
4230
|
+
case "label":
|
|
4231
|
+
case "field":
|
|
4232
|
+
case "trivia":
|
|
4233
|
+
case "token":
|
|
4234
|
+
case "leaf":
|
|
4235
|
+
case "node":
|
|
4236
|
+
case "grammar":
|
|
4237
|
+
case "expect":
|
|
4238
|
+
return rec(d.parser);
|
|
4239
|
+
case "sepBy":
|
|
4240
|
+
return rec(d.parser);
|
|
4241
|
+
case "skip":
|
|
4242
|
+
return rec(d.main);
|
|
4243
|
+
// not / scanTo / guard / withCtx / recover / unknown → shallow set (safe).
|
|
4244
|
+
default:
|
|
4245
|
+
return { concrete: p._meta.firstSet, refs: [] };
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4119
4248
|
var HOST_READS_DECL = "const _hostReads = (b, n) => { if (b === undefined) return false; let s; try { s = Function.prototype.toString.call(b) } catch (e) { return true } if (/\\barguments\\b/.test(s)) return true; const m = /^[^(]*\\(([\\s\\S]*?)\\)/.exec(s); if (m && /\\.\\.\\.|=/.test(m[1])) return true; return b.length > n }";
|
|
4120
4249
|
var _loweringSink = null;
|
|
4121
4250
|
function beginLoweringCapture() {
|
|
@@ -4357,6 +4486,7 @@ var SWITCH_RANGE_LIMIT = 4;
|
|
|
4357
4486
|
var SWITCH_MAX_CASES = 48;
|
|
4358
4487
|
var SWITCH_MIN_CASES = 3;
|
|
4359
4488
|
var _forceDisjointIf = false;
|
|
4489
|
+
var _forceNoSharedPrefix = false;
|
|
4360
4490
|
function planDisjointDispatch(parsers) {
|
|
4361
4491
|
const cases = [];
|
|
4362
4492
|
let total = 0;
|
|
@@ -4992,7 +5122,7 @@ function emitLiteralsLongestFirst(def, sortedIndices, allExpected, ctx, pos, cov
|
|
|
4992
5122
|
stmts.push(...emitElseFail(ctx, failArrBody(ctx, allExpected, pos)));
|
|
4993
5123
|
return { stmts, valueVar: valV, endVar: endV };
|
|
4994
5124
|
}
|
|
4995
|
-
function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
5125
|
+
function emitFirstMatch(def, ctx, pos, coverageBase, preStmts, armGuardPrefix) {
|
|
4996
5126
|
const resValV = v(ctx, "_crv");
|
|
4997
5127
|
const resEndV = v(ctx, "_cre");
|
|
4998
5128
|
const resOkV = v(ctx, "_crok");
|
|
@@ -5006,6 +5136,7 @@ function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
|
5006
5136
|
...autoRejectedV === void 0 ? [] : [`${ind0}const ${autoRejectedV} = []`],
|
|
5007
5137
|
`${ind0}const ${codeV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`
|
|
5008
5138
|
];
|
|
5139
|
+
if (preStmts) stmts.push(...preStmts);
|
|
5009
5140
|
for (let i = 0; i < def.parsers.length; i++) {
|
|
5010
5141
|
const p = def.parsers[i];
|
|
5011
5142
|
const gate = def.gates[i];
|
|
@@ -5013,11 +5144,12 @@ function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
|
5013
5144
|
const atStart = failsAtStart(p);
|
|
5014
5145
|
const staticFx = armStaticExpected(ctx, p);
|
|
5015
5146
|
const deferRuleName = ctx.deferFirstSetRefs ? p._ruleName : void 0;
|
|
5016
|
-
const
|
|
5147
|
+
const baseFsGuard = deferRuleName !== void 0 ? `/*@FS:${deferRuleName}:${codeV}@*/true` : needsFirstSetGuard(p) ? firstSetCond(codeV, p._meta.firstSet) : (() => {
|
|
5017
5148
|
if (p._meta.firstSet.kind !== "any" || matchesEmpty(p)) return null;
|
|
5018
5149
|
const deep = firstSetOf(p);
|
|
5019
5150
|
return deep.kind === "ranges" ? firstSetCond(codeV, deep) : null;
|
|
5020
5151
|
})();
|
|
5152
|
+
const fsGuard = armGuardPrefix === void 0 ? baseFsGuard : baseFsGuard === null ? armGuardPrefix : `${armGuardPrefix} && (${baseFsGuard})`;
|
|
5021
5153
|
let gateCond = null;
|
|
5022
5154
|
if (gate) {
|
|
5023
5155
|
const gateIdx = ctx.mapFns.length;
|
|
@@ -5086,11 +5218,64 @@ function emitFirstMatch(def, ctx, pos, coverageBase) {
|
|
|
5086
5218
|
stmts.push(...emitIfFail(ctx, `!${resOkV}`, failArrBody(ctx, concatExpr, pos, false)));
|
|
5087
5219
|
return { stmts, valueVar: resValV, endVar: resEndV };
|
|
5088
5220
|
}
|
|
5221
|
+
function emitsAsNamedFn(p, ctx) {
|
|
5222
|
+
if (p._def.tag === "lazy") return true;
|
|
5223
|
+
if (ctx.ruleNames?.has(p)) return true;
|
|
5224
|
+
if (ctx.namedParsers.has(p)) return true;
|
|
5225
|
+
const usage = ctx.lazyUsage;
|
|
5226
|
+
return !!usage && !ctx.noHoist && !ctx.capAsTrivia && isHoistableTag(p._def.tag) && (usage.counts.get(p) ?? 0) > 1 && (usage.sizes.get(p) ?? 0) >= HOIST_MIN_SUBTREE;
|
|
5227
|
+
}
|
|
5228
|
+
function armReplayInScope(arm, ctx) {
|
|
5229
|
+
let p = arm;
|
|
5230
|
+
for (; ; ) {
|
|
5231
|
+
if (emitsAsNamedFn(p, ctx)) return false;
|
|
5232
|
+
const d = p._def;
|
|
5233
|
+
if (d.tag === "node" || d.tag === "grammar" || d.tag === "transform" || d.tag === "label") {
|
|
5234
|
+
p = d.parser;
|
|
5235
|
+
continue;
|
|
5236
|
+
}
|
|
5237
|
+
return d.tag === "sequence";
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5240
|
+
function emitSharedPrefix(def, strategy, ctx, pos) {
|
|
5241
|
+
const { prefix, members } = strategy;
|
|
5242
|
+
const savedCapturing = ctx.capturing;
|
|
5243
|
+
ctx.capturing = false;
|
|
5244
|
+
const pfx = emitFallible(prefix, ctx, pos, false);
|
|
5245
|
+
ctx.capturing = savedCapturing;
|
|
5246
|
+
const map = ctx.replayPrefix ??= /* @__PURE__ */ new Map();
|
|
5247
|
+
const keys = [];
|
|
5248
|
+
for (const i of members) {
|
|
5249
|
+
const term0 = leadingTermOfArm(def.parsers[i]);
|
|
5250
|
+
if (term0 === null) continue;
|
|
5251
|
+
map.set(term0, { valVar: pfx.valVar, endVar: pfx.endVar });
|
|
5252
|
+
keys.push(term0);
|
|
5253
|
+
}
|
|
5254
|
+
const r = emitFirstMatch(def, ctx, pos, void 0, pfx.stmts, pfx.okVar);
|
|
5255
|
+
for (const k of keys) map.delete(k);
|
|
5256
|
+
return r;
|
|
5257
|
+
}
|
|
5258
|
+
function emitReplayPrefixLeaf(ctx, pos, replay) {
|
|
5259
|
+
const vv = v(ctx);
|
|
5260
|
+
return {
|
|
5261
|
+
stmts: [
|
|
5262
|
+
`${ind(ctx)}const ${vv} = ${replay.valVar}`,
|
|
5263
|
+
...emitLeafCapture(ctx, vv, pos, replay.endVar)
|
|
5264
|
+
],
|
|
5265
|
+
valueVar: vv,
|
|
5266
|
+
endVar: replay.endVar
|
|
5267
|
+
};
|
|
5268
|
+
}
|
|
5089
5269
|
function emitNonDisjoint(def, strategy, allExpected, ctx, pos, coverageBase) {
|
|
5090
5270
|
if (strategy.tag === "greedyClassify")
|
|
5091
5271
|
return emitGreedyClassify(def, strategy.superIndex, ctx, pos, coverageBase);
|
|
5092
5272
|
if (strategy.tag === "literalsLongestFirst")
|
|
5093
5273
|
return emitLiteralsLongestFirst(def, strategy.sortedIndices, allExpected, ctx, pos, coverageBase);
|
|
5274
|
+
if (strategy.tag === "sharedPrefix") {
|
|
5275
|
+
if (!_forceNoSharedPrefix && coverageBase === void 0 && !ctx.recovery && strategy.members.every((i) => armReplayInScope(def.parsers[i], ctx)))
|
|
5276
|
+
return emitSharedPrefix(def, strategy, ctx, pos);
|
|
5277
|
+
return emitFirstMatch(def, ctx, pos, coverageBase);
|
|
5278
|
+
}
|
|
5094
5279
|
return emitFirstMatch(def, ctx, pos, coverageBase);
|
|
5095
5280
|
}
|
|
5096
5281
|
function pushMapFn(ctx, fn, src) {
|
|
@@ -5170,6 +5355,13 @@ function emitMany(def, ctx, pos) {
|
|
|
5170
5355
|
itemPos = npV;
|
|
5171
5356
|
}
|
|
5172
5357
|
}
|
|
5358
|
+
if (!ctx.recovery && !ctx.coverage && !failsAtStart(def.parser) && needsFirstSetGuard(def.parser)) {
|
|
5359
|
+
const lcV = v(ctx, "_lc");
|
|
5360
|
+
stmts.push(
|
|
5361
|
+
`${ind(ctx)}const ${lcV} = ${itemPos} < input.length ? (input.codePointAt(${itemPos}) ?? -1) : -1`,
|
|
5362
|
+
`${ind(ctx)}if (!(${firstSetCond(lcV, def.parser._meta.firstSet)})) { ${rollback}break }`
|
|
5363
|
+
);
|
|
5364
|
+
}
|
|
5173
5365
|
const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos, true);
|
|
5174
5366
|
stmts.push(...iterStmts);
|
|
5175
5367
|
if (ctx.recovery) {
|
|
@@ -5220,8 +5412,19 @@ function emitAttempt(p, def, ctx, pos) {
|
|
|
5220
5412
|
const rollback = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${trivia2}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${log}; if (_ctx._fields) _ctx._fields.length = ${fields}; if (_ctx._errors) _ctx._errors.length = ${errors}`;
|
|
5221
5413
|
const traceId = ctx.coverage?.plan.attempts.get(p);
|
|
5222
5414
|
const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
|
|
5415
|
+
const preGuard = [];
|
|
5416
|
+
if (!ctx.recovery && !ctx.coverage && needsFirstSetGuard(def.parser)) {
|
|
5417
|
+
const gcV = v(ctx, "_agc");
|
|
5418
|
+
const gExp = armStaticExpected(ctx, def.parser);
|
|
5419
|
+
const gFail = ctx.failLabel ? `{ _ctx._fe = ${pos};${ctx.recordFail ? ` _ctx._fx = ${gExp};` : ""} break ${ctx.failLabel} }` : `{ _ctx._fe = ${pos}; ${failReturnArr(gExp, pos)} }`;
|
|
5420
|
+
preGuard.push(
|
|
5421
|
+
`${ind(ctx)}const ${gcV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`,
|
|
5422
|
+
`${ind(ctx)}if (!(${firstSetCond(gcV, def.parser._meta.firstSet)})) ${gFail}`
|
|
5423
|
+
);
|
|
5424
|
+
}
|
|
5223
5425
|
return {
|
|
5224
5426
|
stmts: [
|
|
5427
|
+
...preGuard,
|
|
5225
5428
|
`${ind(ctx)}const ${leaves} = _ctx._cstLeaves?.length ?? 0, ${raw} = _ctx._cstRawChildren?.length ?? 0, ${trivia2} = _ctx._cstTriviaLog?.length ?? 0, ${log} = _ctx._triviaLog?.length ?? 0, ${fields} = _ctx._fields?.length ?? 0, ${errors} = _ctx._errors?.length ?? 0`,
|
|
5226
5429
|
...inner.stmts,
|
|
5227
5430
|
...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
|
|
@@ -5601,7 +5804,18 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
|
|
|
5601
5804
|
const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
|
|
5602
5805
|
const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
|
|
5603
5806
|
const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
|
|
5807
|
+
const preGuard = [];
|
|
5808
|
+
if (!ctx.recovery && !ctx.coverage && (capturesChildren || structural) && needsFirstSetGuard(def.parser)) {
|
|
5809
|
+
const gcV = v(ctx, "_ngc");
|
|
5810
|
+
const gExp = armStaticExpected(ctx, def.parser);
|
|
5811
|
+
const gFail = ctx.failLabel ? ctx.recordFail ? `{ _ctx._fe = ${pos}; _ctx._fx = ${gExp}; break ${ctx.failLabel} }` : `break ${ctx.failLabel}` : failReturnArr(gExp, pos);
|
|
5812
|
+
preGuard.push(
|
|
5813
|
+
`${i}const ${gcV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`,
|
|
5814
|
+
`${i}if (!(${firstSetCond(gcV, def.parser._meta.firstSet)})) ${gFail}`
|
|
5815
|
+
);
|
|
5816
|
+
}
|
|
5604
5817
|
const stmts = [
|
|
5818
|
+
...preGuard,
|
|
5605
5819
|
profHoist,
|
|
5606
5820
|
allocStmt,
|
|
5607
5821
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
@@ -5775,6 +5989,8 @@ function emitExpect(def, ctx, pos) {
|
|
|
5775
5989
|
return { stmts, valueVar: valVar, endVar };
|
|
5776
5990
|
}
|
|
5777
5991
|
function emit(p, ctx, pos) {
|
|
5992
|
+
const replay = ctx.replayPrefix?.get(p);
|
|
5993
|
+
if (replay !== void 0) return emitReplayPrefixLeaf(ctx, pos, replay);
|
|
5778
5994
|
const dispatch = (emissionPos = pos) => {
|
|
5779
5995
|
const savedRule = ctx.activeCoverageRuleId;
|
|
5780
5996
|
const rule = ctx.coverage?.plan.rules.get(p);
|
|
@@ -6628,6 +6844,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6628
6844
|
].join("\n")));
|
|
6629
6845
|
}
|
|
6630
6846
|
const firstSets = /* @__PURE__ */ new Map();
|
|
6847
|
+
const firstSetRecipes = /* @__PURE__ */ new Map();
|
|
6631
6848
|
for (const [key, rule] of ruleMap) {
|
|
6632
6849
|
let resolved = rule;
|
|
6633
6850
|
const d = rule._def;
|
|
@@ -6639,6 +6856,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6639
6856
|
}
|
|
6640
6857
|
}
|
|
6641
6858
|
firstSets.set(key, canMatchEmptyAtStart(resolved) ? { kind: "any" } : resolved._meta.firstSet);
|
|
6859
|
+
firstSetRecipes.set(key, canMatchEmptyAtStart(resolved) ? { concrete: any(), refs: [] } : leadingFirstSetRecipe(resolved));
|
|
6642
6860
|
}
|
|
6643
6861
|
return {
|
|
6644
6862
|
ns,
|
|
@@ -6647,6 +6865,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
6647
6865
|
ruleFns,
|
|
6648
6866
|
wrappers,
|
|
6649
6867
|
firstSets,
|
|
6868
|
+
firstSetRecipes,
|
|
6650
6869
|
deps: ruleDependencies(ruleMap),
|
|
6651
6870
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
6652
6871
|
needsHostReads: !!ctx.needsHostReads,
|
|
@@ -7293,10 +7512,30 @@ function fusedBody(pieces) {
|
|
|
7293
7512
|
];
|
|
7294
7513
|
const wrapperEntries = [...winner].map(([k, p]) => `${JSON.stringify(k)}: ${p.wrappers.get(k)}`);
|
|
7295
7514
|
const rawBody = [...lines, "return {", wrapperEntries.join(",\n"), "}"].join("\n");
|
|
7296
|
-
const
|
|
7515
|
+
const ANY2 = { kind: "any" };
|
|
7516
|
+
const recipes = /* @__PURE__ */ new Map();
|
|
7517
|
+
const shallow = /* @__PURE__ */ new Map();
|
|
7297
7518
|
for (const [k, p] of winner) {
|
|
7519
|
+
const r = p.firstSetRecipes?.get(k);
|
|
7520
|
+
if (r) recipes.set(k, r);
|
|
7298
7521
|
const fs2 = p.firstSets?.get(k);
|
|
7299
|
-
if (fs2)
|
|
7522
|
+
if (fs2) shallow.set(k, fs2);
|
|
7523
|
+
}
|
|
7524
|
+
const finalFS = /* @__PURE__ */ new Map();
|
|
7525
|
+
for (const [k] of winner) finalFS.set(k, recipes.get(k)?.concrete ?? shallow.get(k) ?? ANY2);
|
|
7526
|
+
for (let iter = 0; iter <= recipes.size; iter++) {
|
|
7527
|
+
let changed = false;
|
|
7528
|
+
for (const [k, r] of recipes) {
|
|
7529
|
+
let fs2 = r.concrete;
|
|
7530
|
+
for (const ref2 of r.refs) {
|
|
7531
|
+
fs2 = union(fs2, recipes.has(ref2) || shallow.has(ref2) ? finalFS.get(ref2) ?? ANY2 : ANY2);
|
|
7532
|
+
}
|
|
7533
|
+
if (JSON.stringify(finalFS.get(k)) !== JSON.stringify(fs2)) {
|
|
7534
|
+
finalFS.set(k, fs2);
|
|
7535
|
+
changed = true;
|
|
7536
|
+
}
|
|
7537
|
+
}
|
|
7538
|
+
if (!changed) break;
|
|
7300
7539
|
}
|
|
7301
7540
|
const body = rawBody.replace(
|
|
7302
7541
|
// Rule name + code-point var are both JS identifiers (rule names are validated
|
|
@@ -8467,7 +8706,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
|
|
|
8467
8706
|
const mapLit = (m, stripVals = false) => `new Map([${[...m].map(
|
|
8468
8707
|
([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(stripVals && typeof v2 === "string" ? stripIndent(v2) : v2)}]`
|
|
8469
8708
|
).join(", ")}])`;
|
|
8470
|
-
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, hasDirectBuilders: ${p.hasDirectBuilders === true}, isRecognitionOnly: ${p.isRecognitionOnly === true}, mfFns: [], buildFns: [] }`;
|
|
8709
|
+
return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, firstSetRecipes: ${p.firstSetRecipes ? mapLit(p.firstSetRecipes) : "new Map()"}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, hasDirectBuilders: ${p.hasDirectBuilders === true}, isRecognitionOnly: ${p.isRecognitionOnly === true}, mfFns: [], buildFns: [] }`;
|
|
8471
8710
|
};
|
|
8472
8711
|
const isSpread = (it) => "__spreadLocal" in it;
|
|
8473
8712
|
const isIR = (it) => "ir" in it && !("ruleFns" in it);
|