parseman 0.50.1 → 0.50.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -10
- package/dist/analysis/diagnostics.js +431 -219
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/cli/index.js +421 -184
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/keywords.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/ref.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/repeat.d.ts.map +1 -1
- package/dist/combinators/scalar.d.ts +6 -0
- package/dist/combinators/scalar.d.ts.map +1 -0
- package/dist/combinators/sequence.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts +2 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +0 -3
- package/dist/compiler/token-capability.js.map +2 -2
- package/dist/index.js +422 -185
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +68 -172
- package/dist/language-service/index.js.map +3 -3
- package/dist/parse-context.d.ts.map +1 -1
- package/dist/plugin/index.js +467 -299
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.js +1 -0
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +399 -277
- package/dist/spec/index.js.map +3 -3
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/index.js +307 -181
- package/dist/table/index.js.map +3 -3
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +4 -2
- package/src/combinators/choice.ts +34 -1
- package/src/combinators/grammar.ts +39 -0
- package/src/combinators/keywords.ts +14 -3
- package/src/combinators/literal.ts +26 -0
- package/src/combinators/map.ts +60 -0
- package/src/combinators/ref.ts +26 -7
- package/src/combinators/regex.ts +23 -0
- package/src/combinators/repeat.ts +109 -16
- package/src/combinators/scalar.ts +30 -0
- package/src/combinators/sequence.ts +76 -161
- package/src/combinators/trivia-skip.ts +14 -1
- package/src/parse-context.ts +1 -0
- package/src/table/emit-assembly.ts +39 -16
- package/src/types.ts +8 -0
- package/src/version.ts +1 -1
package/dist/plugin/index.js
CHANGED
|
@@ -314,9 +314,43 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
// src/combinators/scalar.ts
|
|
318
|
+
var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
|
|
319
|
+
function scalarOf(combinator) {
|
|
320
|
+
return combinator._parseScalar;
|
|
321
|
+
}
|
|
322
|
+
function scalarTree(parser2, seen) {
|
|
323
|
+
if (seen.has(parser2)) return true;
|
|
324
|
+
if (parser2._parseScalar === void 0) return false;
|
|
325
|
+
seen.add(parser2);
|
|
326
|
+
const def = parser2._def;
|
|
327
|
+
if (!SCALAR_TAG.test(def.tag)) return false;
|
|
328
|
+
if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
|
|
329
|
+
if ("parser" in def && !scalarTree(def.parser, seen)) return false;
|
|
330
|
+
if ("separator" in def && !scalarTree(def.separator, seen)) return false;
|
|
331
|
+
return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
|
|
332
|
+
}
|
|
333
|
+
function scalarRootOf(combinator) {
|
|
334
|
+
const scalar = combinator._parseScalar;
|
|
335
|
+
const def = combinator._def;
|
|
336
|
+
return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
|
|
337
|
+
}
|
|
338
|
+
|
|
317
339
|
// src/combinators/ref.ts
|
|
340
|
+
function withRuleTrivia(trivia2, ctx, run) {
|
|
341
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
342
|
+
ctx.trivia = trivia2;
|
|
343
|
+
ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
|
|
344
|
+
try {
|
|
345
|
+
return run();
|
|
346
|
+
} finally {
|
|
347
|
+
ctx.trivia = void 0;
|
|
348
|
+
ctx.triviaKindLabels = savedLabels;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
318
351
|
function ref() {
|
|
319
352
|
let resolved = null;
|
|
353
|
+
let resolvedScalar = null;
|
|
320
354
|
let ownBoundary = false;
|
|
321
355
|
const meta = {
|
|
322
356
|
firstSet: any(),
|
|
@@ -333,25 +367,28 @@ function ref() {
|
|
|
333
367
|
return resolved;
|
|
334
368
|
}
|
|
335
369
|
},
|
|
370
|
+
_parseScalar(input, pos, ctx) {
|
|
371
|
+
const scalar = resolvedScalar;
|
|
372
|
+
if (!scalar) throw new Error("ref<T>() used before .define() was called");
|
|
373
|
+
const gt = meta.grammarTrivia;
|
|
374
|
+
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
375
|
+
return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
|
|
376
|
+
}
|
|
377
|
+
return scalar(input, pos, ctx);
|
|
378
|
+
},
|
|
336
379
|
parse(input, pos, ctx) {
|
|
337
|
-
|
|
380
|
+
const parser2 = resolved;
|
|
381
|
+
if (!parser2) throw new Error("ref<T>() used before .define() was called");
|
|
338
382
|
const gt = meta.grammarTrivia;
|
|
339
383
|
if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
|
|
340
|
-
|
|
341
|
-
ctx.trivia = gt;
|
|
342
|
-
ctx.triviaKindLabels = gt._meta.triviaKindLabels;
|
|
343
|
-
try {
|
|
344
|
-
return resolved.parse(input, pos, ctx);
|
|
345
|
-
} finally {
|
|
346
|
-
ctx.trivia = void 0;
|
|
347
|
-
ctx.triviaKindLabels = savedLabels;
|
|
348
|
-
}
|
|
384
|
+
return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
|
|
349
385
|
}
|
|
350
|
-
return
|
|
386
|
+
return parser2.parse(input, pos, ctx);
|
|
351
387
|
},
|
|
352
388
|
define(p) {
|
|
353
389
|
if (resolved) throw new Error("ref<T>() already defined");
|
|
354
390
|
resolved = p;
|
|
391
|
+
resolvedScalar = scalarOf(p);
|
|
355
392
|
ownBoundary = hasOwnTriviaBoundary(p);
|
|
356
393
|
meta.firstSet = p._meta.firstSet;
|
|
357
394
|
meta.canMatchNewline = p._meta.canMatchNewline;
|
|
@@ -737,6 +774,7 @@ function createParseContext() {
|
|
|
737
774
|
_fe: void 0,
|
|
738
775
|
_fx: void 0,
|
|
739
776
|
_fc: void 0,
|
|
777
|
+
_sv: void 0,
|
|
740
778
|
_probe: void 0,
|
|
741
779
|
_cstChildren: void 0,
|
|
742
780
|
_cstLeaves: void 0,
|
|
@@ -1574,6 +1612,24 @@ function parser(opts, root) {
|
|
|
1574
1612
|
const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
|
|
1575
1613
|
const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
|
|
1576
1614
|
const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
|
|
1615
|
+
const rootScalar = scalarOf(root);
|
|
1616
|
+
const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
|
|
1617
|
+
const parseScalar = scalarEligible ? (input, pos, ctx) => {
|
|
1618
|
+
const savedTrivia = ctx.trivia;
|
|
1619
|
+
const savedLabels = ctx.triviaKindLabels;
|
|
1620
|
+
if (clearTrivia) {
|
|
1621
|
+
ctx.trivia = void 0;
|
|
1622
|
+
ctx.triviaKindLabels = void 0;
|
|
1623
|
+
} else if (scopeTrivia !== void 0) {
|
|
1624
|
+
ctx.trivia = scopeTrivia;
|
|
1625
|
+
ctx.triviaKindLabels = scopeLabels;
|
|
1626
|
+
}
|
|
1627
|
+
const end = rootScalar(input, pos, ctx);
|
|
1628
|
+
ctx.trivia = savedTrivia;
|
|
1629
|
+
ctx.triviaKindLabels = savedLabels;
|
|
1630
|
+
return end;
|
|
1631
|
+
} : void 0;
|
|
1632
|
+
let publicScalar;
|
|
1577
1633
|
const grammar = {
|
|
1578
1634
|
_tag: "grammar",
|
|
1579
1635
|
_meta: {
|
|
@@ -1597,7 +1653,20 @@ function parser(opts, root) {
|
|
|
1597
1653
|
constructionTrackLines: trackLinesPolicy,
|
|
1598
1654
|
...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
|
|
1599
1655
|
},
|
|
1656
|
+
_parseScalar: parseScalar,
|
|
1600
1657
|
parse(input, pos, _ctx) {
|
|
1658
|
+
if (pos === void 0 && _ctx === void 0) {
|
|
1659
|
+
publicScalar ??= scalarRootOf(grammar) ?? null;
|
|
1660
|
+
if (publicScalar) {
|
|
1661
|
+
const ctx2 = createParseContext();
|
|
1662
|
+
const end = publicScalar(input, 0, ctx2);
|
|
1663
|
+
if (end < 0) {
|
|
1664
|
+
const at = ~end;
|
|
1665
|
+
return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
|
|
1666
|
+
}
|
|
1667
|
+
return { ok: true, value: ctx2._sv, span: { start: 0, end } };
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1601
1670
|
if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
|
|
1602
1671
|
const trackLines = trackLinesOf(_ctx);
|
|
1603
1672
|
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
@@ -1889,6 +1958,28 @@ function literal(value, opts = {}) {
|
|
|
1889
1958
|
isTrivia: false
|
|
1890
1959
|
};
|
|
1891
1960
|
const canMatchNewline = meta.canMatchNewline;
|
|
1961
|
+
const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
|
|
1962
|
+
const code = value.charCodeAt(0);
|
|
1963
|
+
return (input, pos, ctx) => {
|
|
1964
|
+
if (input.charCodeAt(pos) === code) {
|
|
1965
|
+
ctx._sv = value;
|
|
1966
|
+
return pos + 1;
|
|
1967
|
+
}
|
|
1968
|
+
ctx._fx = expected;
|
|
1969
|
+
return ~pos;
|
|
1970
|
+
};
|
|
1971
|
+
})() : (input, pos, ctx) => {
|
|
1972
|
+
const end = pos + value.length;
|
|
1973
|
+
if (end <= input.length) {
|
|
1974
|
+
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
1975
|
+
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
1976
|
+
ctx._sv = matchedValue;
|
|
1977
|
+
return end;
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
ctx._fx = expected;
|
|
1981
|
+
return ~pos;
|
|
1982
|
+
};
|
|
1892
1983
|
if (caseInsensitive) {
|
|
1893
1984
|
const upper = value.toUpperCase();
|
|
1894
1985
|
const lower = value.toLowerCase();
|
|
@@ -1929,6 +2020,7 @@ function literal(value, opts = {}) {
|
|
|
1929
2020
|
_tag: "literal",
|
|
1930
2021
|
_meta: meta,
|
|
1931
2022
|
_def: { tag: "literal", value, caseInsensitive },
|
|
2023
|
+
_parseScalar: parseScalar,
|
|
1932
2024
|
parse: parse2
|
|
1933
2025
|
};
|
|
1934
2026
|
}
|
|
@@ -2268,10 +2360,32 @@ function regex(pattern, flags = "") {
|
|
|
2268
2360
|
const canMatchNewline = raw.canMatchNewline;
|
|
2269
2361
|
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
2270
2362
|
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
2363
|
+
const expected = directTerminalFailureExpected(def);
|
|
2364
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2365
|
+
const scanEnd = scan?.(input, pos);
|
|
2366
|
+
if (scanEnd !== void 0) {
|
|
2367
|
+
if (scanEnd === null) {
|
|
2368
|
+
ctx._fx = expected;
|
|
2369
|
+
return ~pos;
|
|
2370
|
+
}
|
|
2371
|
+
ctx._sv = input.slice(pos, scanEnd);
|
|
2372
|
+
return scanEnd;
|
|
2373
|
+
}
|
|
2374
|
+
anchored.lastIndex = pos;
|
|
2375
|
+
const match = anchored.exec(input);
|
|
2376
|
+
if (match === null) {
|
|
2377
|
+
ctx._fx = expected;
|
|
2378
|
+
return ~pos;
|
|
2379
|
+
}
|
|
2380
|
+
ctx._sv = match[0];
|
|
2381
|
+
return pos + match[0].length;
|
|
2382
|
+
};
|
|
2271
2383
|
return {
|
|
2272
2384
|
_tag: "regex",
|
|
2273
2385
|
_meta: meta,
|
|
2274
2386
|
_def: def,
|
|
2387
|
+
_stickyRegex: anchored,
|
|
2388
|
+
_parseScalar: parseScalar,
|
|
2275
2389
|
parse(input, pos, ctx) {
|
|
2276
2390
|
const scanEnd = scan?.(input, pos);
|
|
2277
2391
|
if (scanEnd !== void 0) {
|
|
@@ -2363,16 +2477,26 @@ function keywords(words, opts = {}) {
|
|
|
2363
2477
|
caseInsensitive: opts.caseInsensitive ?? false,
|
|
2364
2478
|
boundary: opts.boundary
|
|
2365
2479
|
};
|
|
2480
|
+
const expected = directTerminalFailureExpected(def);
|
|
2481
|
+
const parseScalar = (input, pos, ctx) => {
|
|
2482
|
+
re.lastIndex = pos;
|
|
2483
|
+
const m = re.exec(input);
|
|
2484
|
+
if (m === null) {
|
|
2485
|
+
ctx._fx = expected;
|
|
2486
|
+
return ~pos;
|
|
2487
|
+
}
|
|
2488
|
+
ctx._sv = m[0];
|
|
2489
|
+
return pos + m[0].length;
|
|
2490
|
+
};
|
|
2366
2491
|
return {
|
|
2367
2492
|
_tag: "keywords",
|
|
2368
2493
|
_meta: meta,
|
|
2369
2494
|
_def: def,
|
|
2495
|
+
_parseScalar: parseScalar,
|
|
2370
2496
|
parse(input, pos, ctx) {
|
|
2371
2497
|
re.lastIndex = pos;
|
|
2372
2498
|
const m = re.exec(input);
|
|
2373
|
-
if (m === null
|
|
2374
|
-
return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
2375
|
-
}
|
|
2499
|
+
if (m === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
2376
2500
|
const value = m[0];
|
|
2377
2501
|
const span = { start: pos, end: pos + value.length };
|
|
2378
2502
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
@@ -2403,6 +2527,9 @@ var fastScanner3;
|
|
|
2403
2527
|
function needsDeferredTriviaCommit(ctx) {
|
|
2404
2528
|
return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
|
|
2405
2529
|
}
|
|
2530
|
+
function needsTriviaRollback(ctx) {
|
|
2531
|
+
return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
|
|
2532
|
+
}
|
|
2406
2533
|
function saveTriviaMark(ctx) {
|
|
2407
2534
|
const m = saveCstMark(ctx);
|
|
2408
2535
|
return {
|
|
@@ -2519,7 +2646,8 @@ function advanceTrivia(input, cur, ctx) {
|
|
|
2519
2646
|
const triviaP = ctx.trivia;
|
|
2520
2647
|
if (!triviaP) return cur;
|
|
2521
2648
|
if (!ctx.trackLines) {
|
|
2522
|
-
const
|
|
2649
|
+
const classified = triviaP._meta.triviaScanner;
|
|
2650
|
+
const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
|
|
2523
2651
|
if (fast2) return fast2(input, cur);
|
|
2524
2652
|
if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
|
|
2525
2653
|
const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
|
|
@@ -3124,6 +3252,7 @@ function sequence(...parsers) {
|
|
|
3124
3252
|
(adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
|
|
3125
3253
|
}
|
|
3126
3254
|
const hasAdjacency = adjacency !== null;
|
|
3255
|
+
const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
|
|
3127
3256
|
const meta = {
|
|
3128
3257
|
// Union through the nullable prefix — a leading optional()/many() lets a later
|
|
3129
3258
|
// term's first char start the sequence. Just `parsers[0]` under-approximates.
|
|
@@ -3132,165 +3261,96 @@ function sequence(...parsers) {
|
|
|
3132
3261
|
isTrivia: false
|
|
3133
3262
|
};
|
|
3134
3263
|
const def = { tag: "sequence", parsers };
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
followSentinels ??= parsers.map((_, i) => {
|
|
3138
|
-
const fs3 = parsers.slice(i + 1).reduce(
|
|
3139
|
-
(acc, p) => union(acc, firstSetOf(p)),
|
|
3140
|
-
{ kind: "empty" }
|
|
3141
|
-
);
|
|
3142
|
-
return firstSetSentinel(fs3);
|
|
3143
|
-
});
|
|
3144
|
-
const values = def.valueUnused ? void 0 : [];
|
|
3264
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
3265
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3145
3266
|
let cur = pos;
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
const mTlog = cstTlLen(ctx);
|
|
3158
|
-
const mLog = ctx._triviaLog?.length ?? 0;
|
|
3159
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3160
|
-
let scanEnd;
|
|
3161
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
3162
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
3163
|
-
} else {
|
|
3164
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3165
|
-
}
|
|
3166
|
-
const scanTlog = cstTlLen(ctx);
|
|
3167
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
3168
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3169
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
3170
|
-
if (!result2.ok) return result2;
|
|
3171
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
3172
|
-
else rollbackScannedTriviaAt(
|
|
3173
|
-
ctx,
|
|
3174
|
-
mTlog,
|
|
3175
|
-
scanTlog,
|
|
3176
|
-
mLog,
|
|
3177
|
-
scanLog,
|
|
3178
|
-
mRootLog,
|
|
3179
|
-
scanRootLog
|
|
3180
|
-
);
|
|
3181
|
-
if (values !== void 0) values.push(result2.value);
|
|
3182
|
-
continue;
|
|
3183
|
-
}
|
|
3184
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
3185
|
-
if (!result.ok) return result;
|
|
3186
|
-
if (values !== void 0) values.push(result.value);
|
|
3187
|
-
cur = result.span.end;
|
|
3267
|
+
if (strictArity !== 0) {
|
|
3268
|
+
cur = scalarParsers[0](input, cur, ctx);
|
|
3269
|
+
if (cur < 0) return cur;
|
|
3270
|
+
const first = ctx._sv;
|
|
3271
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
3272
|
+
cur = scalarParsers[1](input, cur, ctx);
|
|
3273
|
+
if (cur < 0) return cur;
|
|
3274
|
+
const second = ctx._sv;
|
|
3275
|
+
if (strictArity === 2) {
|
|
3276
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second];
|
|
3277
|
+
return cur;
|
|
3188
3278
|
}
|
|
3189
|
-
|
|
3190
|
-
|
|
3279
|
+
if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
|
|
3280
|
+
cur = scalarParsers[2](input, cur, ctx);
|
|
3281
|
+
if (cur < 0) return cur;
|
|
3282
|
+
ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
|
|
3283
|
+
return cur;
|
|
3191
3284
|
}
|
|
3192
|
-
return {
|
|
3193
|
-
ok: true,
|
|
3194
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3195
|
-
value: values ?? void 0,
|
|
3196
|
-
span: { start: pos, end: cur }
|
|
3197
|
-
};
|
|
3198
|
-
}
|
|
3199
|
-
function parseAdjacent(input, pos, ctx) {
|
|
3200
3285
|
const values = def.valueUnused ? void 0 : [];
|
|
3201
|
-
let
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
const mRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3214
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
3215
|
-
scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
3216
|
-
} else {
|
|
3217
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3218
|
-
}
|
|
3219
|
-
const scanTlog = cstTlLen(ctx);
|
|
3220
|
-
const scanLog = ctx._triviaLog?.length ?? 0;
|
|
3221
|
-
const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
|
|
3222
|
-
const result2 = parsers[i].parse(input, scanEnd, ctx);
|
|
3223
|
-
if (!result2.ok) return result2;
|
|
3224
|
-
if (result2.span.end > scanEnd) cur = result2.span.end;
|
|
3225
|
-
else rollbackScannedTriviaAt(
|
|
3226
|
-
ctx,
|
|
3227
|
-
mTlog,
|
|
3228
|
-
scanTlog,
|
|
3229
|
-
mLog,
|
|
3230
|
-
scanLog,
|
|
3231
|
-
mRootLog,
|
|
3232
|
-
scanRootLog
|
|
3233
|
-
);
|
|
3234
|
-
if (values !== void 0) values.push(result2.value);
|
|
3235
|
-
continue;
|
|
3236
|
-
}
|
|
3237
|
-
const result = parsers[i].parse(input, cur, ctx);
|
|
3238
|
-
if (!result.ok) return result;
|
|
3239
|
-
if (values !== void 0) values.push(result.value);
|
|
3240
|
-
cur = result.span.end;
|
|
3241
|
-
}
|
|
3242
|
-
return {
|
|
3243
|
-
ok: true,
|
|
3244
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3245
|
-
value: values ?? void 0,
|
|
3246
|
-
span: { start: pos, end: cur }
|
|
3247
|
-
};
|
|
3248
|
-
}
|
|
3286
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
3287
|
+
let termPos = cur;
|
|
3288
|
+
if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
|
|
3289
|
+
const end = scalarParsers[i](input, termPos, ctx);
|
|
3290
|
+
if (end < 0) return end;
|
|
3291
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
3292
|
+
if (end > termPos || termPos === cur) cur = end;
|
|
3293
|
+
}
|
|
3294
|
+
ctx._sv = values;
|
|
3295
|
+
return cur;
|
|
3296
|
+
};
|
|
3297
|
+
let followSentinels;
|
|
3249
3298
|
return {
|
|
3250
3299
|
_tag: "sequence",
|
|
3251
3300
|
_meta: meta,
|
|
3252
3301
|
_def: def,
|
|
3302
|
+
_parseScalar: hasAdjacency ? void 0 : parseScalar,
|
|
3253
3303
|
parse(input, pos, ctx) {
|
|
3254
|
-
|
|
3255
|
-
if (
|
|
3304
|
+
const tolerant = ctx._tolerant === true;
|
|
3305
|
+
if (tolerant) {
|
|
3306
|
+
followSentinels ??= parsers.map((_, i) => firstSetSentinel(
|
|
3307
|
+
parsers.slice(i + 1).reduce(
|
|
3308
|
+
(set, parser2) => union(set, firstSetOf(parser2)),
|
|
3309
|
+
{ kind: "empty" }
|
|
3310
|
+
)
|
|
3311
|
+
));
|
|
3312
|
+
}
|
|
3313
|
+
const inheritedSync = ctx._sync;
|
|
3314
|
+
const deferredTrivia = needsDeferredTriviaCommit(ctx);
|
|
3256
3315
|
const values = def.valueUnused ? void 0 : [];
|
|
3257
3316
|
let cur = pos;
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
const
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
} else {
|
|
3267
|
-
scanEnd = advanceTrivia(input, cur, ctx);
|
|
3317
|
+
try {
|
|
3318
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
3319
|
+
if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
|
|
3320
|
+
const assertion = adjacency?.[i];
|
|
3321
|
+
if (assertion) {
|
|
3322
|
+
if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
|
|
3323
|
+
if (values !== void 0) values.push(null);
|
|
3324
|
+
continue;
|
|
3268
3325
|
}
|
|
3269
|
-
|
|
3270
|
-
const
|
|
3271
|
-
const
|
|
3272
|
-
const
|
|
3273
|
-
if (
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3326
|
+
let termPos = cur;
|
|
3327
|
+
const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
3328
|
+
const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
3329
|
+
const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
3330
|
+
if (ctx.trivia && i > 0) {
|
|
3331
|
+
termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
|
|
3332
|
+
}
|
|
3333
|
+
const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
|
|
3334
|
+
const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
|
|
3335
|
+
const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
|
|
3336
|
+
const result = parsers[i].parse(input, termPos, ctx);
|
|
3337
|
+
if (!result.ok) return result;
|
|
3338
|
+
if (values !== void 0) values.push(result.value);
|
|
3339
|
+
if (result.span.end > termPos || termPos === cur) cur = result.span.end;
|
|
3340
|
+
else if (deferredTrivia) {
|
|
3277
3341
|
rollbackScannedTriviaAt(
|
|
3278
3342
|
ctx,
|
|
3279
|
-
|
|
3343
|
+
markTlog,
|
|
3280
3344
|
scanTlog,
|
|
3281
|
-
|
|
3345
|
+
markLog,
|
|
3282
3346
|
scanLog,
|
|
3283
|
-
|
|
3347
|
+
markRootLog,
|
|
3284
3348
|
scanRootLog
|
|
3285
3349
|
);
|
|
3286
3350
|
}
|
|
3287
|
-
if (values !== void 0) values.push(result2.value);
|
|
3288
|
-
continue;
|
|
3289
3351
|
}
|
|
3290
|
-
|
|
3291
|
-
if (
|
|
3292
|
-
if (values !== void 0) values.push(result.value);
|
|
3293
|
-
cur = result.span.end;
|
|
3352
|
+
} finally {
|
|
3353
|
+
if (tolerant) ctx._sync = inheritedSync;
|
|
3294
3354
|
}
|
|
3295
3355
|
return {
|
|
3296
3356
|
ok: true,
|
|
@@ -3422,7 +3482,8 @@ function choice(...args) {
|
|
|
3422
3482
|
disjoint
|
|
3423
3483
|
};
|
|
3424
3484
|
const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
|
|
3425
|
-
const
|
|
3485
|
+
const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
|
|
3486
|
+
const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
|
|
3426
3487
|
let greedyLitMap = null;
|
|
3427
3488
|
let sortedParsers = null;
|
|
3428
3489
|
const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
|
|
@@ -3436,6 +3497,37 @@ function choice(...args) {
|
|
|
3436
3497
|
} else if (strategy?.tag === "literalsLongestFirst") {
|
|
3437
3498
|
sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
|
|
3438
3499
|
}
|
|
3500
|
+
const scalarParsers = parsers.map(scalarOf);
|
|
3501
|
+
const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
|
|
3502
|
+
const scalarExpected = parsers.flatMap(deriveExpected);
|
|
3503
|
+
const parseScalar = (input, pos, ctx) => {
|
|
3504
|
+
if (disjoint) {
|
|
3505
|
+
const code = pos < input.length ? input.codePointAt(pos) : -1;
|
|
3506
|
+
let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
|
|
3507
|
+
if (idx < 0 && code >= 0) {
|
|
3508
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
3509
|
+
if (inFirstSet(code, parsers[i]._meta.firstSet)) {
|
|
3510
|
+
idx = i;
|
|
3511
|
+
break;
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
if (idx >= 0) {
|
|
3516
|
+
const gate2 = gates[idx];
|
|
3517
|
+
if (!gate2 || gate2(ctx.state)) return scalarParsers[idx](input, pos, ctx);
|
|
3518
|
+
ctx._fx = deriveExpected(parsers[idx]);
|
|
3519
|
+
return ~pos;
|
|
3520
|
+
}
|
|
3521
|
+
} else {
|
|
3522
|
+
for (let i = 0; i < scalarParsers.length; i++) {
|
|
3523
|
+
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
3524
|
+
const end = scalarParsers[i](input, pos, ctx);
|
|
3525
|
+
if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
ctx._fx = scalarExpected;
|
|
3529
|
+
return ~pos;
|
|
3530
|
+
};
|
|
3439
3531
|
return {
|
|
3440
3532
|
_tag: "choice",
|
|
3441
3533
|
_meta: meta,
|
|
@@ -3447,6 +3539,7 @@ function choice(...args) {
|
|
|
3447
3539
|
strategy: strategy ?? { tag: "firstMatch" },
|
|
3448
3540
|
autoNot
|
|
3449
3541
|
},
|
|
3542
|
+
_parseScalar: scalarEligible ? parseScalar : void 0,
|
|
3450
3543
|
parse(input, pos, ctx) {
|
|
3451
3544
|
const expected = [];
|
|
3452
3545
|
let expectedAt = pos;
|
|
@@ -3978,8 +4071,8 @@ function attempt(parser2) {
|
|
|
3978
4071
|
}
|
|
3979
4072
|
|
|
3980
4073
|
// src/combinators/repeat.ts
|
|
3981
|
-
function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
3982
|
-
const mark = saveTriviaMark(ctx);
|
|
4074
|
+
function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
|
|
4075
|
+
const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
|
|
3983
4076
|
let pos = cur;
|
|
3984
4077
|
if (ctx.trivia) {
|
|
3985
4078
|
if (needsDeferredTriviaCommit(ctx)) {
|
|
@@ -3989,24 +4082,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
|
|
|
3989
4082
|
}
|
|
3990
4083
|
}
|
|
3991
4084
|
if (pos >= input.length && !mandatory) {
|
|
3992
|
-
rollbackTrivia(ctx, mark);
|
|
4085
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3993
4086
|
return "stop";
|
|
3994
4087
|
}
|
|
3995
4088
|
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
3996
|
-
rollbackTrivia(ctx, mark);
|
|
4089
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
3997
4090
|
return "stop";
|
|
3998
4091
|
}
|
|
3999
4092
|
const result = combinator.parse(input, pos, ctx);
|
|
4000
4093
|
if (!result.ok) {
|
|
4001
|
-
rollbackTrivia(ctx, mark);
|
|
4094
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4002
4095
|
if (result.committed) return { fail: result, failPos: pos };
|
|
4003
4096
|
return { fail: result, failPos: pos };
|
|
4004
4097
|
}
|
|
4005
4098
|
if (result.span.end === pos && !mandatory) {
|
|
4006
|
-
rollbackTrivia(ctx, mark);
|
|
4099
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4007
4100
|
return "stop";
|
|
4008
4101
|
}
|
|
4009
|
-
return
|
|
4102
|
+
return result;
|
|
4010
4103
|
}
|
|
4011
4104
|
function resolveBounds(what, opts) {
|
|
4012
4105
|
const min = opts.min ?? 0;
|
|
@@ -4019,6 +4112,21 @@ function resolveBounds(what, opts) {
|
|
|
4019
4112
|
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
4020
4113
|
return { min, max };
|
|
4021
4114
|
}
|
|
4115
|
+
function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
|
|
4116
|
+
while (cur < input.length && remaining > 0) {
|
|
4117
|
+
let itemPos = cur;
|
|
4118
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4119
|
+
if (itemPos >= input.length) break;
|
|
4120
|
+
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
4121
|
+
const end = child(input, itemPos, ctx);
|
|
4122
|
+
if (end <= itemPos) break;
|
|
4123
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4124
|
+
cur = end;
|
|
4125
|
+
remaining--;
|
|
4126
|
+
}
|
|
4127
|
+
ctx._sv = values;
|
|
4128
|
+
return cur;
|
|
4129
|
+
}
|
|
4022
4130
|
function many(combinator, opts = {}) {
|
|
4023
4131
|
const { min, max } = resolveBounds("many()", opts);
|
|
4024
4132
|
if (min >= 1) return atLeast(combinator, min, max);
|
|
@@ -4030,17 +4138,21 @@ function many(combinator, opts = {}) {
|
|
|
4030
4138
|
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
4031
4139
|
let expected;
|
|
4032
4140
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4141
|
+
const scalarChild = scalarOf(combinator);
|
|
4142
|
+
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
4033
4143
|
return {
|
|
4034
4144
|
_tag: "many",
|
|
4035
4145
|
_meta: meta,
|
|
4036
4146
|
_def: def,
|
|
4147
|
+
_parseScalar: parseScalar,
|
|
4037
4148
|
parse(input, pos, ctx) {
|
|
4038
4149
|
const values = def.valueUnused ? void 0 : [];
|
|
4150
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4039
4151
|
let cur = pos;
|
|
4040
4152
|
let count = 0;
|
|
4041
4153
|
while (cur < input.length) {
|
|
4042
4154
|
if (count >= max) break;
|
|
4043
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4155
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4044
4156
|
if (item === "stop") break;
|
|
4045
4157
|
if ("fail" in item) {
|
|
4046
4158
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -4057,7 +4169,7 @@ function many(combinator, opts = {}) {
|
|
|
4057
4169
|
}
|
|
4058
4170
|
if (values !== void 0) values.push(item.value);
|
|
4059
4171
|
count++;
|
|
4060
|
-
cur = item.end;
|
|
4172
|
+
cur = item.span.end;
|
|
4061
4173
|
}
|
|
4062
4174
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4063
4175
|
}
|
|
@@ -4075,30 +4187,47 @@ function atLeast(combinator, min, max) {
|
|
|
4075
4187
|
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4076
4188
|
let expected;
|
|
4077
4189
|
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4190
|
+
const scalarChild = scalarOf(combinator);
|
|
4191
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4192
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4193
|
+
if (cur < 0) return cur;
|
|
4194
|
+
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
4195
|
+
for (let count = 1; count < min; count++) {
|
|
4196
|
+
let itemPos = cur;
|
|
4197
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4198
|
+
const end = scalarChild(input, itemPos, ctx);
|
|
4199
|
+
if (end < 0) return ~cur;
|
|
4200
|
+
cur = end;
|
|
4201
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4202
|
+
}
|
|
4203
|
+
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
4204
|
+
};
|
|
4078
4205
|
return {
|
|
4079
4206
|
_tag: "oneOrMore",
|
|
4080
4207
|
_meta: meta,
|
|
4081
4208
|
_def: def,
|
|
4209
|
+
_parseScalar: parseScalar,
|
|
4082
4210
|
parse(input, pos, ctx) {
|
|
4083
4211
|
const first = combinator.parse(input, pos, ctx);
|
|
4084
4212
|
if (!first.ok) return first;
|
|
4085
4213
|
const values = def.valueUnused ? void 0 : [first.value];
|
|
4214
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4086
4215
|
let cur = first.span.end;
|
|
4087
4216
|
let count = 1;
|
|
4088
4217
|
while (count < min) {
|
|
4089
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true);
|
|
4218
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
4090
4219
|
if (item === "stop" || "fail" in item) {
|
|
4091
4220
|
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
4092
4221
|
expected ??= deriveExpected(combinator);
|
|
4093
4222
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
4094
4223
|
}
|
|
4095
4224
|
if (values !== void 0) values.push(item.value);
|
|
4096
|
-
cur = item.end;
|
|
4225
|
+
cur = item.span.end;
|
|
4097
4226
|
count++;
|
|
4098
4227
|
}
|
|
4099
4228
|
while (cur < input.length) {
|
|
4100
4229
|
if (count >= max) break;
|
|
4101
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false);
|
|
4230
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4102
4231
|
if (item === "stop") break;
|
|
4103
4232
|
if ("fail" in item) {
|
|
4104
4233
|
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
@@ -4115,7 +4244,7 @@ function atLeast(combinator, min, max) {
|
|
|
4115
4244
|
}
|
|
4116
4245
|
if (values !== void 0) values.push(item.value);
|
|
4117
4246
|
count++;
|
|
4118
|
-
cur = item.end;
|
|
4247
|
+
cur = item.span.end;
|
|
4119
4248
|
}
|
|
4120
4249
|
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4121
4250
|
}
|
|
@@ -4128,10 +4257,22 @@ function optional(combinator) {
|
|
|
4128
4257
|
isTrivia: false
|
|
4129
4258
|
};
|
|
4130
4259
|
const firstSetSkippable = !matchesEmpty(combinator);
|
|
4260
|
+
const scalarChild = scalarOf(combinator);
|
|
4261
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4262
|
+
if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
|
|
4263
|
+
ctx._sv = null;
|
|
4264
|
+
return pos;
|
|
4265
|
+
}
|
|
4266
|
+
const end = scalarChild(input, pos, ctx);
|
|
4267
|
+
if (end >= 0) return end;
|
|
4268
|
+
ctx._sv = null;
|
|
4269
|
+
return pos;
|
|
4270
|
+
};
|
|
4131
4271
|
return {
|
|
4132
4272
|
_tag: "optional",
|
|
4133
4273
|
_meta: meta,
|
|
4134
4274
|
_def: { tag: "optional", parser: combinator },
|
|
4275
|
+
_parseScalar: parseScalar,
|
|
4135
4276
|
parse(input, pos, ctx) {
|
|
4136
4277
|
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
4137
4278
|
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
@@ -4168,6 +4309,43 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
4168
4309
|
expected ??= deriveExpected(combinator);
|
|
4169
4310
|
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
4170
4311
|
};
|
|
4312
|
+
const scalarExpected = deriveExpected(combinator);
|
|
4313
|
+
const scalarChild = scalarOf(combinator);
|
|
4314
|
+
const scalarSeparator = scalarOf(separator);
|
|
4315
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4316
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4317
|
+
if (cur < 0) {
|
|
4318
|
+
if (min >= 1) {
|
|
4319
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4320
|
+
return ~pos;
|
|
4321
|
+
}
|
|
4322
|
+
ctx._sv = [];
|
|
4323
|
+
return pos;
|
|
4324
|
+
}
|
|
4325
|
+
const values = [ctx._sv];
|
|
4326
|
+
while (values.length < max && (cur < input.length || values.length < min)) {
|
|
4327
|
+
const beforeSeparator = cur;
|
|
4328
|
+
let separatorPos = cur;
|
|
4329
|
+
if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
|
|
4330
|
+
const separatorEnd = scalarSeparator(input, separatorPos, ctx);
|
|
4331
|
+
if (separatorEnd < 0) break;
|
|
4332
|
+
let itemPos = separatorEnd;
|
|
4333
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
|
|
4334
|
+
const itemEnd = scalarChild(input, itemPos, ctx);
|
|
4335
|
+
if (itemEnd < 0) {
|
|
4336
|
+
cur = trailing === "allow" ? separatorEnd : beforeSeparator;
|
|
4337
|
+
break;
|
|
4338
|
+
}
|
|
4339
|
+
values.push(ctx._sv);
|
|
4340
|
+
cur = itemEnd;
|
|
4341
|
+
}
|
|
4342
|
+
if (values.length < min) {
|
|
4343
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4344
|
+
return ~cur;
|
|
4345
|
+
}
|
|
4346
|
+
ctx._sv = values;
|
|
4347
|
+
return cur;
|
|
4348
|
+
};
|
|
4171
4349
|
return {
|
|
4172
4350
|
_tag: "sepBy",
|
|
4173
4351
|
_meta: meta,
|
|
@@ -4183,6 +4361,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
|
|
|
4183
4361
|
// this option surface already; parity is held by test/parity, not by hope.
|
|
4184
4362
|
...keepSeparators ? { keepSeparators: true } : {}
|
|
4185
4363
|
},
|
|
4364
|
+
_parseScalar: keepSeparators ? void 0 : parseScalar,
|
|
4186
4365
|
parse(input, pos, ctx) {
|
|
4187
4366
|
const first = combinator.parse(input, pos, ctx);
|
|
4188
4367
|
const values = [];
|
|
@@ -4798,11 +4977,54 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
4798
4977
|
}
|
|
4799
4978
|
|
|
4800
4979
|
// src/combinators/map.ts
|
|
4980
|
+
var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
|
|
4801
4981
|
function transform(combinator, fn) {
|
|
4982
|
+
const observesSpan = fn.length > 1;
|
|
4983
|
+
const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
|
|
4984
|
+
const terms = sequenceDef?.parsers;
|
|
4985
|
+
const inner = terms?.[1];
|
|
4986
|
+
const fused = terms?.length === 3 && terms[0]._def.tag === "literal" && terms[0]._def.value === '"' && !terms[0]._def.caseInsensitive && inner._def.tag === "regex" && inner._def.source === JSON_STRING_BODY && inner._def.flags === "" && terms[2]._def.tag === "literal" && terms[2]._def.value === '"' && !terms[2]._def.caseInsensitive && inner._stickyRegex !== void 0;
|
|
4987
|
+
const child = scalarOf(combinator);
|
|
4988
|
+
const parseScalar = fused ? (() => {
|
|
4989
|
+
const body = inner._stickyRegex;
|
|
4990
|
+
const tuple = ['"', "", '"'];
|
|
4991
|
+
const expected = [JSON.stringify('"')];
|
|
4992
|
+
return (input, pos, ctx) => {
|
|
4993
|
+
if (ctx.trivia !== void 0) {
|
|
4994
|
+
const end2 = child(input, pos, ctx);
|
|
4995
|
+
if (end2 < 0) return end2;
|
|
4996
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
|
|
4997
|
+
return end2;
|
|
4998
|
+
}
|
|
4999
|
+
if (input.charCodeAt(pos) !== 34) {
|
|
5000
|
+
ctx._fx = expected;
|
|
5001
|
+
return ~pos;
|
|
5002
|
+
}
|
|
5003
|
+
body.lastIndex = pos + 1;
|
|
5004
|
+
const match = body.exec(input);
|
|
5005
|
+
const close = pos + 1 + match[0].length;
|
|
5006
|
+
if (input.charCodeAt(close) !== 34) {
|
|
5007
|
+
ctx._fx = expected;
|
|
5008
|
+
return ~close;
|
|
5009
|
+
}
|
|
5010
|
+
tuple[1] = match[0];
|
|
5011
|
+
const end = close + 1;
|
|
5012
|
+
ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
|
|
5013
|
+
return end;
|
|
5014
|
+
};
|
|
5015
|
+
})() : /* @__PURE__ */ (() => {
|
|
5016
|
+
return (input, pos, ctx) => {
|
|
5017
|
+
const end = child(input, pos, ctx);
|
|
5018
|
+
if (end < 0) return end;
|
|
5019
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
|
|
5020
|
+
return end;
|
|
5021
|
+
};
|
|
5022
|
+
})();
|
|
4802
5023
|
return {
|
|
4803
5024
|
_tag: "transform",
|
|
4804
5025
|
_meta: combinator._meta,
|
|
4805
5026
|
_def: { tag: "transform", parser: combinator, fn },
|
|
5027
|
+
_parseScalar: parseScalar,
|
|
4806
5028
|
parse(input, pos, ctx) {
|
|
4807
5029
|
const result = combinator.parse(input, pos, ctx);
|
|
4808
5030
|
if (!result.ok) return result;
|
|
@@ -4817,9 +5039,11 @@ function trivia(combinator) {
|
|
|
4817
5039
|
_meta: {
|
|
4818
5040
|
...combinator._meta,
|
|
4819
5041
|
isTrivia: true,
|
|
5042
|
+
triviaScanner: fastTriviaScanner(combinator),
|
|
4820
5043
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
4821
5044
|
},
|
|
4822
5045
|
_def: { tag: "trivia", parser: combinator },
|
|
5046
|
+
_parseScalar: scalarOf(combinator),
|
|
4823
5047
|
parse: combinator.parse.bind(combinator)
|
|
4824
5048
|
};
|
|
4825
5049
|
}
|
|
@@ -5774,7 +5998,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
5774
5998
|
if (!Number.isInteger(spec[2]) || spec[2] < 0) {
|
|
5775
5999
|
throw new TypeError("table balanced lexical program has an invalid scan reference");
|
|
5776
6000
|
}
|
|
5777
|
-
const
|
|
6001
|
+
const run = (_input, _pos, ctx, scan) => {
|
|
5778
6002
|
if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
|
|
5779
6003
|
const result = scan.parse(_input, _pos, ctx);
|
|
5780
6004
|
if (!result.ok) {
|
|
@@ -5784,7 +6008,7 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
5784
6008
|
}
|
|
5785
6009
|
return result.span.end;
|
|
5786
6010
|
};
|
|
5787
|
-
return Object.assign(
|
|
6011
|
+
return Object.assign(run, { scan: spec[2] });
|
|
5788
6012
|
}
|
|
5789
6013
|
if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
|
|
5790
6014
|
if (spec[0] === 1) {
|
|
@@ -7800,15 +8024,15 @@ function parseStringShape(source) {
|
|
|
7800
8024
|
if (source.length < 3 || source[source.length - 1] !== q2) return null;
|
|
7801
8025
|
const inner = source.slice(1, -1);
|
|
7802
8026
|
const CLS = String.raw`\[\^((?:\\.|[^\]])+)\]`;
|
|
7803
|
-
const
|
|
8027
|
+
const ESC = String.raw`\\\\(\.|\[\\s\\S\]|\[\\S\\s\])`;
|
|
7804
8028
|
let body;
|
|
7805
8029
|
let esc;
|
|
7806
|
-
let m = new RegExp(`^\\((?:\\?:)?${CLS}\\|${
|
|
8030
|
+
let m = new RegExp(`^\\((?:\\?:)?${CLS}\\|${ESC}\\)\\*$`).exec(inner);
|
|
7807
8031
|
if (m) {
|
|
7808
8032
|
body = m[1];
|
|
7809
8033
|
esc = m[2];
|
|
7810
8034
|
} else {
|
|
7811
|
-
m = new RegExp(`^\\((?:\\?:)?${
|
|
8035
|
+
m = new RegExp(`^\\((?:\\?:)?${ESC}\\|${CLS}\\)\\*$`).exec(inner);
|
|
7812
8036
|
if (m) {
|
|
7813
8037
|
esc = m[1];
|
|
7814
8038
|
body = m[2];
|
|
@@ -9371,6 +9595,9 @@ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTrivi
|
|
|
9371
9595
|
function q(s) {
|
|
9372
9596
|
return JSON.stringify(s);
|
|
9373
9597
|
}
|
|
9598
|
+
function isAsciiOnlyClass(cls) {
|
|
9599
|
+
return cls !== null && cls !== void 0 && cls.hi.length === 0;
|
|
9600
|
+
}
|
|
9374
9601
|
var NO_SINKS = { fd: false, er: false };
|
|
9375
9602
|
function sinkSlots(t, s) {
|
|
9376
9603
|
return `${s.fd ? `,${t}fd=0` : ""}${s.er ? `,${t}er=0` : ""}`;
|
|
@@ -9481,7 +9708,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9481
9708
|
const { code, k, fx, disp, dsp, triviaLabelled } = t;
|
|
9482
9709
|
const swapLegal = !cfg.trackLines;
|
|
9483
9710
|
const hostCst = cfg.hostCst;
|
|
9484
|
-
const
|
|
9711
|
+
const REC = prog.rec === 1 && cfg.tolerant;
|
|
9485
9712
|
if (cfg.coverage) throw new Unemittable("a coverage assembly");
|
|
9486
9713
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
9487
9714
|
const reachable = [...reachableSites(code, roots)];
|
|
@@ -9560,7 +9787,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
|
|
|
9560
9787
|
const op = code[ip];
|
|
9561
9788
|
sinkBits.set(
|
|
9562
9789
|
ip,
|
|
9563
|
-
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT ||
|
|
9790
|
+
op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
|
|
9564
9791
|
);
|
|
9565
9792
|
}
|
|
9566
9793
|
const sinkKids = [];
|
|
@@ -9917,12 +10144,13 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
|
|
|
9917
10144
|
return `${head}EC.e=pos;return ''}`;
|
|
9918
10145
|
case OP_GATE: {
|
|
9919
10146
|
const child = link(code[ip + 2]);
|
|
9920
|
-
const
|
|
10147
|
+
const resolved = t.cc[code[ip + 1]];
|
|
10148
|
+
const ci = classes.push([resolved]) - 1;
|
|
9921
10149
|
classPlan.push([code[ip + 1]]);
|
|
9922
10150
|
const cls = hoist("cl", `CLS[${ci}][0]`);
|
|
9923
10151
|
const xf = fxRef(code[ip + 3]);
|
|
9924
10152
|
return `${head}
|
|
9925
|
-
if(
|
|
10153
|
+
if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
|
|
9926
10154
|
return ${child}(input,pos,ctx)
|
|
9927
10155
|
}`;
|
|
9928
10156
|
}
|
|
@@ -9964,7 +10192,7 @@ if(v!==FAIL)return v
|
|
|
9964
10192
|
const err={_tag:'parseError',span:${prog.lines === 1 ? "spanLines(ctx,pos,pos)" : "{start:pos,end:pos}"},expected:${xf}}
|
|
9965
10193
|
const es=ctx._errors
|
|
9966
10194
|
if(es!==undefined)es.push(err)
|
|
9967
|
-
${
|
|
10195
|
+
${REC ? "if(ctx._tolerant===true)captureError(ctx,err)\n" : ""}ctx._fc=false
|
|
9968
10196
|
EC.e=pos
|
|
9969
10197
|
return err
|
|
9970
10198
|
}`;
|
|
@@ -10083,7 +10311,7 @@ return v
|
|
|
10083
10311
|
}
|
|
10084
10312
|
case OP_LEX_PROGRAM: {
|
|
10085
10313
|
const programId = code[ip + 1];
|
|
10086
|
-
const
|
|
10314
|
+
const run = hoist("lexProgram", `LEXPROG[${programId}]`);
|
|
10087
10315
|
const scanId = t.lexPrograms[programId].scan;
|
|
10088
10316
|
if (scanId !== void 0) return `${head}
|
|
10089
10317
|
const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
|
|
@@ -10101,7 +10329,7 @@ ctx._cstTriviaLog=undefined
|
|
|
10101
10329
|
ctx._triviaLog=undefined
|
|
10102
10330
|
ctx._rootTriviaLog=undefined
|
|
10103
10331
|
let e
|
|
10104
|
-
try{e=${
|
|
10332
|
+
try{e=${run}(input,pos,ctx,SCANS[${scanId}])}finally{
|
|
10105
10333
|
_pfScan=sScan
|
|
10106
10334
|
ctx.trivia=sTri
|
|
10107
10335
|
ctx.triviaKindLabels=sKinds
|
|
@@ -10120,7 +10348,7 @@ EC.e=e
|
|
|
10120
10348
|
return v
|
|
10121
10349
|
}`;
|
|
10122
10350
|
return `${head}
|
|
10123
|
-
const e=${
|
|
10351
|
+
const e=${run}(input,pos,ctx)
|
|
10124
10352
|
if(e<0)return FAIL
|
|
10125
10353
|
const v=input.slice(pos,e)
|
|
10126
10354
|
if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
|
|
@@ -10131,7 +10359,7 @@ return v
|
|
|
10131
10359
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
10132
10360
|
case OP_ATTEMPT: {
|
|
10133
10361
|
const child = link(code[ip + 1]);
|
|
10134
|
-
const clean = !
|
|
10362
|
+
const clean = !REC && failureRollbackClean(prog, ip);
|
|
10135
10363
|
const p = tmp();
|
|
10136
10364
|
return `${head}
|
|
10137
10365
|
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
@@ -10184,7 +10412,7 @@ return null
|
|
|
10184
10412
|
}
|
|
10185
10413
|
case OP_OPT: {
|
|
10186
10414
|
const child = link(code[ip + 1]);
|
|
10187
|
-
const clean = !
|
|
10415
|
+
const clean = !REC && failureRollbackClean(prog, ip);
|
|
10188
10416
|
const p = tmp();
|
|
10189
10417
|
return `${head}
|
|
10190
10418
|
${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
@@ -10214,15 +10442,15 @@ return v
|
|
|
10214
10442
|
const childIp = code[base + i];
|
|
10215
10443
|
kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
|
|
10216
10444
|
}
|
|
10217
|
-
const sy =
|
|
10445
|
+
const sy = REC ? `${tmp()}sy` : "";
|
|
10218
10446
|
const pub = (i) => {
|
|
10219
10447
|
const s = sentRef(code[base + n + i]);
|
|
10220
10448
|
return s === "undefined" ? `ctx._sync=${sy}` : `ctx._sync=${s}??${sy}`;
|
|
10221
10449
|
};
|
|
10222
10450
|
const parts = [head];
|
|
10223
|
-
if (
|
|
10451
|
+
if (REC) parts.push(`const ${sy}=ctx._sync`, "try{", pub(0));
|
|
10224
10452
|
parts.push(`const v0=${kids[0]}(input,pos,ctx)`, "if(v0===FAIL)return FAIL");
|
|
10225
|
-
const close = () =>
|
|
10453
|
+
const close = () => REC ? `${parts.join("\n")}
|
|
10226
10454
|
}finally{ctx._sync=${sy}}
|
|
10227
10455
|
}` : `${parts.join("\n")}
|
|
10228
10456
|
}`;
|
|
@@ -10235,7 +10463,7 @@ return v
|
|
|
10235
10463
|
for (let i = 1; i < n; i++) {
|
|
10236
10464
|
const vn = `v${i}`;
|
|
10237
10465
|
parts.push(`let ${vn}`);
|
|
10238
|
-
if (
|
|
10466
|
+
if (REC) parts.push(pub(i));
|
|
10239
10467
|
const childIp = code[base + i];
|
|
10240
10468
|
if (code[childIp] === OP_ADJ) {
|
|
10241
10469
|
const negated = code[childIp + 1] === 1;
|
|
@@ -10265,10 +10493,11 @@ return v
|
|
|
10265
10493
|
const asc = hoist("as", `DISP[${di}].ascii`);
|
|
10266
10494
|
const hiArr = table.hi;
|
|
10267
10495
|
const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
|
|
10496
|
+
const directAscii = staticBuild && table.hi.length === 0;
|
|
10268
10497
|
return `${head}
|
|
10269
|
-
const c
|
|
10498
|
+
const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10270
10499
|
let arm=-1
|
|
10271
|
-
if(c>=0&&c<128){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
10500
|
+
if(${directAscii ? "c<128" : "c>=0&&c<128"}){const a=${asc}[c];if(a!==0)arm=a-1}
|
|
10272
10501
|
${hiArr.length === 0 ? "" : `else if(c>=128){const h=${hoist("hi", `DISP[${di}].hi`)}
|
|
10273
10502
|
for(let i=0;i<h.length;i+=3){if(c>=h[i]&&c<=h[i+1]){arm=h[i+2];break}}}`}
|
|
10274
10503
|
if(arm>=0){
|
|
@@ -10290,7 +10519,9 @@ return FAIL
|
|
|
10290
10519
|
const di = code[ip + 1];
|
|
10291
10520
|
const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
|
|
10292
10521
|
const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
|
|
10293
|
-
const
|
|
10522
|
+
const maskable = n <= 32;
|
|
10523
|
+
const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
|
|
10524
|
+
const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
|
|
10294
10525
|
const tokenCandidate = tokenChoiceCandidates.get(ip);
|
|
10295
10526
|
const pretests = Array.from({ length: n }, (_, i) => {
|
|
10296
10527
|
if (tokenCandidate?.arm === i) {
|
|
@@ -10310,12 +10541,11 @@ return FAIL
|
|
|
10310
10541
|
const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
|
|
10311
10542
|
return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
|
|
10312
10543
|
});
|
|
10313
|
-
const maskable = n <= 32;
|
|
10314
10544
|
const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
|
|
10315
10545
|
if (maskable) maskPlan.push(~di);
|
|
10316
10546
|
const p = tmp();
|
|
10317
10547
|
const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
|
|
10318
|
-
const rollbackMask =
|
|
10548
|
+
const rollbackMask = REC ? -1 : encodedRollbackMask;
|
|
10319
10549
|
const hasRollback = rollbackMask !== 0;
|
|
10320
10550
|
const startFailureExact = arms.every((_arm, i) => {
|
|
10321
10551
|
const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
|
|
@@ -10372,16 +10602,16 @@ ${merge}
|
|
|
10372
10602
|
ctx._fe=pos;ctx._fx=acc??${choiceFx}
|
|
10373
10603
|
return FAIL`;
|
|
10374
10604
|
return `${head}
|
|
10375
|
-
const c
|
|
10605
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10376
10606
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
10377
10607
|
${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
|
|
10378
10608
|
${maskable ? `if(c<128){
|
|
10379
|
-
const bits=${maskName}[c<0?128:c]
|
|
10609
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
10380
10610
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10381
10611
|
${lazyArms(true)}
|
|
10382
|
-
}else{
|
|
10612
|
+
}${directAsciiMask ? "" : `else{
|
|
10383
10613
|
${lazyArms(false)}
|
|
10384
|
-
}
|
|
10614
|
+
}`}
|
|
10385
10615
|
` : lazyArms(false)}
|
|
10386
10616
|
${finish}
|
|
10387
10617
|
}`;
|
|
@@ -10432,7 +10662,7 @@ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0
|
|
|
10432
10662
|
${rollbackFor(i)}
|
|
10433
10663
|
}${routeMiss}${sequenceMiss}`;
|
|
10434
10664
|
}).join("\n") : "";
|
|
10435
|
-
const generalArms = arms.map((arm, i) => {
|
|
10665
|
+
const generalArms = directAsciiMask ? "" : arms.map((arm, i) => {
|
|
10436
10666
|
const pretest = pretests[i];
|
|
10437
10667
|
const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
|
|
10438
10668
|
const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
|
|
@@ -10462,12 +10692,12 @@ ${rollbackFor(i)}
|
|
|
10462
10692
|
}${miss}`;
|
|
10463
10693
|
}).join("\n");
|
|
10464
10694
|
return `${head}
|
|
10465
|
-
const c
|
|
10695
|
+
const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
|
|
10466
10696
|
${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
|
|
10467
10697
|
let acc
|
|
10468
10698
|
let best=pos
|
|
10469
10699
|
${maskable ? `if(c<128){
|
|
10470
|
-
const bits=${maskName}[c<0?128:c]
|
|
10700
|
+
const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
|
|
10471
10701
|
if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
|
|
10472
10702
|
${startFailureExact ? "" : "let prev=0"}
|
|
10473
10703
|
${maskArms}
|
|
@@ -10562,14 +10792,18 @@ return [key,v]
|
|
|
10562
10792
|
const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
|
|
10563
10793
|
const collect = op === OP_REP;
|
|
10564
10794
|
let itemCls;
|
|
10565
|
-
|
|
10795
|
+
let itemAscii = false;
|
|
10796
|
+
if (!REC) {
|
|
10566
10797
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
10567
10798
|
if (itemClassIndex >= 0) {
|
|
10568
|
-
const
|
|
10799
|
+
const resolved = t.cc[itemClassIndex];
|
|
10800
|
+
const ci = classes.push([resolved]) - 1;
|
|
10569
10801
|
classPlan.push([itemClassIndex]);
|
|
10570
10802
|
itemCls = hoist("ri", `CLS[${ci}][0]`);
|
|
10803
|
+
itemAscii = staticBuild && isAsciiOnlyClass(resolved);
|
|
10571
10804
|
}
|
|
10572
10805
|
}
|
|
10806
|
+
const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
|
|
10573
10807
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
10574
10808
|
const p = tmp();
|
|
10575
10809
|
const via = sep2 !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
|
|
@@ -10607,11 +10841,11 @@ ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
|
|
|
10607
10841
|
${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}
|
|
10608
10842
|
}`;
|
|
10609
10843
|
const my = `${p}my`;
|
|
10610
|
-
const recFx =
|
|
10611
|
-
const sepSent =
|
|
10844
|
+
const recFx = REC ? fxRef(code[ip + 6]) : "";
|
|
10845
|
+
const sepSent = REC ? sentRef(code[ip + 7]) : "undefined";
|
|
10612
10846
|
const recSent = sep2 === void 0 ? my : sepSent === "undefined" ? `orSentinel(${my},undefined)` : `orSentinel(${sepSent}??${my},${sepSent}===undefined?undefined:${my})`;
|
|
10613
10847
|
const recGate = sep2 !== void 0 || min === 0 ? "" : `count>=${min}&&`;
|
|
10614
|
-
const recBranch = !
|
|
10848
|
+
const recBranch = !REC ? "" : `if(ctx._tolerant===true&&${my}!==undefined&&${recGate}!matchesAt(${my},input,itemStart,ctx)){
|
|
10615
10849
|
${sep2 === void 0 ? `${rb}
|
|
10616
10850
|
` : ""}const rr=recoverScan(input,itemStart,ctx,${recSent},${recFx})
|
|
10617
10851
|
${collect ? "out.push(rr.error)\n" : ""}captureError(ctx,rr.error)
|
|
@@ -10622,14 +10856,14 @@ continue
|
|
|
10622
10856
|
`;
|
|
10623
10857
|
return `${head}
|
|
10624
10858
|
const out=${collect ? "[]" : "undefined"}
|
|
10625
|
-
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${
|
|
10859
|
+
${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC ? `const ${my}=ctx._sync
|
|
10626
10860
|
` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
|
|
10627
10861
|
`}let cur=pos
|
|
10628
10862
|
let count=0
|
|
10629
10863
|
for(;;){
|
|
10630
10864
|
${max >= 0 ? `if(count>=${max})break
|
|
10631
10865
|
` : ""}${sep2 !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
|
|
10632
|
-
` : ""}${itemCls !== void 0 && sep2 === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}
|
|
10866
|
+
` : ""}${itemCls !== void 0 && sep2 === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&${itemMiss("cur")})break
|
|
10633
10867
|
` : ""}let ${p}raw=0,${p}tl=0,${p}lv=0,${p}lg=0,${p}rt=0${sinks.fd ? `,${p}fd=0` : ""}${sinks.er ? `,${p}er=0` : ""}
|
|
10634
10868
|
${markBody}
|
|
10635
10869
|
let itemStart=cur
|
|
@@ -10654,14 +10888,14 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
|
|
|
10654
10888
|
${rb}
|
|
10655
10889
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
10656
10890
|
}
|
|
10657
|
-
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate
|
|
10891
|
+
${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
|
|
10658
10892
|
${rb}
|
|
10659
10893
|
${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
|
|
10660
10894
|
}
|
|
10661
10895
|
`}ctx._fc=false
|
|
10662
10896
|
const v=${child}(input,itemStart,ctx)
|
|
10663
10897
|
if(v===FAIL){
|
|
10664
|
-
${
|
|
10898
|
+
${REC ? `if(ctx._fc===true){
|
|
10665
10899
|
${rb}
|
|
10666
10900
|
return FAIL
|
|
10667
10901
|
}
|
|
@@ -11232,7 +11466,7 @@ function assemble(t, prog, cfg) {
|
|
|
11232
11466
|
const triviaScan = t.triviaScan;
|
|
11233
11467
|
const swapLegal = !cfg.trackLines;
|
|
11234
11468
|
const hostCst = cfg.hostCst;
|
|
11235
|
-
const
|
|
11469
|
+
const REC = prog.rec === 1 && cfg.tolerant;
|
|
11236
11470
|
const sentinels = /* @__PURE__ */ new Map();
|
|
11237
11471
|
function sentinelFor(cls) {
|
|
11238
11472
|
if (cls < 0) return void 0;
|
|
@@ -12233,7 +12467,7 @@ function assemble(t, prog, cfg) {
|
|
|
12233
12467
|
const child = link(code[ip + 1]);
|
|
12234
12468
|
const xf = fx[code[ip + 2]];
|
|
12235
12469
|
const expectSpan = (ctx, pos) => prog.lines === 1 ? spanLines(ctx, pos, pos) : { start: pos, end: pos };
|
|
12236
|
-
if (
|
|
12470
|
+
if (REC) {
|
|
12237
12471
|
return (input, pos, ctx) => {
|
|
12238
12472
|
const v = child(input, pos, ctx);
|
|
12239
12473
|
if (v !== FAIL) return v;
|
|
@@ -12540,8 +12774,8 @@ function assemble(t, prog, cfg) {
|
|
|
12540
12774
|
};
|
|
12541
12775
|
}
|
|
12542
12776
|
case OP_LEX_PROGRAM: {
|
|
12543
|
-
const
|
|
12544
|
-
const scanId =
|
|
12777
|
+
const run = t.lexPrograms[code[ip + 1]];
|
|
12778
|
+
const scanId = run.scan;
|
|
12545
12779
|
if (scanId !== void 0) {
|
|
12546
12780
|
return (input, pos, ctx) => {
|
|
12547
12781
|
const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
|
|
@@ -12562,7 +12796,7 @@ function assemble(t, prog, cfg) {
|
|
|
12562
12796
|
ctx._rootTriviaLog = void 0;
|
|
12563
12797
|
let end;
|
|
12564
12798
|
try {
|
|
12565
|
-
end =
|
|
12799
|
+
end = run(input, pos, ctx, scans[scanId]);
|
|
12566
12800
|
} finally {
|
|
12567
12801
|
SCAN = sScan;
|
|
12568
12802
|
ctx.trivia = sTrivia;
|
|
@@ -12583,7 +12817,7 @@ function assemble(t, prog, cfg) {
|
|
|
12583
12817
|
};
|
|
12584
12818
|
}
|
|
12585
12819
|
return (input, pos, ctx) => {
|
|
12586
|
-
const end =
|
|
12820
|
+
const end = run(input, pos, ctx);
|
|
12587
12821
|
if (end < 0) return FAIL;
|
|
12588
12822
|
const value = input.slice(pos, end);
|
|
12589
12823
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
|
|
@@ -12680,7 +12914,7 @@ function assemble(t, prog, cfg) {
|
|
|
12680
12914
|
return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
|
|
12681
12915
|
};
|
|
12682
12916
|
};
|
|
12683
|
-
if (
|
|
12917
|
+
if (REC) {
|
|
12684
12918
|
const first2 = link(code[base]);
|
|
12685
12919
|
const firstSync = sentinelFor(code[base + n]);
|
|
12686
12920
|
const runnerAt = (i) => {
|
|
@@ -13137,7 +13371,7 @@ function assemble(t, prog, cfg) {
|
|
|
13137
13371
|
if (n === 2 || n === 3) {
|
|
13138
13372
|
const a0 = link(code[base]), a1 = link(code[base + 1]);
|
|
13139
13373
|
const a2 = n === 3 ? link(code[base + 2]) : void 0;
|
|
13140
|
-
const predecide = !hostCst && !
|
|
13374
|
+
const predecide = !hostCst && !REC && !cfg.probe && !cfg.coverage && !cfg.trackLines;
|
|
13141
13375
|
const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
|
|
13142
13376
|
const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
|
|
13143
13377
|
const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
|
|
@@ -13528,10 +13762,10 @@ function assemble(t, prog, cfg) {
|
|
|
13528
13762
|
const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
|
|
13529
13763
|
const collect = op === OP_REP;
|
|
13530
13764
|
const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
|
|
13531
|
-
const itemClass = !
|
|
13765
|
+
const itemClass = !REC && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
|
|
13532
13766
|
const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
|
|
13533
13767
|
const skipBeforeFirst = sepIp < 0 && min === 0;
|
|
13534
|
-
if (
|
|
13768
|
+
if (REC) {
|
|
13535
13769
|
const itemFx2 = fx[code[ip + 6]];
|
|
13536
13770
|
const sepSent = sentinelFor(code[ip + 7]);
|
|
13537
13771
|
return (input, pos, ctx) => {
|
|
@@ -14038,7 +14272,7 @@ function assemble(t, prog, cfg) {
|
|
|
14038
14272
|
lead,
|
|
14039
14273
|
asciiFoldKey,
|
|
14040
14274
|
ROUTED_FX,
|
|
14041
|
-
|
|
14275
|
+
REC ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
14042
14276
|
matchesAt,
|
|
14043
14277
|
recoverScan,
|
|
14044
14278
|
orSentinel,
|
|
@@ -14120,7 +14354,7 @@ function assemble(t, prog, cfg) {
|
|
|
14120
14354
|
// — a strict one emits no reader — and through the SAME `sentinelFor` memo
|
|
14121
14355
|
// the closure pieces use, so both engines resync to the same combinator
|
|
14122
14356
|
// object rather than to two separately constructed ones.
|
|
14123
|
-
|
|
14357
|
+
REC ? prog.cc.map((_, i) => sentinelFor(i)) : EMPTY_SENTS,
|
|
14124
14358
|
matchesAt,
|
|
14125
14359
|
recoverScan,
|
|
14126
14360
|
orSentinel,
|
|
@@ -15153,36 +15387,36 @@ function findRegexFragments(visited) {
|
|
|
15153
15387
|
if (branches.length >= 2) runs.add(branches.join("|"));
|
|
15154
15388
|
for (let i = 0; i < branches.length; i++) {
|
|
15155
15389
|
for (let n = 2; n <= Math.min(MAX_RUN, branches.length - i); n++) {
|
|
15156
|
-
const
|
|
15157
|
-
if (
|
|
15158
|
-
runs.add(
|
|
15390
|
+
const run = branches.slice(i, i + n).join("|");
|
|
15391
|
+
if (run.length < 4) continue;
|
|
15392
|
+
runs.add(run);
|
|
15159
15393
|
}
|
|
15160
15394
|
}
|
|
15161
15395
|
}
|
|
15162
|
-
for (const
|
|
15163
|
-
let e = byRun.get(
|
|
15396
|
+
for (const run of runs) {
|
|
15397
|
+
let e = byRun.get(run);
|
|
15164
15398
|
if (e === void 0) {
|
|
15165
|
-
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches:
|
|
15166
|
-
byRun.set(
|
|
15399
|
+
e = { occ: [], nodes: /* @__PURE__ */ new Set(), branches: run.split("|").length };
|
|
15400
|
+
byRun.set(run, e);
|
|
15167
15401
|
}
|
|
15168
15402
|
if (e.nodes.has(v.p)) continue;
|
|
15169
15403
|
e.nodes.add(v.p);
|
|
15170
15404
|
e.occ.push({ site: v.site, source: d.source });
|
|
15171
15405
|
}
|
|
15172
15406
|
}
|
|
15173
|
-
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([
|
|
15407
|
+
const candidates = [...byRun.entries()].filter(([, e]) => e.occ.length >= 2).map(([run, e]) => ({ run, e, savings: (e.occ.length - 1) * run.length })).sort((a, b) => b.e.occ.length - a.e.occ.length || b.savings - a.savings || b.run.length - a.run.length);
|
|
15174
15408
|
const kept = [];
|
|
15175
15409
|
for (const c of candidates) {
|
|
15176
15410
|
if (kept.some((k) => k.e.occ.length >= c.e.occ.length && `|${k.run}|`.includes(`|${c.run}|`))) continue;
|
|
15177
15411
|
kept.push(c);
|
|
15178
15412
|
}
|
|
15179
|
-
return kept.map(({ run
|
|
15413
|
+
return kept.map(({ run, e }) => ({
|
|
15180
15414
|
kind: "regex-fragment",
|
|
15181
|
-
id: `regex-fragment:${
|
|
15182
|
-
fragment:
|
|
15415
|
+
id: `regex-fragment:${run}`,
|
|
15416
|
+
fragment: run,
|
|
15183
15417
|
branches: e.branches,
|
|
15184
15418
|
count: e.occ.length,
|
|
15185
|
-
savings: (e.occ.length - 1) *
|
|
15419
|
+
savings: (e.occ.length - 1) * run.length,
|
|
15186
15420
|
sources: e.occ.map((o) => `/${o.source}/`),
|
|
15187
15421
|
sites: e.occ.map((o) => o.site),
|
|
15188
15422
|
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.`
|
|
@@ -16692,7 +16926,7 @@ function compileRuleMap(ruleMap, opts = {}) {
|
|
|
16692
16926
|
}
|
|
16693
16927
|
|
|
16694
16928
|
// src/version.ts
|
|
16695
|
-
var PARSEMAN_VERSION = "0.50.
|
|
16929
|
+
var PARSEMAN_VERSION = "0.50.3";
|
|
16696
16930
|
|
|
16697
16931
|
// src/compiler/compile-linkable-table.ts
|
|
16698
16932
|
function isLocal(rule) {
|
|
@@ -16785,72 +17019,6 @@ function cstBuildHost(typeOrOptions, children3, _fields, span, rawChildren, triv
|
|
|
16785
17019
|
cstBuildHost._parsemanCstOutput = true;
|
|
16786
17020
|
var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
|
|
16787
17021
|
|
|
16788
|
-
// src/cst/trivia-entries.ts
|
|
16789
|
-
var EMPTY_INDICES = Object.freeze([]);
|
|
16790
|
-
var EMPTY_GAPS = Object.freeze([]);
|
|
16791
|
-
|
|
16792
|
-
// src/functional/run.ts
|
|
16793
|
-
var SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })";
|
|
16794
|
-
var REMOVED_RUN_RESULT_FIELDS = [
|
|
16795
|
-
[
|
|
16796
|
-
"triviaMap",
|
|
16797
|
-
`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.`
|
|
16798
|
-
],
|
|
16799
|
-
[
|
|
16800
|
-
"triviaLog",
|
|
16801
|
-
`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.`
|
|
16802
|
-
],
|
|
16803
|
-
[
|
|
16804
|
-
"triviaKindLabels",
|
|
16805
|
-
`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\`.`
|
|
16806
|
-
]
|
|
16807
|
-
];
|
|
16808
|
-
var RunResultRecord = class {
|
|
16809
|
-
constructor(ok, value, span, expected, errors, unconsumedFrom) {
|
|
16810
|
-
this.ok = ok;
|
|
16811
|
-
this.value = value;
|
|
16812
|
-
this.span = span;
|
|
16813
|
-
this.expected = expected;
|
|
16814
|
-
this.errors = errors;
|
|
16815
|
-
this.unconsumedFrom = unconsumedFrom;
|
|
16816
|
-
}
|
|
16817
|
-
};
|
|
16818
|
-
var RunResultWithRootTrivia = class {
|
|
16819
|
-
constructor(ok, value, span, expected, errors, rootTrivia, unconsumedFrom) {
|
|
16820
|
-
this.ok = ok;
|
|
16821
|
-
this.value = value;
|
|
16822
|
-
this.span = span;
|
|
16823
|
-
this.expected = expected;
|
|
16824
|
-
this.errors = errors;
|
|
16825
|
-
this.rootTrivia = rootTrivia;
|
|
16826
|
-
this.unconsumedFrom = unconsumedFrom;
|
|
16827
|
-
}
|
|
16828
|
-
};
|
|
16829
|
-
for (const proto of [RunResultRecord.prototype, RunResultWithRootTrivia.prototype]) {
|
|
16830
|
-
for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
|
|
16831
|
-
Object.defineProperty(proto, name, {
|
|
16832
|
-
configurable: true,
|
|
16833
|
-
enumerable: false,
|
|
16834
|
-
get() {
|
|
16835
|
-
throw new TypeError(
|
|
16836
|
-
`RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`
|
|
16837
|
-
);
|
|
16838
|
-
}
|
|
16839
|
-
});
|
|
16840
|
-
}
|
|
16841
|
-
}
|
|
16842
|
-
|
|
16843
|
-
// src/analysis/choice-cost-render.ts
|
|
16844
|
-
var ESC = "\x1B";
|
|
16845
|
-
var ANSI = {
|
|
16846
|
-
dim: `${ESC}[2m`,
|
|
16847
|
-
bold: `${ESC}[1m`,
|
|
16848
|
-
red: `${ESC}[31m`,
|
|
16849
|
-
yellow: `${ESC}[33m`,
|
|
16850
|
-
cyan: `${ESC}[36m`,
|
|
16851
|
-
reset: `${ESC}[0m`
|
|
16852
|
-
};
|
|
16853
|
-
|
|
16854
17022
|
// src/combinators/gate.ts
|
|
16855
17023
|
function gate(predicate) {
|
|
16856
17024
|
const meta = {
|