parseman 0.55.3 → 0.56.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/analysis/choice-cost.d.ts.map +1 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +3360 -3098
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/duplication.d.ts.map +1 -1
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/cli/index.js +1820 -1558
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts.map +1 -1
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/first-set.d.ts.map +1 -1
- package/dist/combinators/lines.d.ts +79 -0
- package/dist/combinators/lines.d.ts.map +1 -0
- package/dist/combinators/trivia-skip.d.ts +1 -0
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +25 -0
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1912 -1628
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +2 -0
- package/dist/language-service/index.js.map +1 -1
- package/dist/parse-context.d.ts.map +1 -1
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +1325 -1048
- package/dist/plugin/index.js.map +3 -3
- package/dist/plugin/ir-eval.d.ts +0 -4
- package/dist/plugin/ir-eval.d.ts.map +1 -1
- package/dist/run/index.js +2 -0
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +15 -0
- package/dist/spec/index.js.map +1 -1
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/table/assemble.d.ts +0 -65
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/emit.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +3449 -3195
- package/dist/table/index.js.map +3 -3
- package/dist/table/line-scan.d.ts +9 -0
- package/dist/table/line-scan.d.ts.map +1 -0
- package/dist/table/program.d.ts +11 -2
- package/dist/table/program.d.ts.map +1 -1
- package/dist/types.d.ts +26 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/choice-cost.ts +1 -0
- package/src/analysis/commitment.ts +13 -0
- package/src/analysis/duplication.ts +3 -0
- package/src/analysis/gating.ts +5 -0
- package/src/analysis/rebuild.ts +2 -2
- package/src/combinators/attempt.ts +2 -0
- package/src/combinators/choice.ts +3 -0
- package/src/combinators/dispatch.ts +3 -0
- package/src/combinators/expect.ts +5 -0
- package/src/combinators/first-set.ts +9 -1
- package/src/combinators/lines.ts +244 -0
- package/src/combinators/trivia-skip.ts +4 -2
- package/src/compiler/fields.ts +3 -0
- package/src/compiler/grammar-coverage-ids.ts +1 -0
- package/src/compiler/ir-serialize.ts +10 -0
- package/src/compiler/token-alphabet.ts +3 -1
- package/src/coverage.ts +6 -0
- package/src/cst/reflection.ts +3 -0
- package/src/index.ts +2 -0
- package/src/parse-context.ts +2 -0
- package/src/plugin/evaluator.ts +4 -0
- package/src/plugin/ir-eval.ts +3 -0
- package/src/spec/model.ts +15 -0
- package/src/table/assemble.ts +10 -13
- package/src/table/compile.ts +5 -2
- package/src/table/emit.ts +7 -6
- package/src/table/encode.ts +18 -6
- package/src/table/exec.ts +7 -1
- package/src/table/line-scan.ts +19 -0
- package/src/table/program.ts +17 -2
- package/src/types.ts +19 -1
- package/src/version.ts +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -163,6 +163,11 @@ function matchesEmptyBody(p, seen, resolve2) {
|
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
// A run consumes at least its first line's prefix, and its body after that.
|
|
167
|
+
case "lines":
|
|
168
|
+
return me(d.first ?? d.prefix) && me(d.body);
|
|
169
|
+
case "columns":
|
|
170
|
+
return d.n === 0;
|
|
166
171
|
default:
|
|
167
172
|
return true;
|
|
168
173
|
}
|
|
@@ -277,6 +282,11 @@ function firstSetBody(p, seen, resolve2, activeTrivia) {
|
|
|
277
282
|
resolve2,
|
|
278
283
|
d.clearTrivia ? null : d.triviaParser ?? activeTrivia
|
|
279
284
|
);
|
|
285
|
+
// A run starts with its first line's prefix; a nullable prefix starts with anything.
|
|
286
|
+
case "lines": {
|
|
287
|
+
const opening = d.first ?? d.prefix;
|
|
288
|
+
return empties(opening) ? any() : fs(opening);
|
|
289
|
+
}
|
|
280
290
|
default:
|
|
281
291
|
return p._meta.firstSet;
|
|
282
292
|
}
|
|
@@ -326,6 +336,10 @@ function childrenOf(d) {
|
|
|
326
336
|
return d.triviaParser ? [d.parser, d.triviaParser] : [d.parser];
|
|
327
337
|
case "routed":
|
|
328
338
|
return d.fallback ? [d.fallback] : [];
|
|
339
|
+
case "lines":
|
|
340
|
+
return [d.prefix, d.body, ...d.first === void 0 ? [] : [d.first], ...d.lazy === void 0 ? [] : [d.lazy]];
|
|
341
|
+
case "columns":
|
|
342
|
+
return [];
|
|
329
343
|
// A `lazy` is a REFERENCE, not a subtree. Descending through it would make
|
|
330
344
|
// every rule's walk cover the whole reachable grammar — site paths become
|
|
331
345
|
// nonsense, and a structural hash includes half the grammar. Treated as a
|
|
@@ -417,6 +431,9 @@ function classifyBroadArm(arm, resolve2) {
|
|
|
417
431
|
return walk(d.parser);
|
|
418
432
|
case "scanTo":
|
|
419
433
|
return { cause: "broad-recognizer", detail: "scanTo (any first char)" };
|
|
434
|
+
// A run opens with its first line's prefix.
|
|
435
|
+
case "lines":
|
|
436
|
+
return walk(d.first ?? d.prefix);
|
|
420
437
|
// `guard` (the `gate()` state predicate) has a genuinely-`any` first-set of
|
|
421
438
|
// its own — it is the poison. `withCtx`/`recover` FORWARD their inner
|
|
422
439
|
// first-set (see firstSetOf), so a broad result comes from the inner parser:
|
|
@@ -1052,6 +1069,8 @@ function createParseContext() {
|
|
|
1052
1069
|
_triviaCaptureMask: void 0,
|
|
1053
1070
|
trackLines: false,
|
|
1054
1071
|
state: void 0,
|
|
1072
|
+
lineView: void 0,
|
|
1073
|
+
_columnsSplit: void 0,
|
|
1055
1074
|
build: void 0,
|
|
1056
1075
|
_errors: void 0,
|
|
1057
1076
|
_tolerant: void 0,
|
|
@@ -1773,11 +1792,12 @@ function parseTriviaNoCapture(triviaP, input, cur, ctx) {
|
|
|
1773
1792
|
return result;
|
|
1774
1793
|
}
|
|
1775
1794
|
function saveLookaheadMark(ctx) {
|
|
1776
|
-
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
|
|
1795
|
+
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null, split: ctx._columnsSplit };
|
|
1777
1796
|
}
|
|
1778
1797
|
function rollbackLookahead(ctx, mark) {
|
|
1779
1798
|
rollbackTrivia(ctx, mark);
|
|
1780
1799
|
if (ctx._probe) ctx._probe.best = mark.probeBest;
|
|
1800
|
+
ctx._columnsSplit = mark.split;
|
|
1781
1801
|
}
|
|
1782
1802
|
function scanWithLabels(input, cur, ctx) {
|
|
1783
1803
|
const triviaP = ctx.trivia;
|
|
@@ -2295,6 +2315,9 @@ function parserUsesRouted(parser2, seen = /* @__PURE__ */ new Set()) {
|
|
|
2295
2315
|
return parserUsesRouted(def.sentinel, seen) || def.skip.some((entry) => parserUsesRouted(entry, seen)) || def.recoverAt !== void 0 && parserUsesRouted(def.recoverAt, seen) || def.stopAt !== void 0 && parserUsesRouted(def.stopAt, seen);
|
|
2296
2316
|
case "recover":
|
|
2297
2317
|
return parserUsesRouted(def.parser, seen) || parserUsesRouted(def.sentinel, seen);
|
|
2318
|
+
// The body parses its own input, so only the checks on this one can reuse a routed head.
|
|
2319
|
+
case "lines":
|
|
2320
|
+
return [def.prefix, def.first, def.lazy].some((entry) => entry !== void 0 && parserUsesRouted(entry, seen));
|
|
2298
2321
|
case "lazy":
|
|
2299
2322
|
try {
|
|
2300
2323
|
return parserUsesRouted(def.thunk(), seen);
|
|
@@ -2485,6 +2508,12 @@ function derive(c, seen) {
|
|
|
2485
2508
|
return deriveExpected2(def.parser);
|
|
2486
2509
|
case "expect":
|
|
2487
2510
|
return def.expected;
|
|
2511
|
+
case "lines": {
|
|
2512
|
+
const opening = def.first ?? def.prefix;
|
|
2513
|
+
return matchesEmpty(opening) ? [...deriveExpected2(opening), ...deriveExpected2(def.body)] : deriveExpected2(opening);
|
|
2514
|
+
}
|
|
2515
|
+
case "columns":
|
|
2516
|
+
return [`columns(${def.n})`];
|
|
2488
2517
|
case "node":
|
|
2489
2518
|
case "grammar":
|
|
2490
2519
|
case "trivia":
|
|
@@ -3087,6 +3116,9 @@ function childrenOf2(def) {
|
|
|
3087
3116
|
];
|
|
3088
3117
|
case "routed":
|
|
3089
3118
|
return def.fallback ? [def.fallback] : [];
|
|
3119
|
+
case "lines":
|
|
3120
|
+
return [def.prefix, def.body, ...def.first === void 0 ? [] : [def.first], ...def.lazy === void 0 ? [] : [def.lazy]];
|
|
3121
|
+
case "columns":
|
|
3090
3122
|
case "literal":
|
|
3091
3123
|
case "regex":
|
|
3092
3124
|
case "keywords":
|
|
@@ -3479,7 +3511,11 @@ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActiv
|
|
|
3479
3511
|
case "leaf":
|
|
3480
3512
|
case "scanTo":
|
|
3481
3513
|
case "unknown":
|
|
3514
|
+
case "columns":
|
|
3482
3515
|
return false;
|
|
3516
|
+
// A run's prefixes are probed detached; only its body can capture.
|
|
3517
|
+
case "lines":
|
|
3518
|
+
return mayLeavePartialCapture(d.body, seen, triviaActive);
|
|
3483
3519
|
// node() captures into its own private buffers and rolls them back on
|
|
3484
3520
|
// failure (emitNode restores _ctx.* and never pushes on the !ok path).
|
|
3485
3521
|
case "node":
|
|
@@ -3599,6 +3635,10 @@ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3599
3635
|
return capturesLeaf(d.parser, seen);
|
|
3600
3636
|
case "scanTo":
|
|
3601
3637
|
return true;
|
|
3638
|
+
case "lines":
|
|
3639
|
+
return capturesLeaf(d.body, seen);
|
|
3640
|
+
case "columns":
|
|
3641
|
+
return true;
|
|
3602
3642
|
case "lazy": {
|
|
3603
3643
|
try {
|
|
3604
3644
|
return capturesLeaf(d.thunk(), seen);
|
|
@@ -3646,6 +3686,8 @@ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3646
3686
|
return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
|
|
3647
3687
|
case "scanTo":
|
|
3648
3688
|
return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen)) || d.recoverAt !== void 0 && hasNodeDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasNodeDef(d.stopAt, seen);
|
|
3689
|
+
case "lines":
|
|
3690
|
+
return hasNodeDef(d.body, seen);
|
|
3649
3691
|
case "recover":
|
|
3650
3692
|
return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
|
|
3651
3693
|
case "expect":
|
|
@@ -3695,6 +3737,8 @@ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
3695
3737
|
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
|
|
3696
3738
|
case "scanTo":
|
|
3697
3739
|
return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen)) || d.recoverAt !== void 0 && hasDirectBuildDef(d.recoverAt, seen) || d.stopAt !== void 0 && hasDirectBuildDef(d.stopAt, seen);
|
|
3740
|
+
case "lines":
|
|
3741
|
+
return hasDirectBuildDef(d.body, seen);
|
|
3698
3742
|
case "recover":
|
|
3699
3743
|
return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
|
|
3700
3744
|
case "routed":
|
|
@@ -3740,6 +3784,9 @@ function commitFailureSuccessors(p, resolve2) {
|
|
|
3740
3784
|
...d.recoverAt === void 0 ? NO_EDGES : [d.recoverAt],
|
|
3741
3785
|
...d.stopAt === void 0 ? NO_EDGES : [d.stopAt]
|
|
3742
3786
|
];
|
|
3787
|
+
// A run's prefixes are probed detached; a committed failure reaches it only from its body.
|
|
3788
|
+
case "lines":
|
|
3789
|
+
return [d.body];
|
|
3743
3790
|
case "lazy": {
|
|
3744
3791
|
try {
|
|
3745
3792
|
return [d.thunk()];
|
|
@@ -3945,9 +3992,11 @@ function choice(...args) {
|
|
|
3945
3992
|
for (let i = 0; i < parsers.length; i++) {
|
|
3946
3993
|
if (gates[i] && !gates[i](ctx.state)) continue;
|
|
3947
3994
|
const mark = saveTriviaMark(ctx);
|
|
3995
|
+
const split = ctx._columnsSplit;
|
|
3948
3996
|
const result = parsers[i].parse(input, pos, ctx);
|
|
3949
3997
|
if (!result.ok) {
|
|
3950
3998
|
rollbackTrivia(ctx, mark);
|
|
3999
|
+
ctx._columnsSplit = split;
|
|
3951
4000
|
const at = result.span.start;
|
|
3952
4001
|
if (at > expectedAt) {
|
|
3953
4002
|
expectedAt = at;
|
|
@@ -4147,665 +4196,671 @@ function buildAsciiDispatch(parsers) {
|
|
|
4147
4196
|
return table;
|
|
4148
4197
|
}
|
|
4149
4198
|
|
|
4150
|
-
// src/
|
|
4151
|
-
|
|
4152
|
-
|
|
4199
|
+
// src/combinators/field-trivia.ts
|
|
4200
|
+
var LEAD = { at: -1 };
|
|
4201
|
+
var FIELD_LEADING_TRIVIA = 1;
|
|
4202
|
+
var FIELD_TRAILING_TRIVIA = 2;
|
|
4203
|
+
function triviaFieldCapture(name, value, input, start, end, leadFrom, trailEnd) {
|
|
4204
|
+
return {
|
|
4205
|
+
name,
|
|
4206
|
+
value,
|
|
4207
|
+
span: { start, end },
|
|
4208
|
+
leading: leadFrom >= 0 && leadFrom < start ? input.slice(leadFrom, start) : "",
|
|
4209
|
+
trailing: trailEnd > end ? input.slice(end, trailEnd) : ""
|
|
4210
|
+
};
|
|
4153
4211
|
}
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
`[parseman] degraded [${code}] +${items.length - DETAIL_CAP} more site(s) not listed (${items.length} total). Set PARSEMAN_DEGRADATION=error to fail the build on these.`
|
|
4168
|
-
);
|
|
4212
|
+
function leadsTrivia(p) {
|
|
4213
|
+
return p._def.tag === "field" && p._def.leadingTrivia === true;
|
|
4214
|
+
}
|
|
4215
|
+
|
|
4216
|
+
// src/combinators/repeat.ts
|
|
4217
|
+
function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
|
|
4218
|
+
const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
|
|
4219
|
+
let pos = cur;
|
|
4220
|
+
if (ctx.trivia) {
|
|
4221
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
4222
|
+
pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
4223
|
+
} else {
|
|
4224
|
+
pos = advanceTrivia(input, cur, ctx);
|
|
4169
4225
|
}
|
|
4170
4226
|
}
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
function beginDegradationCapture() {
|
|
4175
|
-
_sinks.push(/* @__PURE__ */ new Map());
|
|
4176
|
-
}
|
|
4177
|
-
function degradationCaptureDepth() {
|
|
4178
|
-
return _sinks.length;
|
|
4179
|
-
}
|
|
4180
|
-
function unwindDegradationCapture(depth) {
|
|
4181
|
-
const found = [];
|
|
4182
|
-
while (_sinks.length > depth) {
|
|
4183
|
-
const sink = _sinks.pop();
|
|
4184
|
-
found.unshift(...sink.values());
|
|
4227
|
+
if (pos >= input.length && !mandatory) {
|
|
4228
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4229
|
+
return "stop";
|
|
4185
4230
|
}
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
const
|
|
4191
|
-
if (
|
|
4192
|
-
|
|
4231
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
4232
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4233
|
+
return "stop";
|
|
4234
|
+
}
|
|
4235
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4236
|
+
if (!result.ok) {
|
|
4237
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4238
|
+
if (result.committed) return { fail: result, failPos: pos };
|
|
4239
|
+
return { fail: result, failPos: pos };
|
|
4240
|
+
}
|
|
4241
|
+
if (result.span.end === pos && !mandatory) {
|
|
4242
|
+
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
4243
|
+
return "stop";
|
|
4244
|
+
}
|
|
4245
|
+
return result;
|
|
4193
4246
|
}
|
|
4194
|
-
function
|
|
4195
|
-
|
|
4247
|
+
function resolveBounds(what, opts) {
|
|
4248
|
+
const min = opts.min ?? 0;
|
|
4249
|
+
const max = opts.max ?? Infinity;
|
|
4250
|
+
const bad = (msg) => {
|
|
4251
|
+
throw new RangeError(`parseman: ${what} ${msg}`);
|
|
4252
|
+
};
|
|
4253
|
+
if (!Number.isInteger(min) || min < 0) bad(`min must be a non-negative integer (got ${String(opts.min)})`);
|
|
4254
|
+
if (max !== Infinity && (!Number.isInteger(max) || max < 1)) bad(`max must be a positive integer (got ${String(opts.max)})`);
|
|
4255
|
+
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
4256
|
+
return { min, max };
|
|
4196
4257
|
}
|
|
4197
|
-
function
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4258
|
+
function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
|
|
4259
|
+
while (cur < input.length && remaining > 0) {
|
|
4260
|
+
let itemPos = cur;
|
|
4261
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4262
|
+
if (itemPos >= input.length) break;
|
|
4263
|
+
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
4264
|
+
const end = child(input, itemPos, ctx);
|
|
4265
|
+
if (end <= itemPos) break;
|
|
4266
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4267
|
+
cur = end;
|
|
4268
|
+
remaining--;
|
|
4205
4269
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
4209
|
-
${formatDegradation(d)}`);
|
|
4210
|
-
console.warn(formatDegradation(d));
|
|
4270
|
+
ctx._sv = values;
|
|
4271
|
+
return cur;
|
|
4211
4272
|
}
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
if (
|
|
4273
|
+
function many(combinator, opts = {}) {
|
|
4274
|
+
const { min, max } = resolveBounds("many()", opts);
|
|
4275
|
+
if (min >= 1) return atLeast(combinator, min, max);
|
|
4276
|
+
const meta = {
|
|
4277
|
+
firstSet: combinator._meta.firstSet,
|
|
4278
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4279
|
+
isTrivia: false
|
|
4215
4280
|
};
|
|
4216
|
-
const
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4281
|
+
const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
|
|
4282
|
+
let expected;
|
|
4283
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4284
|
+
const scalarChild = scalarOf(combinator);
|
|
4285
|
+
const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
|
|
4286
|
+
return {
|
|
4287
|
+
_tag: "many",
|
|
4288
|
+
_meta: meta,
|
|
4289
|
+
_def: def,
|
|
4290
|
+
_parseScalar: parseScalar,
|
|
4291
|
+
parse(input, pos, ctx) {
|
|
4292
|
+
const values = def.valueUnused ? void 0 : [];
|
|
4293
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4294
|
+
let cur = pos;
|
|
4295
|
+
let count = 0;
|
|
4296
|
+
while (cur < input.length) {
|
|
4297
|
+
if (count >= max) break;
|
|
4298
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4299
|
+
if (item === "stop") break;
|
|
4300
|
+
if ("fail" in item) {
|
|
4301
|
+
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
4302
|
+
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
4303
|
+
if (sync === void 0) break;
|
|
4304
|
+
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
4305
|
+
expected ??= deriveExpected(combinator);
|
|
4306
|
+
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
4307
|
+
if (values !== void 0) values.push(error);
|
|
4308
|
+
captureError(ctx, error);
|
|
4309
|
+
count++;
|
|
4310
|
+
cur = end;
|
|
4311
|
+
continue;
|
|
4312
|
+
}
|
|
4313
|
+
if (values !== void 0) values.push(item.value);
|
|
4314
|
+
count++;
|
|
4315
|
+
cur = item.span.end;
|
|
4316
|
+
}
|
|
4317
|
+
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4232
4318
|
}
|
|
4233
|
-
for (const l of lines) console.warn(l);
|
|
4234
4319
|
};
|
|
4235
4320
|
}
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
function cstOutputHost(build) {
|
|
4239
|
-
return build?._parsemanCstOutput === true;
|
|
4240
|
-
}
|
|
4241
|
-
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
4242
|
-
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
4243
|
-
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
4244
|
-
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
4245
|
-
function confirmedBuildArity(src) {
|
|
4246
|
-
const s = src.trim();
|
|
4247
|
-
if (NATIVE_CODE_RE.test(s)) return null;
|
|
4248
|
-
if (/\barguments\b/.test(s)) return null;
|
|
4249
|
-
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
4250
|
-
const inner = paramListText(s);
|
|
4251
|
-
if (inner === null) return null;
|
|
4252
|
-
if (inner.trim() === "") return 0;
|
|
4253
|
-
const parts = splitTopLevel(inner);
|
|
4254
|
-
if (parts === null) return null;
|
|
4255
|
-
for (const part of parts) {
|
|
4256
|
-
if (!isConfirmableParam(part.trim())) return null;
|
|
4257
|
-
}
|
|
4258
|
-
return parts.length;
|
|
4259
|
-
}
|
|
4260
|
-
function paramListText(s) {
|
|
4261
|
-
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
4262
|
-
if (!open) return null;
|
|
4263
|
-
const start = open[0].length;
|
|
4264
|
-
const end = matchingParen(s, start);
|
|
4265
|
-
if (end === null) return null;
|
|
4266
|
-
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
4267
|
-
return s.slice(start, end);
|
|
4321
|
+
function oneOrMore(combinator, opts = {}) {
|
|
4322
|
+
return many(combinator, { ...opts, min: opts.min ?? 1 });
|
|
4268
4323
|
}
|
|
4269
|
-
function
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4324
|
+
function atLeast(combinator, min, max) {
|
|
4325
|
+
const meta = {
|
|
4326
|
+
firstSet: combinator._meta.firstSet,
|
|
4327
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4328
|
+
isTrivia: false
|
|
4329
|
+
};
|
|
4330
|
+
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
4331
|
+
let expected;
|
|
4332
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
4333
|
+
const scalarChild = scalarOf(combinator);
|
|
4334
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4335
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4336
|
+
if (cur < 0) return cur;
|
|
4337
|
+
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
4338
|
+
for (let count = 1; count < min; count++) {
|
|
4339
|
+
let itemPos = cur;
|
|
4340
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
4341
|
+
const end = scalarChild(input, itemPos, ctx);
|
|
4342
|
+
if (end < 0) return ~cur;
|
|
4343
|
+
cur = end;
|
|
4344
|
+
if (values !== void 0) values.push(ctx._sv);
|
|
4285
4345
|
}
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4346
|
+
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
4347
|
+
};
|
|
4348
|
+
return {
|
|
4349
|
+
_tag: "oneOrMore",
|
|
4350
|
+
_meta: meta,
|
|
4351
|
+
_def: def,
|
|
4352
|
+
_parseScalar: parseScalar,
|
|
4353
|
+
parse(input, pos, ctx) {
|
|
4354
|
+
const first = combinator.parse(input, pos, ctx);
|
|
4355
|
+
if (!first.ok) return first;
|
|
4356
|
+
const values = def.valueUnused ? void 0 : [first.value];
|
|
4357
|
+
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
4358
|
+
let cur = first.span.end;
|
|
4359
|
+
let count = 1;
|
|
4360
|
+
while (count < min) {
|
|
4361
|
+
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
4362
|
+
if (item === "stop" || "fail" in item) {
|
|
4363
|
+
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
4364
|
+
expected ??= deriveExpected(combinator);
|
|
4365
|
+
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
4366
|
+
}
|
|
4367
|
+
if (values !== void 0) values.push(item.value);
|
|
4368
|
+
cur = item.span.end;
|
|
4369
|
+
count++;
|
|
4370
|
+
}
|
|
4371
|
+
while (cur < input.length) {
|
|
4372
|
+
if (count >= max) break;
|
|
4373
|
+
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
4374
|
+
if (item === "stop") break;
|
|
4375
|
+
if ("fail" in item) {
|
|
4376
|
+
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
4377
|
+
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
4378
|
+
if (sync === void 0) break;
|
|
4379
|
+
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
4380
|
+
expected ??= deriveExpected(combinator);
|
|
4381
|
+
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
4382
|
+
if (values !== void 0) values.push(error);
|
|
4383
|
+
captureError(ctx, error);
|
|
4384
|
+
count++;
|
|
4385
|
+
cur = end;
|
|
4386
|
+
continue;
|
|
4387
|
+
}
|
|
4388
|
+
if (values !== void 0) values.push(item.value);
|
|
4389
|
+
count++;
|
|
4390
|
+
cur = item.span.end;
|
|
4391
|
+
}
|
|
4392
|
+
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
4295
4393
|
}
|
|
4296
|
-
|
|
4297
|
-
}
|
|
4298
|
-
return null;
|
|
4394
|
+
};
|
|
4299
4395
|
}
|
|
4300
|
-
function
|
|
4301
|
-
const
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
const close = skipString(inner, i);
|
|
4313
|
-
if (close === null) return null;
|
|
4314
|
-
i = close;
|
|
4315
|
-
continue;
|
|
4316
|
-
}
|
|
4317
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
4318
|
-
else if (c === ")" || c === "]" || c === "}") {
|
|
4319
|
-
if (--depth < 0) return null;
|
|
4320
|
-
} else if (c === "<") angle++;
|
|
4321
|
-
else if (c === ">") {
|
|
4322
|
-
if (--angle < 0) return null;
|
|
4323
|
-
} else if (c === "," && depth === 0 && angle === 0) {
|
|
4324
|
-
parts.push(inner.slice(last, i));
|
|
4325
|
-
last = i + 1;
|
|
4396
|
+
function optional(combinator) {
|
|
4397
|
+
const meta = {
|
|
4398
|
+
firstSet: combinator._meta.firstSet,
|
|
4399
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4400
|
+
isTrivia: false
|
|
4401
|
+
};
|
|
4402
|
+
const firstSetSkippable = !matchesEmpty(combinator);
|
|
4403
|
+
const scalarChild = scalarOf(combinator);
|
|
4404
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4405
|
+
if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
|
|
4406
|
+
ctx._sv = null;
|
|
4407
|
+
return pos;
|
|
4326
4408
|
}
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
}
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
}
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4409
|
+
const end = scalarChild(input, pos, ctx);
|
|
4410
|
+
if (end >= 0) return end;
|
|
4411
|
+
ctx._sv = null;
|
|
4412
|
+
return pos;
|
|
4413
|
+
};
|
|
4414
|
+
return {
|
|
4415
|
+
_tag: "optional",
|
|
4416
|
+
_meta: meta,
|
|
4417
|
+
_def: { tag: "optional", parser: combinator },
|
|
4418
|
+
_parseScalar: parseScalar,
|
|
4419
|
+
parse(input, pos, ctx) {
|
|
4420
|
+
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
4421
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4422
|
+
}
|
|
4423
|
+
const mark = saveTriviaMark(ctx);
|
|
4424
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4425
|
+
if (result.ok) return result;
|
|
4426
|
+
rollbackTrivia(ctx, mark);
|
|
4427
|
+
if (result.committed) return result;
|
|
4428
|
+
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
4346
4429
|
}
|
|
4347
|
-
|
|
4348
|
-
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
4349
|
-
return true;
|
|
4350
|
-
}
|
|
4351
|
-
return false;
|
|
4352
|
-
}
|
|
4353
|
-
function buildAnalysisSrc(def) {
|
|
4354
|
-
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
4355
|
-
}
|
|
4356
|
-
var RESOLVER_REASONS = {
|
|
4357
|
-
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
4358
|
-
"arguments": "its body references `arguments`",
|
|
4359
|
-
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
4360
|
-
"not-a-function": "the binding it names is not a function declaration",
|
|
4361
|
-
"unresolved-import": "its module could not be resolved or parsed",
|
|
4362
|
-
"not-found": "the name did not resolve to any binding",
|
|
4363
|
-
"computed": "it is a computed expression",
|
|
4364
|
-
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
4365
|
-
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
4366
|
-
};
|
|
4367
|
-
function unconfirmableReason(def, src) {
|
|
4368
|
-
const declared = def.buildArityUnresolved;
|
|
4369
|
-
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
4370
|
-
const s = src.trim();
|
|
4371
|
-
const params = s.slice(0, s.indexOf(")") + 1);
|
|
4372
|
-
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
4373
|
-
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
4374
|
-
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
4375
|
-
return "it names a binding this build could not resolve to a function declaration";
|
|
4376
|
-
}
|
|
4377
|
-
return "its parameter list could not be parsed";
|
|
4378
|
-
}
|
|
4379
|
-
function confirmedArityForDef(def) {
|
|
4380
|
-
if (def.buildArity !== void 0) return def.buildArity;
|
|
4381
|
-
const src = buildAnalysisSrc(def);
|
|
4382
|
-
const arity = confirmedBuildArity(src);
|
|
4383
|
-
if (arity !== null) return arity;
|
|
4384
|
-
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
4385
|
-
recordDegradation({
|
|
4386
|
-
code: "build-arity-unconfirmed",
|
|
4387
|
-
severity: "warn",
|
|
4388
|
-
where: `node("${def.type ?? "<inferred>"}")`,
|
|
4389
|
-
subject,
|
|
4390
|
-
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
|
|
4391
|
-
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
4392
|
-
});
|
|
4393
|
-
return null;
|
|
4394
|
-
}
|
|
4395
|
-
function buildReadsRaw(def) {
|
|
4396
|
-
if (!def.build) return true;
|
|
4397
|
-
if (def.buildRawUnused === true) return false;
|
|
4398
|
-
const arity = confirmedArityForDef(def);
|
|
4399
|
-
if (arity === null) return true;
|
|
4400
|
-
return arity >= 4;
|
|
4401
|
-
}
|
|
4402
|
-
function buildReadsTrivia(def) {
|
|
4403
|
-
if (!def.build) return true;
|
|
4404
|
-
const arity = confirmedArityForDef(def);
|
|
4405
|
-
if (arity === null) return true;
|
|
4406
|
-
return arity >= 5;
|
|
4407
|
-
}
|
|
4408
|
-
function buildReadsState(def) {
|
|
4409
|
-
if (!def.build) return true;
|
|
4410
|
-
const arity = confirmedArityForDef(def);
|
|
4411
|
-
if (arity === null) return true;
|
|
4412
|
-
return arity >= 6;
|
|
4430
|
+
};
|
|
4413
4431
|
}
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
function buildReadsFields(def) {
|
|
4417
|
-
if (!def.build) return true;
|
|
4418
|
-
const arity = confirmedArityForDef(def);
|
|
4419
|
-
if (arity === null) return true;
|
|
4420
|
-
return arity >= 2;
|
|
4432
|
+
function unwrapSeparator(separator) {
|
|
4433
|
+
return "_keepSeparator" in separator ? { sep: separator._keepSeparator, keep: true } : { sep: separator, keep: false };
|
|
4421
4434
|
}
|
|
4422
|
-
function
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
const
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4435
|
+
function sepBy(combinator, separatorArg, opts = {}) {
|
|
4436
|
+
const { sep: separator, keep: keepSeparators } = unwrapSeparator(separatorArg);
|
|
4437
|
+
const separatorLeads = leadsTrivia(separator);
|
|
4438
|
+
const { min, max } = resolveBounds("sepBy()", opts);
|
|
4439
|
+
const trailing = opts.trailing ?? "forbid";
|
|
4440
|
+
const meta = {
|
|
4441
|
+
firstSet: combinator._meta.firstSet,
|
|
4442
|
+
canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
|
|
4443
|
+
isTrivia: false
|
|
4444
|
+
};
|
|
4445
|
+
let expected;
|
|
4446
|
+
const failAt2 = (at) => {
|
|
4447
|
+
expected ??= deriveExpected(combinator);
|
|
4448
|
+
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
4449
|
+
};
|
|
4450
|
+
const scalarExpected = deriveExpected(combinator);
|
|
4451
|
+
const scalarChild = scalarOf(combinator);
|
|
4452
|
+
const scalarSeparator = scalarOf(separator);
|
|
4453
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4454
|
+
let cur = scalarChild(input, pos, ctx);
|
|
4455
|
+
if (cur < 0) {
|
|
4456
|
+
if (min >= 1) {
|
|
4457
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4458
|
+
return ~pos;
|
|
4436
4459
|
}
|
|
4460
|
+
ctx._sv = [];
|
|
4461
|
+
return pos;
|
|
4437
4462
|
}
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
}
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4463
|
+
const values = [ctx._sv];
|
|
4464
|
+
while (values.length < max && (cur < input.length || values.length < min)) {
|
|
4465
|
+
const beforeSeparator = cur;
|
|
4466
|
+
let separatorPos = cur;
|
|
4467
|
+
if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
|
|
4468
|
+
const separatorEnd = scalarSeparator(input, separatorPos, ctx);
|
|
4469
|
+
if (separatorEnd < 0) break;
|
|
4470
|
+
let itemPos = separatorEnd;
|
|
4471
|
+
if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
|
|
4472
|
+
const itemEnd = scalarChild(input, itemPos, ctx);
|
|
4473
|
+
if (itemEnd < 0) {
|
|
4474
|
+
cur = trailing === "allow" ? separatorEnd : beforeSeparator;
|
|
4475
|
+
break;
|
|
4476
|
+
}
|
|
4477
|
+
values.push(ctx._sv);
|
|
4478
|
+
cur = itemEnd;
|
|
4479
|
+
}
|
|
4480
|
+
if (values.length < min) {
|
|
4481
|
+
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
4482
|
+
return ~cur;
|
|
4483
|
+
}
|
|
4484
|
+
ctx._sv = values;
|
|
4485
|
+
return cur;
|
|
4486
|
+
};
|
|
4487
|
+
return {
|
|
4488
|
+
_tag: "sepBy",
|
|
4489
|
+
_meta: meta,
|
|
4490
|
+
_def: {
|
|
4491
|
+
tag: "sepBy",
|
|
4492
|
+
parser: combinator,
|
|
4493
|
+
separator,
|
|
4494
|
+
min,
|
|
4495
|
+
...max === Infinity ? {} : { max },
|
|
4496
|
+
...trailing === "forbid" ? {} : { trailing },
|
|
4497
|
+
// Carried into the IR so the COMPILED engine demotes exactly where the
|
|
4498
|
+
// interpreter does. The two engines have drifted three separate ways across
|
|
4499
|
+
// this option surface already; parity is held by test/parity, not by hope.
|
|
4500
|
+
...keepSeparators ? { keepSeparators: true } : {}
|
|
4501
|
+
},
|
|
4502
|
+
_parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
|
|
4503
|
+
parse(input, pos, ctx) {
|
|
4504
|
+
const first = combinator.parse(input, pos, ctx);
|
|
4505
|
+
const values = [];
|
|
4506
|
+
let cur;
|
|
4507
|
+
if (first.ok) {
|
|
4508
|
+
values.push(first.value);
|
|
4509
|
+
cur = first.span.end;
|
|
4510
|
+
} else {
|
|
4511
|
+
if (first.committed) return first;
|
|
4512
|
+
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
4513
|
+
if (term === void 0 || matchesAt(term, input, pos, ctx)) {
|
|
4514
|
+
if (min >= 1) return failAt2(pos);
|
|
4515
|
+
return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
4516
|
+
}
|
|
4517
|
+
expected ??= deriveExpected(combinator);
|
|
4518
|
+
const rec = recoverScan(input, pos, ctx, orSentinel(separator, term), expected);
|
|
4519
|
+
values.push(rec.error);
|
|
4520
|
+
captureError(ctx, rec.error);
|
|
4521
|
+
cur = rec.end;
|
|
4522
|
+
}
|
|
4523
|
+
while (cur < input.length || values.length < min) {
|
|
4524
|
+
if (values.length >= max) break;
|
|
4525
|
+
const loopMark = saveTriviaMark(ctx);
|
|
4526
|
+
let sepPos = cur;
|
|
4527
|
+
if (ctx.trivia) {
|
|
4528
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
4529
|
+
sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
4530
|
+
} else {
|
|
4531
|
+
sepPos = advanceTrivia(input, cur, ctx);
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
if (separatorLeads) LEAD.at = cur;
|
|
4535
|
+
const sep = separator.parse(input, sepPos, ctx);
|
|
4536
|
+
if (!sep.ok) {
|
|
4537
|
+
rollbackTrivia(ctx, loopMark);
|
|
4538
|
+
if (sep.committed) return sep;
|
|
4539
|
+
break;
|
|
4540
|
+
}
|
|
4541
|
+
if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
|
|
4542
|
+
const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
|
|
4543
|
+
let nextPos = sep.span.end;
|
|
4544
|
+
if (ctx.trivia) {
|
|
4545
|
+
if (needsDeferredTriviaCommit(ctx)) {
|
|
4546
|
+
nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
|
|
4547
|
+
} else {
|
|
4548
|
+
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
const next = combinator.parse(input, nextPos, ctx);
|
|
4552
|
+
if (!next.ok) {
|
|
4553
|
+
if (next.committed) return next;
|
|
4554
|
+
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
4555
|
+
if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
|
|
4556
|
+
expected ??= deriveExpected(combinator);
|
|
4557
|
+
const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
|
|
4558
|
+
values.push(rec.error);
|
|
4559
|
+
captureError(ctx, rec.error);
|
|
4560
|
+
cur = rec.end;
|
|
4561
|
+
continue;
|
|
4562
|
+
}
|
|
4563
|
+
if (sepMark !== void 0) {
|
|
4564
|
+
rollbackTrivia(ctx, sepMark);
|
|
4565
|
+
cur = sep.span.end;
|
|
4566
|
+
break;
|
|
4567
|
+
}
|
|
4568
|
+
rollbackTrivia(ctx, loopMark);
|
|
4569
|
+
break;
|
|
4570
|
+
}
|
|
4571
|
+
values.push(next.value);
|
|
4572
|
+
cur = next.span.end;
|
|
4573
|
+
}
|
|
4574
|
+
if (values.length < min) return failAt2(cur);
|
|
4575
|
+
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
4576
|
+
}
|
|
4577
|
+
};
|
|
4482
4578
|
}
|
|
4483
4579
|
|
|
4484
|
-
// src/combinators/
|
|
4485
|
-
var
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4580
|
+
// src/combinators/map.ts
|
|
4581
|
+
var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
|
|
4582
|
+
function transform(combinator, fn) {
|
|
4583
|
+
const observesSpan = fn.length > 1;
|
|
4584
|
+
const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
|
|
4585
|
+
const terms = sequenceDef?.parsers;
|
|
4586
|
+
const inner = terms?.[1];
|
|
4587
|
+
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;
|
|
4588
|
+
const child = scalarOf(combinator);
|
|
4589
|
+
const parseScalar = fused ? (() => {
|
|
4590
|
+
const body = inner._stickyRegex;
|
|
4591
|
+
const tuple = ['"', "", '"'];
|
|
4592
|
+
const expected = [JSON.stringify('"')];
|
|
4593
|
+
return (input, pos, ctx) => {
|
|
4594
|
+
if (ctx.trivia !== void 0) {
|
|
4595
|
+
const end2 = child(input, pos, ctx);
|
|
4596
|
+
if (end2 < 0) return end2;
|
|
4597
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
|
|
4598
|
+
return end2;
|
|
4599
|
+
}
|
|
4600
|
+
if (input.charCodeAt(pos) !== 34) {
|
|
4601
|
+
ctx._fx = expected;
|
|
4602
|
+
return ~pos;
|
|
4603
|
+
}
|
|
4604
|
+
body.lastIndex = pos + 1;
|
|
4605
|
+
const match = body.exec(input);
|
|
4606
|
+
const close = pos + 1 + match[0].length;
|
|
4607
|
+
if (input.charCodeAt(close) !== 34) {
|
|
4608
|
+
ctx._fx = expected;
|
|
4609
|
+
return ~close;
|
|
4610
|
+
}
|
|
4611
|
+
tuple[1] = match[0];
|
|
4612
|
+
const end = close + 1;
|
|
4613
|
+
ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
|
|
4614
|
+
return end;
|
|
4615
|
+
};
|
|
4616
|
+
})() : /* @__PURE__ */ (() => {
|
|
4617
|
+
return (input, pos, ctx) => {
|
|
4618
|
+
const end = child(input, pos, ctx);
|
|
4619
|
+
if (end < 0) return end;
|
|
4620
|
+
ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
|
|
4621
|
+
return end;
|
|
4622
|
+
};
|
|
4623
|
+
})();
|
|
4489
4624
|
return {
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4625
|
+
_tag: "transform",
|
|
4626
|
+
_meta: combinator._meta,
|
|
4627
|
+
_def: { tag: "transform", parser: combinator, fn },
|
|
4628
|
+
_parseScalar: parseScalar,
|
|
4629
|
+
parse(input, pos, ctx) {
|
|
4630
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4631
|
+
if (!result.ok) return result;
|
|
4632
|
+
return { ok: true, value: fn(result.value, result.span), span: result.span };
|
|
4633
|
+
}
|
|
4495
4634
|
};
|
|
4496
4635
|
}
|
|
4497
|
-
function
|
|
4498
|
-
|
|
4636
|
+
function trivia(combinator) {
|
|
4637
|
+
const labeled = analyzeLabeledTrivia(combinator);
|
|
4638
|
+
const kindLabels = labeled?.labels;
|
|
4639
|
+
return {
|
|
4640
|
+
_tag: combinator._tag,
|
|
4641
|
+
_meta: {
|
|
4642
|
+
...combinator._meta,
|
|
4643
|
+
isTrivia: true,
|
|
4644
|
+
triviaScanner: fastTriviaScanner(combinator),
|
|
4645
|
+
// Every labeled scan of this trivia reads its spec; the module's four-slot
|
|
4646
|
+
// memo alone thrashes on a grammar with more than four trivia tables.
|
|
4647
|
+
labeledTriviaSpec: labeled,
|
|
4648
|
+
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
4649
|
+
},
|
|
4650
|
+
_def: { tag: "trivia", parser: combinator },
|
|
4651
|
+
_parseScalar: scalarOf(combinator),
|
|
4652
|
+
parse: combinator.parse.bind(combinator)
|
|
4653
|
+
};
|
|
4499
4654
|
}
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
var OP_LIT_TRACK = 17;
|
|
4519
|
-
var OP_RX_TRACK = 18;
|
|
4520
|
-
var OP_NODE_TRACK = 19;
|
|
4521
|
-
var OP_SCOPE = 20;
|
|
4522
|
-
var OP_EXPECT = 21;
|
|
4523
|
-
var OP_SEQX = 22;
|
|
4524
|
-
var OP_SCAN = 23;
|
|
4525
|
-
var OP_FIELD = 24;
|
|
4526
|
-
var OP_LIT_CI = 27;
|
|
4527
|
-
var OP_LIT_CI_TRACK = 28;
|
|
4528
|
-
var OP_TOKEN = 29;
|
|
4529
|
-
var OP_SCOPE_CAP = 30;
|
|
4530
|
-
var OP_WITHCTX = 31;
|
|
4531
|
-
var OP_GUARD = 32;
|
|
4532
|
-
var OP_ADJ = 33;
|
|
4533
|
-
var OP_GREEDY = 34;
|
|
4534
|
-
var OP_REJECT = 35;
|
|
4535
|
-
var OP_ARMGATE = 36;
|
|
4536
|
-
var OP_LIVE = 37;
|
|
4537
|
-
var OP_ATTEMPT = 38;
|
|
4538
|
-
var OP_LABEL = 39;
|
|
4539
|
-
var OP_COV = 40;
|
|
4540
|
-
var OP_SCOPE_PLAIN = 41;
|
|
4541
|
-
var OP_LEX_BODY = 42;
|
|
4542
|
-
var OP_LEX_PROGRAM = 43;
|
|
4543
|
-
var OP_SOURCE_LEAF = 44;
|
|
4544
|
-
var OP_DISPATCH = 25;
|
|
4545
|
-
var OP_ROUTED = 26;
|
|
4546
|
-
var OP_NAMES = {
|
|
4547
|
-
[OP_LIT]: "LIT",
|
|
4548
|
-
[OP_RX]: "RX",
|
|
4549
|
-
[OP_SEQ]: "SEQ",
|
|
4550
|
-
[OP_SEQV]: "SEQV",
|
|
4551
|
-
[OP_CHOICE]: "CHOICE",
|
|
4552
|
-
[OP_REP]: "REP",
|
|
4553
|
-
[OP_REPV]: "REPV",
|
|
4554
|
-
[OP_OPT]: "OPT",
|
|
4555
|
-
[OP_XFORM]: "XFORM",
|
|
4556
|
-
[OP_NODE]: "NODE",
|
|
4557
|
-
[OP_RULE]: "RULE",
|
|
4558
|
-
[OP_GATE]: "GATE",
|
|
4559
|
-
[OP_NOT]: "NOT",
|
|
4560
|
-
[OP_PEEK]: "PEEK",
|
|
4561
|
-
[OP_LEAF]: "LEAF",
|
|
4562
|
-
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
4563
|
-
[OP_EMPTY]: "EMPTY",
|
|
4564
|
-
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
4565
|
-
[OP_RX_TRACK]: "RX_TRACK",
|
|
4566
|
-
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
4567
|
-
[OP_SCOPE]: "SCOPE",
|
|
4568
|
-
[OP_EXPECT]: "EXPECT",
|
|
4569
|
-
[OP_SEQX]: "SEQX",
|
|
4570
|
-
[OP_SCAN]: "SCAN",
|
|
4571
|
-
[OP_FIELD]: "FIELD",
|
|
4572
|
-
[OP_LIT_CI]: "LIT_CI",
|
|
4573
|
-
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
4574
|
-
[OP_DISPATCH]: "DISPATCH",
|
|
4575
|
-
[OP_ROUTED]: "ROUTED",
|
|
4576
|
-
[OP_TOKEN]: "TOKEN",
|
|
4577
|
-
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
4578
|
-
[OP_WITHCTX]: "WITHCTX",
|
|
4579
|
-
[OP_GUARD]: "GUARD",
|
|
4580
|
-
[OP_ADJ]: "ADJ",
|
|
4581
|
-
[OP_GREEDY]: "GREEDY",
|
|
4582
|
-
[OP_REJECT]: "REJECT",
|
|
4583
|
-
[OP_ARMGATE]: "ARMGATE",
|
|
4584
|
-
[OP_LIVE]: "LIVE",
|
|
4585
|
-
[OP_ATTEMPT]: "ATTEMPT",
|
|
4586
|
-
[OP_LABEL]: "LABEL",
|
|
4587
|
-
[OP_COV]: "COV",
|
|
4588
|
-
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
4589
|
-
[OP_LEX_BODY]: "LEX_BODY",
|
|
4590
|
-
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
4591
|
-
};
|
|
4592
|
-
|
|
4593
|
-
// src/combinators/adjacency.ts
|
|
4594
|
-
function adjacencyOf(p) {
|
|
4595
|
-
return p._def.tag === "adjacency" ? p._def : null;
|
|
4596
|
-
}
|
|
4597
|
-
function adjacencyExpected(def) {
|
|
4598
|
-
if (def.polarity === "adjacent") return "adjacent";
|
|
4599
|
-
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
4600
|
-
}
|
|
4601
|
-
function holdsAdjacency(input, cur, ctx, def) {
|
|
4602
|
-
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
4603
|
-
}
|
|
4604
|
-
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
4605
|
-
const end = probeTriviaEnd(input, cur, ctx);
|
|
4606
|
-
if (!negated) return end === cur;
|
|
4607
|
-
if (end === cur) return false;
|
|
4608
|
-
if (kinds === void 0) return true;
|
|
4609
|
-
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
4610
|
-
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
4611
|
-
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
4612
|
-
}
|
|
4613
|
-
function adjacencyFail(pos, def) {
|
|
4614
|
-
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
4615
|
-
}
|
|
4616
|
-
var NO_STANDALONE_PARSE = "adjacency assertions are boundary tests: use adjacent()/notAdjacent() as a NON-FIRST term of a sequence(), where the preceding term defines the gap being asserted.";
|
|
4617
|
-
function adjacencyMisuse(polarity) {
|
|
4618
|
-
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
4655
|
+
function classifiedTrivia(arms) {
|
|
4656
|
+
const entries = Object.entries(arms);
|
|
4657
|
+
if (entries.length === 0) {
|
|
4658
|
+
throw new TypeError("classifiedTrivia() requires at least one named trivia arm.");
|
|
4659
|
+
}
|
|
4660
|
+
for (let i = 0; i < entries.length; i++) {
|
|
4661
|
+
const [name, arm] = entries[i];
|
|
4662
|
+
const first = arm._meta.firstSet;
|
|
4663
|
+
if (matchesEmpty(arm) || first.kind !== "ranges" || first.ranges.length === 0) {
|
|
4664
|
+
throw new TypeError(
|
|
4665
|
+
`classifiedTrivia(): ${JSON.stringify(name)} must be non-nullable with a concrete finite first set.`
|
|
4666
|
+
);
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
const labeledArms = entries.map(([name, arm]) => label(name, arm));
|
|
4670
|
+
const result = trivia(oneOrMore(choice(...labeledArms)));
|
|
4671
|
+
result._meta.rootTriviaClassified = true;
|
|
4672
|
+
return result;
|
|
4619
4673
|
}
|
|
4620
|
-
function
|
|
4621
|
-
const meta = {
|
|
4622
|
-
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
4623
|
-
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
4624
|
-
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
4625
|
-
firstSet: { kind: "any" },
|
|
4626
|
-
canMatchNewline: false,
|
|
4627
|
-
isTrivia: false
|
|
4628
|
-
};
|
|
4674
|
+
function label(name, combinator) {
|
|
4629
4675
|
return {
|
|
4630
|
-
_tag:
|
|
4631
|
-
_meta:
|
|
4632
|
-
_def:
|
|
4633
|
-
parse() {
|
|
4634
|
-
|
|
4676
|
+
_tag: combinator._tag,
|
|
4677
|
+
_meta: combinator._meta,
|
|
4678
|
+
_def: { tag: "label", label: name, parser: combinator },
|
|
4679
|
+
parse(input, pos, ctx) {
|
|
4680
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4681
|
+
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
4682
|
+
return result;
|
|
4635
4683
|
}
|
|
4636
4684
|
};
|
|
4637
4685
|
}
|
|
4638
|
-
function
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4686
|
+
function field(name, combinator, opts) {
|
|
4687
|
+
const leadingTrivia = opts?.leadingTrivia === true;
|
|
4688
|
+
const trailingTrivia = opts?.trailingTrivia === true;
|
|
4689
|
+
if (!leadingTrivia && !trailingTrivia) {
|
|
4690
|
+
return {
|
|
4691
|
+
_tag: combinator._tag,
|
|
4692
|
+
_meta: combinator._meta,
|
|
4693
|
+
_def: { tag: "field", name, parser: combinator },
|
|
4694
|
+
parse(input, pos, ctx) {
|
|
4695
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4696
|
+
if (!result.ok) return result;
|
|
4697
|
+
ctx._fields?.push({ name, value: result.value, span: result.span });
|
|
4698
|
+
return result;
|
|
4650
4699
|
}
|
|
4651
|
-
}
|
|
4700
|
+
};
|
|
4652
4701
|
}
|
|
4653
|
-
return
|
|
4654
|
-
|
|
4655
|
-
|
|
4702
|
+
return {
|
|
4703
|
+
_tag: combinator._tag,
|
|
4704
|
+
_meta: combinator._meta,
|
|
4705
|
+
_def: {
|
|
4706
|
+
tag: "field",
|
|
4707
|
+
name,
|
|
4708
|
+
parser: combinator,
|
|
4709
|
+
...leadingTrivia ? { leadingTrivia: true } : {},
|
|
4710
|
+
...trailingTrivia ? { trailingTrivia: true } : {}
|
|
4711
|
+
},
|
|
4712
|
+
parse(input, pos, ctx) {
|
|
4713
|
+
const leadFrom = LEAD.at;
|
|
4714
|
+
LEAD.at = -1;
|
|
4715
|
+
const result = combinator.parse(input, pos, ctx);
|
|
4716
|
+
if (!result.ok) return result;
|
|
4717
|
+
const end = result.span.end;
|
|
4718
|
+
const trailEnd = trailingTrivia && ctx.trivia ? consumeTrivia(input, end, ctx) : end;
|
|
4719
|
+
ctx._fields?.push(triviaFieldCapture(name, result.value, input, result.span.start, end, leadingTrivia ? leadFrom : -1, trailEnd));
|
|
4720
|
+
return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
|
|
4721
|
+
}
|
|
4722
|
+
};
|
|
4656
4723
|
}
|
|
4657
4724
|
|
|
4658
|
-
// src/combinators/
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
}
|
|
4665
|
-
function missingInferredType() {
|
|
4666
|
-
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
4667
|
-
}
|
|
4668
|
-
function normalizeBuildArity(arity) {
|
|
4669
|
-
if (arity === void 0) return void 0;
|
|
4670
|
-
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
4671
|
-
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
4725
|
+
// src/combinators/regex.ts
|
|
4726
|
+
var SCAN_BAIL_AT = 64;
|
|
4727
|
+
function inRanges3(cp, ranges) {
|
|
4728
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
4729
|
+
const [lo, hi] = ranges[i];
|
|
4730
|
+
if (cp >= lo && cp <= hi) return true;
|
|
4672
4731
|
}
|
|
4673
|
-
return
|
|
4732
|
+
return false;
|
|
4674
4733
|
}
|
|
4675
|
-
function
|
|
4676
|
-
if (
|
|
4677
|
-
|
|
4678
|
-
throw new Error("node() project child must be a non-negative integer");
|
|
4679
|
-
}
|
|
4680
|
-
return project;
|
|
4734
|
+
function readClassRanges(body) {
|
|
4735
|
+
if (body.startsWith("^")) return null;
|
|
4736
|
+
return parseClassRanges(body);
|
|
4681
4737
|
}
|
|
4682
|
-
function
|
|
4683
|
-
if (
|
|
4684
|
-
|
|
4738
|
+
function shortScanner(source, flags) {
|
|
4739
|
+
if (/[imsuvy]/.test(flags)) return null;
|
|
4740
|
+
let ranges = null;
|
|
4741
|
+
let quant = "";
|
|
4742
|
+
if (source[0] === "[") {
|
|
4743
|
+
let end = 1;
|
|
4744
|
+
while (end < source.length && source[end] !== "]") {
|
|
4745
|
+
if (source[end] === "\\") end += 2;
|
|
4746
|
+
else end++;
|
|
4747
|
+
}
|
|
4748
|
+
if (source[end] !== "]") return null;
|
|
4749
|
+
ranges = readClassRanges(source.slice(1, end));
|
|
4750
|
+
quant = source.slice(end + 1);
|
|
4751
|
+
} else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
|
|
4752
|
+
ranges = shorthandRanges(source[1]);
|
|
4753
|
+
quant = source.slice(2);
|
|
4685
4754
|
}
|
|
4686
|
-
|
|
4755
|
+
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
4756
|
+
const minOne = quant === "+";
|
|
4757
|
+
return (input, pos) => {
|
|
4758
|
+
let end = pos;
|
|
4759
|
+
while (end < input.length && inRanges3(input.charCodeAt(end), ranges)) {
|
|
4760
|
+
end++;
|
|
4761
|
+
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
4762
|
+
}
|
|
4763
|
+
return minOne && end === pos ? null : end;
|
|
4764
|
+
};
|
|
4687
4765
|
}
|
|
4688
|
-
function
|
|
4689
|
-
|
|
4690
|
-
const
|
|
4691
|
-
const
|
|
4692
|
-
|
|
4693
|
-
const build = typeof buildArg === "function" ? buildArg : void 0;
|
|
4694
|
-
const opts = typeof buildArg === "function" ? maybeOpts : buildArg ?? maybeOpts;
|
|
4695
|
-
const project = normalizeProject(opts?.project);
|
|
4696
|
-
if (project !== void 0 && build !== void 0) {
|
|
4697
|
-
throw new Error("node() options cannot combine project with a build callback");
|
|
4698
|
-
}
|
|
4699
|
-
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
4700
|
-
const meta = {
|
|
4701
|
-
firstSet: combinator._meta.firstSet,
|
|
4702
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
4703
|
-
isTrivia: false
|
|
4766
|
+
function asciiCaseFold(fs) {
|
|
4767
|
+
if (fs.kind !== "ranges") return fs;
|
|
4768
|
+
const ranges = fs.ranges.map((r) => ({ lo: r.lo, hi: r.hi }));
|
|
4769
|
+
const add = (lo, hi) => {
|
|
4770
|
+
if (lo <= hi) ranges.push({ lo, hi });
|
|
4704
4771
|
};
|
|
4705
|
-
const
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
4711
|
-
if (unwrap && collapse) {
|
|
4712
|
-
throw new Error("node() options cannot set both unwrap and collapse");
|
|
4772
|
+
for (const r of fs.ranges) {
|
|
4773
|
+
const uLo = Math.max(r.lo, 65), uHi = Math.min(r.hi, 90);
|
|
4774
|
+
add(uLo + 32, uHi + 32);
|
|
4775
|
+
const lLo = Math.max(r.lo, 97), lHi = Math.min(r.hi, 122);
|
|
4776
|
+
add(lLo - 32, lHi - 32);
|
|
4713
4777
|
}
|
|
4714
|
-
|
|
4715
|
-
|
|
4778
|
+
ranges.sort((a, b) => a.lo - b.lo);
|
|
4779
|
+
const merged = [];
|
|
4780
|
+
for (const r of ranges) {
|
|
4781
|
+
const last = merged[merged.length - 1];
|
|
4782
|
+
if (last && r.lo <= last.hi + 1) last.hi = Math.max(last.hi, r.hi);
|
|
4783
|
+
else merged.push({ lo: r.lo, hi: r.hi });
|
|
4716
4784
|
}
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
const
|
|
4721
|
-
const
|
|
4722
|
-
const
|
|
4723
|
-
|
|
4785
|
+
return { kind: "ranges", ranges: merged };
|
|
4786
|
+
}
|
|
4787
|
+
function regex(pattern, flags = "") {
|
|
4788
|
+
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
4789
|
+
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
4790
|
+
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
4791
|
+
const scan = shortScanner(source, resolvedFlags);
|
|
4792
|
+
const raw = firstSetFromRegex(source);
|
|
4793
|
+
const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
|
|
4794
|
+
const canMatchNewline = raw.canMatchNewline;
|
|
4795
|
+
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
4796
|
+
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
4797
|
+
const expected = directTerminalFailureExpected(def);
|
|
4798
|
+
const parseScalar = (input, pos, ctx) => {
|
|
4799
|
+
const scanEnd = scan?.(input, pos);
|
|
4800
|
+
if (scanEnd !== void 0) {
|
|
4801
|
+
if (scanEnd === null) {
|
|
4802
|
+
ctx._fx = expected;
|
|
4803
|
+
return ~pos;
|
|
4804
|
+
}
|
|
4805
|
+
ctx._sv = input.slice(pos, scanEnd);
|
|
4806
|
+
return scanEnd;
|
|
4807
|
+
}
|
|
4808
|
+
anchored.lastIndex = pos;
|
|
4809
|
+
const match = anchored.exec(input);
|
|
4810
|
+
if (match === null) {
|
|
4811
|
+
ctx._fx = expected;
|
|
4812
|
+
return ~pos;
|
|
4813
|
+
}
|
|
4814
|
+
ctx._sv = match[0];
|
|
4815
|
+
return pos + match[0].length;
|
|
4816
|
+
};
|
|
4724
4817
|
return {
|
|
4725
|
-
_tag: "
|
|
4818
|
+
_tag: "regex",
|
|
4726
4819
|
_meta: meta,
|
|
4727
4820
|
_def: def,
|
|
4821
|
+
_stickyRegex: anchored,
|
|
4822
|
+
_parseScalar: parseScalar,
|
|
4728
4823
|
parse(input, pos, ctx) {
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
}
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
const hostCst = hasDirectValue && cstOutputHost(ctx.build);
|
|
4738
|
-
const structural = !hasDirectValue;
|
|
4739
|
-
const hostCapturesThisType = structural && def.type !== void 0 && ctx.build?._parsemanCaptureTrivia !== void 0 ? ctx.build._parsemanCaptureTrivia(def.type) : void 0;
|
|
4740
|
-
const effTrivia = structural ? captureTrivia || trailingTrivia || hostCapturesThisType !== false : capturesTrivia || hostCst;
|
|
4741
|
-
const effFields = capturesFields || hostCst && hasOwnFields;
|
|
4742
|
-
const saved = beginCstNodeCapture(ctx);
|
|
4743
|
-
const savedFields = ctx._fields;
|
|
4744
|
-
ctx._fields = effFields ? [] : void 0;
|
|
4745
|
-
const savedMask = ctx._triviaCaptureMask;
|
|
4746
|
-
if (build === void 0 && project === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
|
|
4747
|
-
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
4748
|
-
}
|
|
4749
|
-
if (!effTrivia) ctx.captureTrivia = false;
|
|
4750
|
-
let r = combinator.parse(input, pos, ctx);
|
|
4751
|
-
if (r.ok && trailingTrivia && ctx.trivia) {
|
|
4752
|
-
const end = consumeTrivia(input, r.span.end, ctx);
|
|
4753
|
-
r = { ...r, span: { start: r.span.start, end } };
|
|
4824
|
+
const scanEnd = scan?.(input, pos);
|
|
4825
|
+
if (scanEnd !== void 0) {
|
|
4826
|
+
if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
4827
|
+
const value = input.slice(pos, scanEnd);
|
|
4828
|
+
const span2 = { start: pos, end: scanEnd };
|
|
4829
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
|
|
4830
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
|
|
4831
|
+
return { ok: true, value, span: span2 };
|
|
4754
4832
|
}
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
if (!r.ok) return r;
|
|
4760
|
-
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
4761
|
-
const nodeType = def.type ?? missingInferredType();
|
|
4762
|
-
const cstOutput = cstOutputHost(ctx.build);
|
|
4763
|
-
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
4764
|
-
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
4765
|
-
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
|
|
4766
|
-
const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
4767
|
-
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
4768
|
-
pushCstChild(ctx, built, rawEntry2);
|
|
4833
|
+
anchored.lastIndex = pos;
|
|
4834
|
+
const m = anchored.exec(input);
|
|
4835
|
+
if (m === null) {
|
|
4836
|
+
return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
4769
4837
|
}
|
|
4770
|
-
|
|
4838
|
+
const span = { start: pos, end: pos + m[0].length };
|
|
4839
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
4840
|
+
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
4841
|
+
return { ok: true, value: m[0], span };
|
|
4771
4842
|
}
|
|
4772
4843
|
};
|
|
4773
4844
|
}
|
|
4774
4845
|
|
|
4775
|
-
// src/
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
if (
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
return d.parsers.length > 1;
|
|
4784
|
-
case "many":
|
|
4785
|
-
case "oneOrMore":
|
|
4786
|
-
case "sepBy":
|
|
4787
|
-
return true;
|
|
4788
|
-
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
4789
|
-
case "node":
|
|
4790
|
-
case "transform":
|
|
4791
|
-
case "leaf":
|
|
4792
|
-
case "label":
|
|
4793
|
-
case "field":
|
|
4794
|
-
case "token":
|
|
4795
|
-
case "attempt":
|
|
4796
|
-
case "optional":
|
|
4797
|
-
case "expect":
|
|
4798
|
-
case "withCtx":
|
|
4799
|
-
case "recover":
|
|
4800
|
-
case "trivia":
|
|
4801
|
-
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
4802
|
-
// An alternation adds no position either, but ONE arm that has one is enough
|
|
4803
|
-
// to make the scope meaningful for this rule.
|
|
4804
|
-
case "choice":
|
|
4805
|
-
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
4806
|
-
default:
|
|
4807
|
-
return false;
|
|
4846
|
+
// src/table/lex-body.ts
|
|
4847
|
+
function buildLexBodyRecognizer(spec, constants) {
|
|
4848
|
+
const raw = constants[spec[0]];
|
|
4849
|
+
if (!(raw instanceof RegExp)) {
|
|
4850
|
+
throw new TypeError("table lexical body does not reference a RegExp constant");
|
|
4851
|
+
}
|
|
4852
|
+
if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
|
|
4853
|
+
throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
|
|
4808
4854
|
}
|
|
4855
|
+
const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
|
|
4856
|
+
const suffix = spec[1];
|
|
4857
|
+
return (input, pos) => {
|
|
4858
|
+
re.lastIndex = pos;
|
|
4859
|
+
if (!re.test(input)) return -1;
|
|
4860
|
+
const end = re.lastIndex;
|
|
4861
|
+
if (suffix < 0) return end * 2;
|
|
4862
|
+
return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
|
|
4863
|
+
};
|
|
4809
4864
|
}
|
|
4810
4865
|
|
|
4811
4866
|
// src/table/lex-program.ts
|
|
@@ -5186,888 +5241,890 @@ function buildLexProgramRunner(spec, matchers, classes, expected) {
|
|
|
5186
5241
|
};
|
|
5187
5242
|
}
|
|
5188
5243
|
|
|
5189
|
-
// src/
|
|
5190
|
-
function
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
}
|
|
5204
|
-
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
5205
|
-
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
5206
|
-
return "stop";
|
|
5207
|
-
}
|
|
5208
|
-
const result = combinator.parse(input, pos, ctx);
|
|
5209
|
-
if (!result.ok) {
|
|
5210
|
-
if (mark !== void 0) rollbackTrivia(ctx, mark);
|
|
5211
|
-
if (result.committed) return { fail: result, failPos: pos };
|
|
5212
|
-
return { fail: result, failPos: pos };
|
|
5244
|
+
// src/table/program.ts
|
|
5245
|
+
function closureArtifact(prog) {
|
|
5246
|
+
return { ...prog, asm: [] };
|
|
5247
|
+
}
|
|
5248
|
+
function covKindCode(kind) {
|
|
5249
|
+
switch (kind) {
|
|
5250
|
+
case "rule":
|
|
5251
|
+
return 0;
|
|
5252
|
+
case "choice-arm":
|
|
5253
|
+
return 1;
|
|
5254
|
+
case "dispatch-arm":
|
|
5255
|
+
return 2;
|
|
5256
|
+
case "label":
|
|
5257
|
+
return 3;
|
|
5213
5258
|
}
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5259
|
+
}
|
|
5260
|
+
function covKindName(code) {
|
|
5261
|
+
switch (code) {
|
|
5262
|
+
case 0:
|
|
5263
|
+
return "rule";
|
|
5264
|
+
case 1:
|
|
5265
|
+
return "choice-arm";
|
|
5266
|
+
case 2:
|
|
5267
|
+
return "dispatch-arm";
|
|
5268
|
+
case 3:
|
|
5269
|
+
return "label";
|
|
5217
5270
|
}
|
|
5218
|
-
return result;
|
|
5219
5271
|
}
|
|
5220
|
-
function
|
|
5221
|
-
|
|
5222
|
-
const max = opts.max ?? Infinity;
|
|
5223
|
-
const bad = (msg) => {
|
|
5224
|
-
throw new RangeError(`parseman: ${what} ${msg}`);
|
|
5225
|
-
};
|
|
5226
|
-
if (!Number.isInteger(min) || min < 0) bad(`min must be a non-negative integer (got ${String(opts.min)})`);
|
|
5227
|
-
if (max !== Infinity && (!Number.isInteger(max) || max < 1)) bad(`max must be a positive integer (got ${String(opts.max)})`);
|
|
5228
|
-
if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
|
|
5229
|
-
return { min, max };
|
|
5272
|
+
function covDefinitions(prog) {
|
|
5273
|
+
return (prog.cov ?? []).map(([id, kind]) => ({ id, kind: covKindName(kind) }));
|
|
5230
5274
|
}
|
|
5231
|
-
function
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
|
|
5237
|
-
const end = child(input, itemPos, ctx);
|
|
5238
|
-
if (end <= itemPos) break;
|
|
5239
|
-
if (values !== void 0) values.push(ctx._sv);
|
|
5240
|
-
cur = end;
|
|
5241
|
-
remaining--;
|
|
5242
|
-
}
|
|
5243
|
-
ctx._sv = values;
|
|
5244
|
-
return cur;
|
|
5275
|
+
function scanRefs(s) {
|
|
5276
|
+
const refs = [];
|
|
5277
|
+
for (const r of [s.sentinel, s.recoverAt, s.stopAt, s.prefix, s.body, s.first, s.lazy]) if (r !== void 0) refs.push(r);
|
|
5278
|
+
refs.push(...s.skip);
|
|
5279
|
+
return refs;
|
|
5245
5280
|
}
|
|
5246
|
-
function
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5281
|
+
function expandCompact(p) {
|
|
5282
|
+
if ("code" in p) return p;
|
|
5283
|
+
return ownTableProgram({
|
|
5284
|
+
code: p.c,
|
|
5285
|
+
k: p.k,
|
|
5286
|
+
cc: p.x,
|
|
5287
|
+
fx: p.e,
|
|
5288
|
+
disp: p.d,
|
|
5289
|
+
rules: p.r,
|
|
5290
|
+
fns: p.f,
|
|
5291
|
+
lines: p.l ?? 0,
|
|
5292
|
+
dsp: p.p ?? [],
|
|
5293
|
+
...p.lx === void 0 ? {} : { lex: p.lx },
|
|
5294
|
+
...p.lp === void 0 ? {} : { lexPrograms: p.lp },
|
|
5295
|
+
...p.lb === void 0 ? {} : { labels: p.lb },
|
|
5296
|
+
...p.rc === void 0 ? {} : { classified: p.rc },
|
|
5297
|
+
...p.h === void 0 ? {} : { hostMode: p.h },
|
|
5298
|
+
...p.tv === void 0 ? {} : { triviaSpecs: p.tv },
|
|
5299
|
+
...p.sc === void 0 ? {} : { scans: p.sc },
|
|
5300
|
+
...p.ss === void 0 ? {} : { scanSkip: p.ss },
|
|
5301
|
+
...p.so === void 0 ? {} : { scanSkipOf: p.so },
|
|
5302
|
+
...p.rv === void 0 ? {} : { rec: p.rv },
|
|
5303
|
+
...p.cv === void 0 ? {} : { cov: p.cv },
|
|
5304
|
+
...p.a === void 0 ? {} : { asm: p.a }
|
|
5305
|
+
});
|
|
5306
|
+
}
|
|
5307
|
+
function validateDispatchSpec(spec, arity, fallbackRouted) {
|
|
5308
|
+
const invalid = (arms) => {
|
|
5309
|
+
for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
|
|
5310
|
+
return false;
|
|
5253
5311
|
};
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5312
|
+
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
|
|
5313
|
+
throw new TypeError("table: malformed dispatch");
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
5317
|
+
function ownTableProgram(prog, resolved, caches = {}) {
|
|
5318
|
+
const runtime = prog[TABLE_RUNTIME];
|
|
5259
5319
|
return {
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
5267
|
-
let cur = pos;
|
|
5268
|
-
let count = 0;
|
|
5269
|
-
while (cur < input.length) {
|
|
5270
|
-
if (count >= max) break;
|
|
5271
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
5272
|
-
if (item === "stop") break;
|
|
5273
|
-
if ("fail" in item) {
|
|
5274
|
-
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
5275
|
-
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
5276
|
-
if (sync === void 0) break;
|
|
5277
|
-
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
5278
|
-
expected ??= deriveExpected(combinator);
|
|
5279
|
-
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
5280
|
-
if (values !== void 0) values.push(error);
|
|
5281
|
-
captureError(ctx, error);
|
|
5282
|
-
count++;
|
|
5283
|
-
cur = end;
|
|
5284
|
-
continue;
|
|
5285
|
-
}
|
|
5286
|
-
if (values !== void 0) values.push(item.value);
|
|
5287
|
-
count++;
|
|
5288
|
-
cur = item.span.end;
|
|
5289
|
-
}
|
|
5290
|
-
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
5320
|
+
...prog,
|
|
5321
|
+
[TABLE_RUNTIME]: {
|
|
5322
|
+
resolved,
|
|
5323
|
+
choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
|
|
5324
|
+
nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
|
|
5325
|
+
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
5291
5326
|
}
|
|
5292
5327
|
};
|
|
5293
5328
|
}
|
|
5294
|
-
function
|
|
5295
|
-
return
|
|
5329
|
+
function choiceRollbackMask(prog, ip) {
|
|
5330
|
+
return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
|
|
5296
5331
|
}
|
|
5297
|
-
function
|
|
5298
|
-
|
|
5299
|
-
firstSet: combinator._meta.firstSet,
|
|
5300
|
-
canMatchNewline: combinator._meta.canMatchNewline,
|
|
5301
|
-
isTrivia: false
|
|
5302
|
-
};
|
|
5303
|
-
const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
|
|
5304
|
-
let expected;
|
|
5305
|
-
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
5306
|
-
const scalarChild = scalarOf(combinator);
|
|
5307
|
-
const parseScalar = (input, pos, ctx) => {
|
|
5308
|
-
let cur = scalarChild(input, pos, ctx);
|
|
5309
|
-
if (cur < 0) return cur;
|
|
5310
|
-
const values = def.valueUnused ? void 0 : [ctx._sv];
|
|
5311
|
-
for (let count = 1; count < min; count++) {
|
|
5312
|
-
let itemPos = cur;
|
|
5313
|
-
if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
|
|
5314
|
-
const end = scalarChild(input, itemPos, ctx);
|
|
5315
|
-
if (end < 0) return ~cur;
|
|
5316
|
-
cur = end;
|
|
5317
|
-
if (values !== void 0) values.push(ctx._sv);
|
|
5318
|
-
}
|
|
5319
|
-
return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
|
|
5320
|
-
};
|
|
5321
|
-
return {
|
|
5322
|
-
_tag: "oneOrMore",
|
|
5323
|
-
_meta: meta,
|
|
5324
|
-
_def: def,
|
|
5325
|
-
_parseScalar: parseScalar,
|
|
5326
|
-
parse(input, pos, ctx) {
|
|
5327
|
-
const first = combinator.parse(input, pos, ctx);
|
|
5328
|
-
if (!first.ok) return first;
|
|
5329
|
-
const values = def.valueUnused ? void 0 : [first.value];
|
|
5330
|
-
const rollbackNeeded = needsTriviaRollback(ctx);
|
|
5331
|
-
let cur = first.span.end;
|
|
5332
|
-
let count = 1;
|
|
5333
|
-
while (count < min) {
|
|
5334
|
-
const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
|
|
5335
|
-
if (item === "stop" || "fail" in item) {
|
|
5336
|
-
if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
|
|
5337
|
-
expected ??= deriveExpected(combinator);
|
|
5338
|
-
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
|
|
5339
|
-
}
|
|
5340
|
-
if (values !== void 0) values.push(item.value);
|
|
5341
|
-
cur = item.span.end;
|
|
5342
|
-
count++;
|
|
5343
|
-
}
|
|
5344
|
-
while (cur < input.length) {
|
|
5345
|
-
if (count >= max) break;
|
|
5346
|
-
const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
|
|
5347
|
-
if (item === "stop") break;
|
|
5348
|
-
if ("fail" in item) {
|
|
5349
|
-
if (!item.fail.ok && item.fail.committed) return item.fail;
|
|
5350
|
-
const sync = ctx._tolerant ? ctx._sync : void 0;
|
|
5351
|
-
if (sync === void 0) break;
|
|
5352
|
-
if (matchesAt(sync, input, item.failPos, ctx)) break;
|
|
5353
|
-
expected ??= deriveExpected(combinator);
|
|
5354
|
-
const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
|
|
5355
|
-
if (values !== void 0) values.push(error);
|
|
5356
|
-
captureError(ctx, error);
|
|
5357
|
-
count++;
|
|
5358
|
-
cur = end;
|
|
5359
|
-
continue;
|
|
5360
|
-
}
|
|
5361
|
-
if (values !== void 0) values.push(item.value);
|
|
5362
|
-
count++;
|
|
5363
|
-
cur = item.span.end;
|
|
5364
|
-
}
|
|
5365
|
-
return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
|
|
5366
|
-
}
|
|
5367
|
-
};
|
|
5332
|
+
function choiceCannotCommit(prog, ip) {
|
|
5333
|
+
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
5368
5334
|
}
|
|
5369
|
-
function
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
const
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
|
|
5379
|
-
ctx._sv = null;
|
|
5380
|
-
return pos;
|
|
5381
|
-
}
|
|
5382
|
-
const end = scalarChild(input, pos, ctx);
|
|
5383
|
-
if (end >= 0) return end;
|
|
5384
|
-
ctx._sv = null;
|
|
5385
|
-
return pos;
|
|
5386
|
-
};
|
|
5387
|
-
return {
|
|
5388
|
-
_tag: "optional",
|
|
5389
|
-
_meta: meta,
|
|
5390
|
-
_def: { tag: "optional", parser: combinator },
|
|
5391
|
-
_parseScalar: parseScalar,
|
|
5392
|
-
parse(input, pos, ctx) {
|
|
5393
|
-
if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
|
|
5394
|
-
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
5395
|
-
}
|
|
5396
|
-
const mark = saveTriviaMark(ctx);
|
|
5397
|
-
const result = combinator.parse(input, pos, ctx);
|
|
5398
|
-
if (result.ok) return result;
|
|
5399
|
-
rollbackTrivia(ctx, mark);
|
|
5400
|
-
if (result.committed) return result;
|
|
5401
|
-
return { ok: true, value: null, span: { start: pos, end: pos } };
|
|
5335
|
+
function failureRollbackClean(prog, ip) {
|
|
5336
|
+
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
5337
|
+
}
|
|
5338
|
+
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
5339
|
+
var WIDE_CLASS_PREFIX_HI = 0;
|
|
5340
|
+
function validateClassRange(lo, hi) {
|
|
5341
|
+
for (const cp of [lo, hi]) {
|
|
5342
|
+
if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) {
|
|
5343
|
+
throw new TypeError(`table char-class endpoint is outside Unicode: ${cp}`);
|
|
5402
5344
|
}
|
|
5403
|
-
}
|
|
5345
|
+
}
|
|
5346
|
+
if (lo > hi) {
|
|
5347
|
+
throw new TypeError(`table char-class range is descending: ${lo} > ${hi}`);
|
|
5348
|
+
}
|
|
5404
5349
|
}
|
|
5405
|
-
function
|
|
5406
|
-
|
|
5350
|
+
function encodeClassSpec(ranges) {
|
|
5351
|
+
let wide = false;
|
|
5352
|
+
for (const range of ranges) {
|
|
5353
|
+
validateClassRange(range.lo, range.hi);
|
|
5354
|
+
if (range.hi > 65535) wide = true;
|
|
5355
|
+
}
|
|
5356
|
+
if (!wide) {
|
|
5357
|
+
let spec2 = "";
|
|
5358
|
+
for (const range of ranges) spec2 += String.fromCharCode(range.lo, range.hi);
|
|
5359
|
+
return spec2;
|
|
5360
|
+
}
|
|
5361
|
+
let spec = String.fromCharCode(WIDE_CLASS_PREFIX_LO, WIDE_CLASS_PREFIX_HI);
|
|
5362
|
+
for (const range of ranges) {
|
|
5363
|
+
spec += String.fromCharCode(
|
|
5364
|
+
range.lo >>> 16,
|
|
5365
|
+
range.lo & 65535,
|
|
5366
|
+
range.hi >>> 16,
|
|
5367
|
+
range.hi & 65535
|
|
5368
|
+
);
|
|
5369
|
+
}
|
|
5370
|
+
return spec;
|
|
5407
5371
|
}
|
|
5408
|
-
function
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
let expected;
|
|
5419
|
-
const failAt2 = (at) => {
|
|
5420
|
-
expected ??= deriveExpected(combinator);
|
|
5421
|
-
return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
|
|
5422
|
-
};
|
|
5423
|
-
const scalarExpected = deriveExpected(combinator);
|
|
5424
|
-
const scalarChild = scalarOf(combinator);
|
|
5425
|
-
const scalarSeparator = scalarOf(separator);
|
|
5426
|
-
const parseScalar = (input, pos, ctx) => {
|
|
5427
|
-
let cur = scalarChild(input, pos, ctx);
|
|
5428
|
-
if (cur < 0) {
|
|
5429
|
-
if (min >= 1) {
|
|
5430
|
-
ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
|
|
5431
|
-
return ~pos;
|
|
5432
|
-
}
|
|
5433
|
-
ctx._sv = [];
|
|
5434
|
-
return pos;
|
|
5435
|
-
}
|
|
5436
|
-
const values = [ctx._sv];
|
|
5437
|
-
while (values.length < max && (cur < input.length || values.length < min)) {
|
|
5438
|
-
const beforeSeparator = cur;
|
|
5439
|
-
let separatorPos = cur;
|
|
5440
|
-
if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
|
|
5441
|
-
const separatorEnd = scalarSeparator(input, separatorPos, ctx);
|
|
5442
|
-
if (separatorEnd < 0) break;
|
|
5443
|
-
let itemPos = separatorEnd;
|
|
5444
|
-
if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
|
|
5445
|
-
const itemEnd = scalarChild(input, itemPos, ctx);
|
|
5446
|
-
if (itemEnd < 0) {
|
|
5447
|
-
cur = trailing === "allow" ? separatorEnd : beforeSeparator;
|
|
5448
|
-
break;
|
|
5449
|
-
}
|
|
5450
|
-
values.push(ctx._sv);
|
|
5451
|
-
cur = itemEnd;
|
|
5372
|
+
function decodeClassSpec(spec) {
|
|
5373
|
+
if (spec.charCodeAt(0) === WIDE_CLASS_PREFIX_LO && spec.charCodeAt(1) === WIDE_CLASS_PREFIX_HI) {
|
|
5374
|
+
if ((spec.length - 2) % 4 !== 0) throw new TypeError("table char-class spec has a truncated wide range");
|
|
5375
|
+
if (spec.length === 2) throw new TypeError("table char-class spec has a wide prefix but no ranges");
|
|
5376
|
+
const ranges2 = [];
|
|
5377
|
+
for (let i = 2; i < spec.length; i += 4) {
|
|
5378
|
+
const lo = spec.charCodeAt(i) * 65536 + spec.charCodeAt(i + 1);
|
|
5379
|
+
const hi = spec.charCodeAt(i + 2) * 65536 + spec.charCodeAt(i + 3);
|
|
5380
|
+
validateClassRange(lo, hi);
|
|
5381
|
+
ranges2.push({ lo, hi });
|
|
5452
5382
|
}
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5383
|
+
return ranges2;
|
|
5384
|
+
}
|
|
5385
|
+
if (spec.length % 2 !== 0) throw new TypeError("table char-class spec has an unmatched range endpoint");
|
|
5386
|
+
const ranges = [];
|
|
5387
|
+
for (let i = 0; i < spec.length; i += 2) {
|
|
5388
|
+
const lo = spec.charCodeAt(i);
|
|
5389
|
+
const hi = spec.charCodeAt(i + 1);
|
|
5390
|
+
validateClassRange(lo, hi);
|
|
5391
|
+
ranges.push({ lo, hi });
|
|
5392
|
+
}
|
|
5393
|
+
return ranges;
|
|
5394
|
+
}
|
|
5395
|
+
function resolveClass(spec) {
|
|
5396
|
+
const ascii = new Uint8Array(128);
|
|
5397
|
+
const hi = [];
|
|
5398
|
+
for (const { lo, hi: up } of decodeClassSpec(spec)) {
|
|
5399
|
+
if (lo < 128) for (let c = lo; c <= Math.min(up, 127); c++) ascii[c] = 1;
|
|
5400
|
+
if (up >= 128) hi.push(Math.max(lo, 128), up);
|
|
5401
|
+
}
|
|
5402
|
+
return { ascii, hi };
|
|
5403
|
+
}
|
|
5404
|
+
function classHas2(cls, code) {
|
|
5405
|
+
if (code < 0) return false;
|
|
5406
|
+
if (code < 128) return cls.ascii[code] === 1;
|
|
5407
|
+
const hi = cls.hi;
|
|
5408
|
+
for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
|
|
5409
|
+
return false;
|
|
5410
|
+
}
|
|
5411
|
+
function resolveDispatch(arms, cc) {
|
|
5412
|
+
const ascii = new Uint8Array(128);
|
|
5413
|
+
const hi = [];
|
|
5414
|
+
const open = [];
|
|
5415
|
+
const armCls = [];
|
|
5416
|
+
let exclusive = true;
|
|
5417
|
+
let hiOwners = 0;
|
|
5418
|
+
for (let a = 0; a < arms.length; a++) {
|
|
5419
|
+
const ci = arms[a];
|
|
5420
|
+
if (ci < 0) {
|
|
5421
|
+
open.push(a);
|
|
5422
|
+
armCls.push(null);
|
|
5423
|
+
exclusive = false;
|
|
5424
|
+
continue;
|
|
5456
5425
|
}
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
_def: {
|
|
5464
|
-
tag: "sepBy",
|
|
5465
|
-
parser: combinator,
|
|
5466
|
-
separator,
|
|
5467
|
-
min,
|
|
5468
|
-
...max === Infinity ? {} : { max },
|
|
5469
|
-
...trailing === "forbid" ? {} : { trailing },
|
|
5470
|
-
// Carried into the IR so the COMPILED engine demotes exactly where the
|
|
5471
|
-
// interpreter does. The two engines have drifted three separate ways across
|
|
5472
|
-
// this option surface already; parity is held by test/parity, not by hope.
|
|
5473
|
-
...keepSeparators ? { keepSeparators: true } : {}
|
|
5474
|
-
},
|
|
5475
|
-
_parseScalar: keepSeparators || separatorLeads ? void 0 : parseScalar,
|
|
5476
|
-
parse(input, pos, ctx) {
|
|
5477
|
-
const first = combinator.parse(input, pos, ctx);
|
|
5478
|
-
const values = [];
|
|
5479
|
-
let cur;
|
|
5480
|
-
if (first.ok) {
|
|
5481
|
-
values.push(first.value);
|
|
5482
|
-
cur = first.span.end;
|
|
5483
|
-
} else {
|
|
5484
|
-
if (first.committed) return first;
|
|
5485
|
-
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
5486
|
-
if (term === void 0 || matchesAt(term, input, pos, ctx)) {
|
|
5487
|
-
if (min >= 1) return failAt2(pos);
|
|
5488
|
-
return { ok: true, value: [], span: { start: pos, end: pos } };
|
|
5489
|
-
}
|
|
5490
|
-
expected ??= deriveExpected(combinator);
|
|
5491
|
-
const rec = recoverScan(input, pos, ctx, orSentinel(separator, term), expected);
|
|
5492
|
-
values.push(rec.error);
|
|
5493
|
-
captureError(ctx, rec.error);
|
|
5494
|
-
cur = rec.end;
|
|
5495
|
-
}
|
|
5496
|
-
while (cur < input.length || values.length < min) {
|
|
5497
|
-
if (values.length >= max) break;
|
|
5498
|
-
const loopMark = saveTriviaMark(ctx);
|
|
5499
|
-
let sepPos = cur;
|
|
5500
|
-
if (ctx.trivia) {
|
|
5501
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
5502
|
-
sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
|
|
5503
|
-
} else {
|
|
5504
|
-
sepPos = advanceTrivia(input, cur, ctx);
|
|
5505
|
-
}
|
|
5506
|
-
}
|
|
5507
|
-
if (separatorLeads) LEAD.at = cur;
|
|
5508
|
-
const sep = separator.parse(input, sepPos, ctx);
|
|
5509
|
-
if (!sep.ok) {
|
|
5510
|
-
rollbackTrivia(ctx, loopMark);
|
|
5511
|
-
if (sep.committed) return sep;
|
|
5512
|
-
break;
|
|
5513
|
-
}
|
|
5514
|
-
if (!keepSeparators) demoteCapturedToRaw(ctx, loopMark.leaves);
|
|
5515
|
-
const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
|
|
5516
|
-
let nextPos = sep.span.end;
|
|
5517
|
-
if (ctx.trivia) {
|
|
5518
|
-
if (needsDeferredTriviaCommit(ctx)) {
|
|
5519
|
-
nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
|
|
5520
|
-
} else {
|
|
5521
|
-
nextPos = advanceTrivia(input, sep.span.end, ctx);
|
|
5522
|
-
}
|
|
5523
|
-
}
|
|
5524
|
-
const next = combinator.parse(input, nextPos, ctx);
|
|
5525
|
-
if (!next.ok) {
|
|
5526
|
-
if (next.committed) return next;
|
|
5527
|
-
const term = ctx._tolerant ? ctx._sync : void 0;
|
|
5528
|
-
if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
|
|
5529
|
-
expected ??= deriveExpected(combinator);
|
|
5530
|
-
const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
|
|
5531
|
-
values.push(rec.error);
|
|
5532
|
-
captureError(ctx, rec.error);
|
|
5533
|
-
cur = rec.end;
|
|
5534
|
-
continue;
|
|
5535
|
-
}
|
|
5536
|
-
if (sepMark !== void 0) {
|
|
5537
|
-
rollbackTrivia(ctx, sepMark);
|
|
5538
|
-
cur = sep.span.end;
|
|
5539
|
-
break;
|
|
5540
|
-
}
|
|
5541
|
-
rollbackTrivia(ctx, loopMark);
|
|
5542
|
-
break;
|
|
5543
|
-
}
|
|
5544
|
-
values.push(next.value);
|
|
5545
|
-
cur = next.span.end;
|
|
5546
|
-
}
|
|
5547
|
-
if (values.length < min) return failAt2(cur);
|
|
5548
|
-
return { ok: true, value: values, span: { start: pos, end: cur } };
|
|
5426
|
+
const cls = cc[ci];
|
|
5427
|
+
armCls.push(cls);
|
|
5428
|
+
for (let c = 0; c < 128; c++) {
|
|
5429
|
+
if (cls.ascii[c] !== 1) continue;
|
|
5430
|
+
if (ascii[c] === 0) ascii[c] = a + 1;
|
|
5431
|
+
else exclusive = false;
|
|
5549
5432
|
}
|
|
5433
|
+
if (cls.hi.length > 0 && ++hiOwners > 1) exclusive = false;
|
|
5434
|
+
for (let i = 0; i < cls.hi.length; i += 2) hi.push(cls.hi[i], cls.hi[i + 1], a);
|
|
5435
|
+
}
|
|
5436
|
+
return { ascii, hi, open, armCls, exclusive };
|
|
5437
|
+
}
|
|
5438
|
+
function buildTrivia(spec) {
|
|
5439
|
+
if (spec.live !== void 0) return spec.live;
|
|
5440
|
+
if (spec.plain !== void 0) return trivia(regex(new RegExp(spec.plain[0], spec.plain[1])));
|
|
5441
|
+
if (spec.alts !== void 0) {
|
|
5442
|
+
const [head, ...rest] = spec.alts.map(([source, flags]) => regex(new RegExp(source, flags)));
|
|
5443
|
+
if (head === void 0) throw new TypeError("trivia spec has an EMPTY alternation, which matches nothing");
|
|
5444
|
+
const body = rest.length === 0 ? head : choice(head, ...rest);
|
|
5445
|
+
return trivia(many(body, { min: spec.min ?? 1 }));
|
|
5446
|
+
}
|
|
5447
|
+
const arms = {};
|
|
5448
|
+
for (const [name, source, flags] of spec.arms) arms[name] = regex(new RegExp(source, flags));
|
|
5449
|
+
return classifiedTrivia(arms);
|
|
5450
|
+
}
|
|
5451
|
+
function resolveTable(prog) {
|
|
5452
|
+
const owner = prog[TABLE_RUNTIME];
|
|
5453
|
+
const hit = owner?.resolved;
|
|
5454
|
+
if (hit !== void 0) return hit;
|
|
5455
|
+
const cc = prog.cc.map(resolveClass);
|
|
5456
|
+
const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
|
|
5457
|
+
const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
|
|
5458
|
+
const built = {
|
|
5459
|
+
prog,
|
|
5460
|
+
code: Int32Array.from(prog.code),
|
|
5461
|
+
k: prog.k,
|
|
5462
|
+
fns: prog.fns,
|
|
5463
|
+
cc,
|
|
5464
|
+
fx: prog.fx,
|
|
5465
|
+
disp: prog.disp.map((d) => resolveDispatch(d, cc)),
|
|
5466
|
+
trivia: triviaBuilt,
|
|
5467
|
+
triviaScan: triviaBuilt.map(fastTriviaScanner),
|
|
5468
|
+
triviaLabelled: triviaBuilt.map((t2) => t2._meta.triviaKindLabels !== void 0),
|
|
5469
|
+
dsp: prog.dsp.map((d) => ({
|
|
5470
|
+
byKey: new Map(d.key.map((x, i) => [x, d.keyArm[i]])),
|
|
5471
|
+
byFold: new Map(d.fold.map((x, i) => [x, d.foldArm[i]])),
|
|
5472
|
+
match: d.match,
|
|
5473
|
+
routed: d.routed,
|
|
5474
|
+
expected: d.expected
|
|
5475
|
+
})),
|
|
5476
|
+
lex,
|
|
5477
|
+
lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
|
|
5478
|
+
rules: prog.rules
|
|
5550
5479
|
};
|
|
5480
|
+
if (owner !== void 0) owner.resolved = built;
|
|
5481
|
+
return built;
|
|
5551
5482
|
}
|
|
5552
5483
|
|
|
5553
|
-
// src/
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
const
|
|
5560
|
-
const
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5484
|
+
// src/compiler/degradation.ts
|
|
5485
|
+
function formatDegradation(d) {
|
|
5486
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
5487
|
+
}
|
|
5488
|
+
var DETAIL_CAP = 8;
|
|
5489
|
+
function formatDegradations(list) {
|
|
5490
|
+
const byCode = /* @__PURE__ */ new Map();
|
|
5491
|
+
for (const d of list) {
|
|
5492
|
+
const bucket = byCode.get(d.code);
|
|
5493
|
+
if (bucket) bucket.push(d);
|
|
5494
|
+
else byCode.set(d.code, [d]);
|
|
5495
|
+
}
|
|
5496
|
+
const out = [];
|
|
5497
|
+
for (const [code, items] of byCode) {
|
|
5498
|
+
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
5499
|
+
if (items.length > DETAIL_CAP) {
|
|
5500
|
+
out.push(
|
|
5501
|
+
`[parseman] degraded [${code}] +${items.length - DETAIL_CAP} more site(s) not listed (${items.length} total). Set PARSEMAN_DEGRADATION=error to fail the build on these.`
|
|
5502
|
+
);
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
return out;
|
|
5506
|
+
}
|
|
5507
|
+
var _sinks = [];
|
|
5508
|
+
function beginDegradationCapture() {
|
|
5509
|
+
_sinks.push(/* @__PURE__ */ new Map());
|
|
5510
|
+
}
|
|
5511
|
+
function degradationCaptureDepth() {
|
|
5512
|
+
return _sinks.length;
|
|
5513
|
+
}
|
|
5514
|
+
function unwindDegradationCapture(depth) {
|
|
5515
|
+
const found = [];
|
|
5516
|
+
while (_sinks.length > depth) {
|
|
5517
|
+
const sink = _sinks.pop();
|
|
5518
|
+
found.unshift(...sink.values());
|
|
5519
|
+
}
|
|
5520
|
+
return found;
|
|
5521
|
+
}
|
|
5522
|
+
function resolveDegradationLevel(explicit) {
|
|
5523
|
+
if (explicit !== void 0) return explicit;
|
|
5524
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
5525
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
5526
|
+
return "warn";
|
|
5527
|
+
}
|
|
5528
|
+
function degradationKey(d) {
|
|
5529
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
5530
|
+
}
|
|
5531
|
+
function recordDegradation(d) {
|
|
5532
|
+
const level = resolveDegradationLevel();
|
|
5533
|
+
if (level === "off") return;
|
|
5534
|
+
const key = degradationKey(d);
|
|
5535
|
+
const sink = _sinks[_sinks.length - 1];
|
|
5536
|
+
if (sink) {
|
|
5537
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
5538
|
+
return;
|
|
5539
|
+
}
|
|
5540
|
+
if (_immediate.has(key)) return;
|
|
5541
|
+
_immediate.add(key);
|
|
5542
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
5543
|
+
${formatDegradation(d)}`);
|
|
5544
|
+
console.warn(formatDegradation(d));
|
|
5545
|
+
}
|
|
5546
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
5547
|
+
function beginCompileDegradationDrain() {
|
|
5548
|
+
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
5549
|
+
};
|
|
5550
|
+
const depth = degradationCaptureDepth();
|
|
5551
|
+
beginDegradationCapture();
|
|
5552
|
+
return (report) => {
|
|
5553
|
+
const found = unwindDegradationCapture(depth);
|
|
5554
|
+
if (!report || found.length === 0) return;
|
|
5555
|
+
const fresh = found.filter((d) => {
|
|
5556
|
+
const k = degradationKey(d);
|
|
5557
|
+
if (_immediate.has(k)) return false;
|
|
5558
|
+
_immediate.add(k);
|
|
5559
|
+
return true;
|
|
5560
|
+
});
|
|
5561
|
+
if (fresh.length === 0) return;
|
|
5562
|
+
const lines2 = formatDegradations(fresh);
|
|
5563
|
+
if (resolveDegradationLevel() === "error") {
|
|
5564
|
+
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
5565
|
+
${lines2.join("\n")}`);
|
|
5606
5566
|
}
|
|
5567
|
+
for (const l of lines2) console.warn(l);
|
|
5607
5568
|
};
|
|
5608
5569
|
}
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
return
|
|
5613
|
-
_tag: combinator._tag,
|
|
5614
|
-
_meta: {
|
|
5615
|
-
...combinator._meta,
|
|
5616
|
-
isTrivia: true,
|
|
5617
|
-
triviaScanner: fastTriviaScanner(combinator),
|
|
5618
|
-
// Every labeled scan of this trivia reads its spec; the module's four-slot
|
|
5619
|
-
// memo alone thrashes on a grammar with more than four trivia tables.
|
|
5620
|
-
labeledTriviaSpec: labeled,
|
|
5621
|
-
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
5622
|
-
},
|
|
5623
|
-
_def: { tag: "trivia", parser: combinator },
|
|
5624
|
-
_parseScalar: scalarOf(combinator),
|
|
5625
|
-
parse: combinator.parse.bind(combinator)
|
|
5626
|
-
};
|
|
5570
|
+
|
|
5571
|
+
// src/compiler/build-arity.ts
|
|
5572
|
+
function cstOutputHost(build) {
|
|
5573
|
+
return build?._parsemanCstOutput === true;
|
|
5627
5574
|
}
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5575
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
5576
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
5577
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
5578
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
5579
|
+
function confirmedBuildArity(src) {
|
|
5580
|
+
const s = src.trim();
|
|
5581
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
5582
|
+
if (/\barguments\b/.test(s)) return null;
|
|
5583
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
5584
|
+
const inner = paramListText(s);
|
|
5585
|
+
if (inner === null) return null;
|
|
5586
|
+
if (inner.trim() === "") return 0;
|
|
5587
|
+
const parts = splitTopLevel(inner);
|
|
5588
|
+
if (parts === null) return null;
|
|
5589
|
+
for (const part of parts) {
|
|
5590
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
5632
5591
|
}
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5592
|
+
return parts.length;
|
|
5593
|
+
}
|
|
5594
|
+
function paramListText(s) {
|
|
5595
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
5596
|
+
if (!open) return null;
|
|
5597
|
+
const start = open[0].length;
|
|
5598
|
+
const end = matchingParen(s, start);
|
|
5599
|
+
if (end === null) return null;
|
|
5600
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
5601
|
+
return s.slice(start, end);
|
|
5602
|
+
}
|
|
5603
|
+
function matchingParen(s, start) {
|
|
5604
|
+
let depth = 0;
|
|
5605
|
+
for (let i = start; i < s.length; i++) {
|
|
5606
|
+
const c = s[i];
|
|
5607
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
5608
|
+
const close = skipString(s, i);
|
|
5609
|
+
if (close === null) return null;
|
|
5610
|
+
i = close;
|
|
5611
|
+
continue;
|
|
5612
|
+
}
|
|
5613
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5614
|
+
else if (c === "]" || c === "}") {
|
|
5615
|
+
if (--depth < 0) return null;
|
|
5616
|
+
} else if (c === ")") {
|
|
5617
|
+
if (depth === 0) return i;
|
|
5618
|
+
depth--;
|
|
5640
5619
|
}
|
|
5641
5620
|
}
|
|
5642
|
-
|
|
5643
|
-
const result = trivia(oneOrMore(choice(...labeledArms)));
|
|
5644
|
-
result._meta.rootTriviaClassified = true;
|
|
5645
|
-
return result;
|
|
5621
|
+
return null;
|
|
5646
5622
|
}
|
|
5647
|
-
function
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
const result = combinator.parse(input, pos, ctx);
|
|
5654
|
-
if (!result.ok) return { ok: false, expected: [name], span: result.span };
|
|
5655
|
-
return result;
|
|
5623
|
+
function skipString(s, open) {
|
|
5624
|
+
const quote = s[open];
|
|
5625
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
5626
|
+
if (s[i] === "\\") {
|
|
5627
|
+
i++;
|
|
5628
|
+
continue;
|
|
5656
5629
|
}
|
|
5657
|
-
|
|
5630
|
+
if (s[i] === quote) return i;
|
|
5631
|
+
}
|
|
5632
|
+
return null;
|
|
5658
5633
|
}
|
|
5659
|
-
function
|
|
5660
|
-
const
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5634
|
+
function splitTopLevel(inner) {
|
|
5635
|
+
const parts = [];
|
|
5636
|
+
let depth = 0;
|
|
5637
|
+
let angle = 0;
|
|
5638
|
+
let last = 0;
|
|
5639
|
+
for (let i = 0; i < inner.length; i++) {
|
|
5640
|
+
const c = inner[i];
|
|
5641
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
5642
|
+
i++;
|
|
5643
|
+
continue;
|
|
5644
|
+
}
|
|
5645
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
5646
|
+
const close = skipString(inner, i);
|
|
5647
|
+
if (close === null) return null;
|
|
5648
|
+
i = close;
|
|
5649
|
+
continue;
|
|
5650
|
+
}
|
|
5651
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
5652
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
5653
|
+
if (--depth < 0) return null;
|
|
5654
|
+
} else if (c === "<") angle++;
|
|
5655
|
+
else if (c === ">") {
|
|
5656
|
+
if (--angle < 0) return null;
|
|
5657
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
5658
|
+
parts.push(inner.slice(last, i));
|
|
5659
|
+
last = i + 1;
|
|
5660
|
+
}
|
|
5674
5661
|
}
|
|
5675
|
-
return
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
return trailEnd === end ? result : { ok: true, value: result.value, span: { start: result.span.start, end: trailEnd } };
|
|
5662
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
5663
|
+
parts.push(inner.slice(last));
|
|
5664
|
+
return parts;
|
|
5665
|
+
}
|
|
5666
|
+
function isConfirmableParam(part) {
|
|
5667
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
5668
|
+
if (!head) return false;
|
|
5669
|
+
const rest = part.slice(head[0].length);
|
|
5670
|
+
if (rest === "") return true;
|
|
5671
|
+
if (rest[0] !== ":") return false;
|
|
5672
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
5673
|
+
}
|
|
5674
|
+
function hasDefaultAssign(annotation) {
|
|
5675
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
5676
|
+
if (annotation[i] !== "=") continue;
|
|
5677
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
5678
|
+
i++;
|
|
5679
|
+
continue;
|
|
5694
5680
|
}
|
|
5695
|
-
|
|
5681
|
+
const prev = annotation[i - 1];
|
|
5682
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
5683
|
+
return true;
|
|
5684
|
+
}
|
|
5685
|
+
return false;
|
|
5686
|
+
}
|
|
5687
|
+
function buildAnalysisSrc(def) {
|
|
5688
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
5689
|
+
}
|
|
5690
|
+
var RESOLVER_REASONS = {
|
|
5691
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
5692
|
+
"arguments": "its body references `arguments`",
|
|
5693
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
5694
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
5695
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
5696
|
+
"not-found": "the name did not resolve to any binding",
|
|
5697
|
+
"computed": "it is a computed expression",
|
|
5698
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
5699
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
5700
|
+
};
|
|
5701
|
+
function unconfirmableReason(def, src) {
|
|
5702
|
+
const declared = def.buildArityUnresolved;
|
|
5703
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
5704
|
+
const s = src.trim();
|
|
5705
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
5706
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
5707
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
5708
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
5709
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
5710
|
+
}
|
|
5711
|
+
return "its parameter list could not be parsed";
|
|
5712
|
+
}
|
|
5713
|
+
function confirmedArityForDef(def) {
|
|
5714
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
5715
|
+
const src = buildAnalysisSrc(def);
|
|
5716
|
+
const arity = confirmedBuildArity(src);
|
|
5717
|
+
if (arity !== null) return arity;
|
|
5718
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
5719
|
+
recordDegradation({
|
|
5720
|
+
code: "build-arity-unconfirmed",
|
|
5721
|
+
severity: "warn",
|
|
5722
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
5723
|
+
subject,
|
|
5724
|
+
fellBackTo: `could not confirm its declared arity \u2014 ${unconfirmableReason(def, src)} \u2014 so this node captures children, fields and raw children, logs trivia, and clones \`_ctx.state\` on every match`,
|
|
5725
|
+
otherwise: "only the tiers the reducer actually declares would be captured (arity >= 1 children, >= 2 fields, >= 4 raw, >= 5 trivia, >= 6 state). Declare it with `node(..., { buildArity: n })` if it cannot be derived"
|
|
5726
|
+
});
|
|
5727
|
+
return null;
|
|
5728
|
+
}
|
|
5729
|
+
function buildReadsRaw(def) {
|
|
5730
|
+
if (!def.build) return true;
|
|
5731
|
+
if (def.buildRawUnused === true) return false;
|
|
5732
|
+
const arity = confirmedArityForDef(def);
|
|
5733
|
+
if (arity === null) return true;
|
|
5734
|
+
return arity >= 4;
|
|
5696
5735
|
}
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
const [lo, hi] = ranges[i];
|
|
5703
|
-
if (cp >= lo && cp <= hi) return true;
|
|
5704
|
-
}
|
|
5705
|
-
return false;
|
|
5736
|
+
function buildReadsTrivia(def) {
|
|
5737
|
+
if (!def.build) return true;
|
|
5738
|
+
const arity = confirmedArityForDef(def);
|
|
5739
|
+
if (arity === null) return true;
|
|
5740
|
+
return arity >= 5;
|
|
5706
5741
|
}
|
|
5707
|
-
function
|
|
5708
|
-
if (
|
|
5709
|
-
|
|
5742
|
+
function buildReadsState(def) {
|
|
5743
|
+
if (!def.build) return true;
|
|
5744
|
+
const arity = confirmedArityForDef(def);
|
|
5745
|
+
if (arity === null) return true;
|
|
5746
|
+
return arity >= 6;
|
|
5710
5747
|
}
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5748
|
+
|
|
5749
|
+
// src/compiler/fields.ts
|
|
5750
|
+
function buildReadsFields(def) {
|
|
5751
|
+
if (!def.build) return true;
|
|
5752
|
+
const arity = confirmedArityForDef(def);
|
|
5753
|
+
if (arity === null) return true;
|
|
5754
|
+
return arity >= 2;
|
|
5755
|
+
}
|
|
5756
|
+
function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
|
|
5757
|
+
if (seen.has(p)) return false;
|
|
5758
|
+
seen.add(p);
|
|
5759
|
+
const d = p._def;
|
|
5760
|
+
switch (d.tag) {
|
|
5761
|
+
case "field":
|
|
5762
|
+
return true;
|
|
5763
|
+
case "node":
|
|
5764
|
+
return false;
|
|
5765
|
+
case "lazy": {
|
|
5766
|
+
try {
|
|
5767
|
+
return parserHasOwnFields(d.thunk(), seen);
|
|
5768
|
+
} catch {
|
|
5769
|
+
return false;
|
|
5770
|
+
}
|
|
5720
5771
|
}
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5772
|
+
case "sequence":
|
|
5773
|
+
case "choice":
|
|
5774
|
+
return d.parsers.some((x) => parserHasOwnFields(x, seen));
|
|
5775
|
+
case "dispatch":
|
|
5776
|
+
return parserHasOwnFields(d.selector, seen) || d.cases.some((x) => parserHasOwnFields(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => parserHasOwnFields(entry.parser, seen)) : false) || (d.otherwise ? parserHasOwnFields(d.otherwise, seen) : false);
|
|
5777
|
+
case "sepBy":
|
|
5778
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
|
|
5779
|
+
case "grammar":
|
|
5780
|
+
return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
|
|
5781
|
+
case "scanTo":
|
|
5782
|
+
return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen)) || d.recoverAt !== void 0 && parserHasOwnFields(d.recoverAt, seen) || d.stopAt !== void 0 && parserHasOwnFields(d.stopAt, seen);
|
|
5783
|
+
case "recover":
|
|
5784
|
+
return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
|
|
5785
|
+
case "lines":
|
|
5786
|
+
return parserHasOwnFields(d.body, seen);
|
|
5787
|
+
case "routed":
|
|
5788
|
+
return d.fallback ? parserHasOwnFields(d.fallback, seen) : false;
|
|
5789
|
+
case "many":
|
|
5790
|
+
case "oneOrMore":
|
|
5791
|
+
case "optional":
|
|
5792
|
+
case "attempt":
|
|
5793
|
+
case "transform":
|
|
5794
|
+
case "trivia":
|
|
5795
|
+
case "token":
|
|
5796
|
+
case "leaf":
|
|
5797
|
+
case "label":
|
|
5798
|
+
case "expect":
|
|
5799
|
+
case "withCtx":
|
|
5800
|
+
case "not":
|
|
5801
|
+
case "peek":
|
|
5802
|
+
return parserHasOwnFields(d.parser, seen);
|
|
5803
|
+
default:
|
|
5804
|
+
return false;
|
|
5727
5805
|
}
|
|
5728
|
-
if (!ranges || quant !== "+" && quant !== "*") return null;
|
|
5729
|
-
const minOne = quant === "+";
|
|
5730
|
-
return (input, pos) => {
|
|
5731
|
-
let end = pos;
|
|
5732
|
-
while (end < input.length && inRanges3(input.charCodeAt(end), ranges)) {
|
|
5733
|
-
end++;
|
|
5734
|
-
if (end - pos >= SCAN_BAIL_AT) return void 0;
|
|
5735
|
-
}
|
|
5736
|
-
return minOne && end === pos ? null : end;
|
|
5737
|
-
};
|
|
5738
5806
|
}
|
|
5739
|
-
function
|
|
5740
|
-
if (
|
|
5741
|
-
const
|
|
5742
|
-
const
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
const lLo = Math.max(r.lo, 97), lHi = Math.min(r.hi, 122);
|
|
5749
|
-
add(lLo - 32, lHi - 32);
|
|
5750
|
-
}
|
|
5751
|
-
ranges.sort((a, b) => a.lo - b.lo);
|
|
5752
|
-
const merged = [];
|
|
5753
|
-
for (const r of ranges) {
|
|
5754
|
-
const last = merged[merged.length - 1];
|
|
5755
|
-
if (last && r.lo <= last.hi + 1) last.hi = Math.max(last.hi, r.hi);
|
|
5756
|
-
else merged.push({ lo: r.lo, hi: r.hi });
|
|
5807
|
+
function buildFieldMap(captures) {
|
|
5808
|
+
if (!captures?.length) return void 0;
|
|
5809
|
+
const out = {};
|
|
5810
|
+
for (const cap of captures) {
|
|
5811
|
+
const entry = cap.leading === void 0 ? { value: cap.value, span: cap.span } : { value: cap.value, span: cap.span, leading: cap.leading, trailing: cap.trailing };
|
|
5812
|
+
const current = out[cap.name];
|
|
5813
|
+
if (current === void 0) out[cap.name] = entry;
|
|
5814
|
+
else if (Array.isArray(current)) current.push(entry);
|
|
5815
|
+
else out[cap.name] = [current, entry];
|
|
5757
5816
|
}
|
|
5758
|
-
return
|
|
5759
|
-
}
|
|
5760
|
-
function regex(pattern, flags = "") {
|
|
5761
|
-
const source = typeof pattern === "string" ? pattern : pattern.source;
|
|
5762
|
-
const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
|
|
5763
|
-
const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
|
|
5764
|
-
const scan = shortScanner(source, resolvedFlags);
|
|
5765
|
-
const raw = firstSetFromRegex(source);
|
|
5766
|
-
const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
|
|
5767
|
-
const canMatchNewline = raw.canMatchNewline;
|
|
5768
|
-
const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
|
|
5769
|
-
const def = { tag: "regex", source, flags: resolvedFlags };
|
|
5770
|
-
const expected = directTerminalFailureExpected(def);
|
|
5771
|
-
const parseScalar = (input, pos, ctx) => {
|
|
5772
|
-
const scanEnd = scan?.(input, pos);
|
|
5773
|
-
if (scanEnd !== void 0) {
|
|
5774
|
-
if (scanEnd === null) {
|
|
5775
|
-
ctx._fx = expected;
|
|
5776
|
-
return ~pos;
|
|
5777
|
-
}
|
|
5778
|
-
ctx._sv = input.slice(pos, scanEnd);
|
|
5779
|
-
return scanEnd;
|
|
5780
|
-
}
|
|
5781
|
-
anchored.lastIndex = pos;
|
|
5782
|
-
const match = anchored.exec(input);
|
|
5783
|
-
if (match === null) {
|
|
5784
|
-
ctx._fx = expected;
|
|
5785
|
-
return ~pos;
|
|
5786
|
-
}
|
|
5787
|
-
ctx._sv = match[0];
|
|
5788
|
-
return pos + match[0].length;
|
|
5789
|
-
};
|
|
5790
|
-
return {
|
|
5791
|
-
_tag: "regex",
|
|
5792
|
-
_meta: meta,
|
|
5793
|
-
_def: def,
|
|
5794
|
-
_stickyRegex: anchored,
|
|
5795
|
-
_parseScalar: parseScalar,
|
|
5796
|
-
parse(input, pos, ctx) {
|
|
5797
|
-
const scanEnd = scan?.(input, pos);
|
|
5798
|
-
if (scanEnd !== void 0) {
|
|
5799
|
-
if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
5800
|
-
const value = input.slice(pos, scanEnd);
|
|
5801
|
-
const span2 = { start: pos, end: scanEnd };
|
|
5802
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
|
|
5803
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
|
|
5804
|
-
return { ok: true, value, span: span2 };
|
|
5805
|
-
}
|
|
5806
|
-
anchored.lastIndex = pos;
|
|
5807
|
-
const m = anchored.exec(input);
|
|
5808
|
-
if (m === null) {
|
|
5809
|
-
return failAt(ctx, directTerminalFailureExpected(def), pos);
|
|
5810
|
-
}
|
|
5811
|
-
const span = { start: pos, end: pos + m[0].length };
|
|
5812
|
-
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
5813
|
-
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
5814
|
-
return { ok: true, value: m[0], span };
|
|
5815
|
-
}
|
|
5816
|
-
};
|
|
5817
|
+
return out;
|
|
5817
5818
|
}
|
|
5818
5819
|
|
|
5819
|
-
// src/table/
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5820
|
+
// src/table/ops.ts
|
|
5821
|
+
var OP_LIT = 1;
|
|
5822
|
+
var OP_RX = 2;
|
|
5823
|
+
var OP_SEQ = 3;
|
|
5824
|
+
var OP_SEQV = 4;
|
|
5825
|
+
var OP_CHOICE = 5;
|
|
5826
|
+
var OP_REP = 6;
|
|
5827
|
+
var OP_REPV = 7;
|
|
5828
|
+
var OP_OPT = 8;
|
|
5829
|
+
var OP_XFORM = 9;
|
|
5830
|
+
var OP_NODE = 10;
|
|
5831
|
+
var OP_RULE = 11;
|
|
5832
|
+
var OP_GATE = 12;
|
|
5833
|
+
var OP_NOT = 13;
|
|
5834
|
+
var OP_PEEK = 14;
|
|
5835
|
+
var OP_LEAF = 15;
|
|
5836
|
+
var OP_EMPTY = 16;
|
|
5837
|
+
var OP_LIT_TRACK = 17;
|
|
5838
|
+
var OP_RX_TRACK = 18;
|
|
5839
|
+
var OP_NODE_TRACK = 19;
|
|
5840
|
+
var OP_SCOPE = 20;
|
|
5841
|
+
var OP_EXPECT = 21;
|
|
5842
|
+
var OP_SEQX = 22;
|
|
5843
|
+
var OP_SCAN = 23;
|
|
5844
|
+
var OP_FIELD = 24;
|
|
5845
|
+
var OP_LIT_CI = 27;
|
|
5846
|
+
var OP_LIT_CI_TRACK = 28;
|
|
5847
|
+
var OP_TOKEN = 29;
|
|
5848
|
+
var OP_SCOPE_CAP = 30;
|
|
5849
|
+
var OP_WITHCTX = 31;
|
|
5850
|
+
var OP_GUARD = 32;
|
|
5851
|
+
var OP_ADJ = 33;
|
|
5852
|
+
var OP_GREEDY = 34;
|
|
5853
|
+
var OP_REJECT = 35;
|
|
5854
|
+
var OP_ARMGATE = 36;
|
|
5855
|
+
var OP_LIVE = 37;
|
|
5856
|
+
var OP_ATTEMPT = 38;
|
|
5857
|
+
var OP_LABEL = 39;
|
|
5858
|
+
var OP_COV = 40;
|
|
5859
|
+
var OP_SCOPE_PLAIN = 41;
|
|
5860
|
+
var OP_LEX_BODY = 42;
|
|
5861
|
+
var OP_LEX_PROGRAM = 43;
|
|
5862
|
+
var OP_SOURCE_LEAF = 44;
|
|
5863
|
+
var OP_DISPATCH = 25;
|
|
5864
|
+
var OP_ROUTED = 26;
|
|
5865
|
+
var OP_NAMES = {
|
|
5866
|
+
[OP_LIT]: "LIT",
|
|
5867
|
+
[OP_RX]: "RX",
|
|
5868
|
+
[OP_SEQ]: "SEQ",
|
|
5869
|
+
[OP_SEQV]: "SEQV",
|
|
5870
|
+
[OP_CHOICE]: "CHOICE",
|
|
5871
|
+
[OP_REP]: "REP",
|
|
5872
|
+
[OP_REPV]: "REPV",
|
|
5873
|
+
[OP_OPT]: "OPT",
|
|
5874
|
+
[OP_XFORM]: "XFORM",
|
|
5875
|
+
[OP_NODE]: "NODE",
|
|
5876
|
+
[OP_RULE]: "RULE",
|
|
5877
|
+
[OP_GATE]: "GATE",
|
|
5878
|
+
[OP_NOT]: "NOT",
|
|
5879
|
+
[OP_PEEK]: "PEEK",
|
|
5880
|
+
[OP_LEAF]: "LEAF",
|
|
5881
|
+
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
5882
|
+
[OP_EMPTY]: "EMPTY",
|
|
5883
|
+
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
5884
|
+
[OP_RX_TRACK]: "RX_TRACK",
|
|
5885
|
+
[OP_NODE_TRACK]: "NODE_TRACK",
|
|
5886
|
+
[OP_SCOPE]: "SCOPE",
|
|
5887
|
+
[OP_EXPECT]: "EXPECT",
|
|
5888
|
+
[OP_SEQX]: "SEQX",
|
|
5889
|
+
[OP_SCAN]: "SCAN",
|
|
5890
|
+
[OP_FIELD]: "FIELD",
|
|
5891
|
+
[OP_LIT_CI]: "LIT_CI",
|
|
5892
|
+
[OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
|
|
5893
|
+
[OP_DISPATCH]: "DISPATCH",
|
|
5894
|
+
[OP_ROUTED]: "ROUTED",
|
|
5895
|
+
[OP_TOKEN]: "TOKEN",
|
|
5896
|
+
[OP_SCOPE_CAP]: "SCOPE_CAP",
|
|
5897
|
+
[OP_WITHCTX]: "WITHCTX",
|
|
5898
|
+
[OP_GUARD]: "GUARD",
|
|
5899
|
+
[OP_ADJ]: "ADJ",
|
|
5900
|
+
[OP_GREEDY]: "GREEDY",
|
|
5901
|
+
[OP_REJECT]: "REJECT",
|
|
5902
|
+
[OP_ARMGATE]: "ARMGATE",
|
|
5903
|
+
[OP_LIVE]: "LIVE",
|
|
5904
|
+
[OP_ATTEMPT]: "ATTEMPT",
|
|
5905
|
+
[OP_LABEL]: "LABEL",
|
|
5906
|
+
[OP_COV]: "COV",
|
|
5907
|
+
[OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
|
|
5908
|
+
[OP_LEX_BODY]: "LEX_BODY",
|
|
5909
|
+
[OP_LEX_PROGRAM]: "LEX_PROGRAM"
|
|
5910
|
+
};
|
|
5911
|
+
|
|
5912
|
+
// src/combinators/adjacency.ts
|
|
5913
|
+
function adjacencyOf(p) {
|
|
5914
|
+
return p._def.tag === "adjacency" ? p._def : null;
|
|
5837
5915
|
}
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
return { ...prog, asm: [] };
|
|
5916
|
+
function adjacencyExpected(def) {
|
|
5917
|
+
if (def.polarity === "adjacent") return "adjacent";
|
|
5918
|
+
return def.kinds === void 0 ? "notAdjacent" : `notAdjacent(${def.kinds.join("|")})`;
|
|
5842
5919
|
}
|
|
5843
|
-
function
|
|
5844
|
-
|
|
5845
|
-
case "rule":
|
|
5846
|
-
return 0;
|
|
5847
|
-
case "choice-arm":
|
|
5848
|
-
return 1;
|
|
5849
|
-
case "dispatch-arm":
|
|
5850
|
-
return 2;
|
|
5851
|
-
case "label":
|
|
5852
|
-
return 3;
|
|
5853
|
-
}
|
|
5920
|
+
function holdsAdjacency(input, cur, ctx, def) {
|
|
5921
|
+
return adjacencyHolds(input, cur, ctx, def.polarity === "notAdjacent", def.kinds);
|
|
5854
5922
|
}
|
|
5855
|
-
function
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
case 3:
|
|
5864
|
-
return "label";
|
|
5865
|
-
}
|
|
5923
|
+
function adjacencyHolds(input, cur, ctx, negated, kinds) {
|
|
5924
|
+
const end = probeTriviaEnd(input, cur, ctx);
|
|
5925
|
+
if (!negated) return end === cur;
|
|
5926
|
+
if (end === cur) return false;
|
|
5927
|
+
if (kinds === void 0) return true;
|
|
5928
|
+
const want = resolveAdjacencyKindMask(ctx.trivia, kinds);
|
|
5929
|
+
const spec = analyzeLabeledTrivia(ctx.trivia);
|
|
5930
|
+
return (triviaKindMaskAt(input, cur, spec, ctx.state) & want) !== 0;
|
|
5866
5931
|
}
|
|
5867
|
-
function
|
|
5868
|
-
return
|
|
5932
|
+
function adjacencyFail(pos, def) {
|
|
5933
|
+
return { ok: false, expected: [adjacencyExpected(def)], span: { start: pos, end: pos } };
|
|
5869
5934
|
}
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
return
|
|
5873
|
-
code: p.c,
|
|
5874
|
-
k: p.k,
|
|
5875
|
-
cc: p.x,
|
|
5876
|
-
fx: p.e,
|
|
5877
|
-
disp: p.d,
|
|
5878
|
-
rules: p.r,
|
|
5879
|
-
fns: p.f,
|
|
5880
|
-
lines: p.l ?? 0,
|
|
5881
|
-
dsp: p.p ?? [],
|
|
5882
|
-
...p.lx === void 0 ? {} : { lex: p.lx },
|
|
5883
|
-
...p.lp === void 0 ? {} : { lexPrograms: p.lp },
|
|
5884
|
-
...p.lb === void 0 ? {} : { labels: p.lb },
|
|
5885
|
-
...p.rc === void 0 ? {} : { classified: p.rc },
|
|
5886
|
-
...p.h === void 0 ? {} : { hostMode: p.h },
|
|
5887
|
-
...p.tv === void 0 ? {} : { triviaSpecs: p.tv },
|
|
5888
|
-
...p.sc === void 0 ? {} : { scans: p.sc },
|
|
5889
|
-
...p.ss === void 0 ? {} : { scanSkip: p.ss },
|
|
5890
|
-
...p.so === void 0 ? {} : { scanSkipOf: p.so },
|
|
5891
|
-
...p.rv === void 0 ? {} : { rec: p.rv },
|
|
5892
|
-
...p.cv === void 0 ? {} : { cov: p.cv },
|
|
5893
|
-
...p.a === void 0 ? {} : { asm: p.a }
|
|
5894
|
-
});
|
|
5935
|
+
var NO_STANDALONE_PARSE = "adjacency assertions are boundary tests: use adjacent()/notAdjacent() as a NON-FIRST term of a sequence(), where the preceding term defines the gap being asserted.";
|
|
5936
|
+
function adjacencyMisuse(polarity) {
|
|
5937
|
+
return new TypeError(`${polarity}(): ${NO_STANDALONE_PARSE}`);
|
|
5895
5938
|
}
|
|
5896
|
-
function
|
|
5897
|
-
const
|
|
5898
|
-
|
|
5899
|
-
|
|
5939
|
+
function adjacencyCombinator(def) {
|
|
5940
|
+
const meta = {
|
|
5941
|
+
// Zero-width and never leading (sequence() rejects index 0), so it contributes
|
|
5942
|
+
// no first char. `isZeroWidthAssertion` drops it from a sequence's first-set
|
|
5943
|
+
// rather than letting `any` poison the enclosing choice's dispatch.
|
|
5944
|
+
firstSet: { kind: "any" },
|
|
5945
|
+
canMatchNewline: false,
|
|
5946
|
+
isTrivia: false
|
|
5900
5947
|
};
|
|
5901
|
-
if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
|
|
5902
|
-
throw new TypeError("table: malformed dispatch");
|
|
5903
|
-
}
|
|
5904
|
-
}
|
|
5905
|
-
var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
|
|
5906
|
-
function ownTableProgram(prog, resolved, caches = {}) {
|
|
5907
|
-
const runtime = prog[TABLE_RUNTIME];
|
|
5908
5948
|
return {
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
|
|
5949
|
+
_tag: "adjacency",
|
|
5950
|
+
_meta: meta,
|
|
5951
|
+
_def: def,
|
|
5952
|
+
parse() {
|
|
5953
|
+
throw adjacencyMisuse(def.polarity);
|
|
5915
5954
|
}
|
|
5916
5955
|
};
|
|
5917
5956
|
}
|
|
5918
|
-
function
|
|
5919
|
-
return
|
|
5920
|
-
}
|
|
5921
|
-
function choiceCannotCommit(prog, ip) {
|
|
5922
|
-
return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
|
|
5923
|
-
}
|
|
5924
|
-
function failureRollbackClean(prog, ip) {
|
|
5925
|
-
return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
|
|
5926
|
-
}
|
|
5927
|
-
var WIDE_CLASS_PREFIX_LO = 65535;
|
|
5928
|
-
var WIDE_CLASS_PREFIX_HI = 0;
|
|
5929
|
-
function validateClassRange(lo, hi) {
|
|
5930
|
-
for (const cp of [lo, hi]) {
|
|
5931
|
-
if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) {
|
|
5932
|
-
throw new TypeError(`table char-class endpoint is outside Unicode: ${cp}`);
|
|
5933
|
-
}
|
|
5934
|
-
}
|
|
5935
|
-
if (lo > hi) {
|
|
5936
|
-
throw new TypeError(`table char-class range is descending: ${lo} > ${hi}`);
|
|
5937
|
-
}
|
|
5938
|
-
}
|
|
5939
|
-
function encodeClassSpec(ranges) {
|
|
5940
|
-
let wide = false;
|
|
5941
|
-
for (const range of ranges) {
|
|
5942
|
-
validateClassRange(range.lo, range.hi);
|
|
5943
|
-
if (range.hi > 65535) wide = true;
|
|
5944
|
-
}
|
|
5945
|
-
if (!wide) {
|
|
5946
|
-
let spec2 = "";
|
|
5947
|
-
for (const range of ranges) spec2 += String.fromCharCode(range.lo, range.hi);
|
|
5948
|
-
return spec2;
|
|
5949
|
-
}
|
|
5950
|
-
let spec = String.fromCharCode(WIDE_CLASS_PREFIX_LO, WIDE_CLASS_PREFIX_HI);
|
|
5951
|
-
for (const range of ranges) {
|
|
5952
|
-
spec += String.fromCharCode(
|
|
5953
|
-
range.lo >>> 16,
|
|
5954
|
-
range.lo & 65535,
|
|
5955
|
-
range.hi >>> 16,
|
|
5956
|
-
range.hi & 65535
|
|
5957
|
-
);
|
|
5958
|
-
}
|
|
5959
|
-
return spec;
|
|
5960
|
-
}
|
|
5961
|
-
function decodeClassSpec(spec) {
|
|
5962
|
-
if (spec.charCodeAt(0) === WIDE_CLASS_PREFIX_LO && spec.charCodeAt(1) === WIDE_CLASS_PREFIX_HI) {
|
|
5963
|
-
if ((spec.length - 2) % 4 !== 0) throw new TypeError("table char-class spec has a truncated wide range");
|
|
5964
|
-
if (spec.length === 2) throw new TypeError("table char-class spec has a wide prefix but no ranges");
|
|
5965
|
-
const ranges2 = [];
|
|
5966
|
-
for (let i = 2; i < spec.length; i += 4) {
|
|
5967
|
-
const lo = spec.charCodeAt(i) * 65536 + spec.charCodeAt(i + 1);
|
|
5968
|
-
const hi = spec.charCodeAt(i + 2) * 65536 + spec.charCodeAt(i + 3);
|
|
5969
|
-
validateClassRange(lo, hi);
|
|
5970
|
-
ranges2.push({ lo, hi });
|
|
5971
|
-
}
|
|
5972
|
-
return ranges2;
|
|
5973
|
-
}
|
|
5974
|
-
if (spec.length % 2 !== 0) throw new TypeError("table char-class spec has an unmatched range endpoint");
|
|
5975
|
-
const ranges = [];
|
|
5976
|
-
for (let i = 0; i < spec.length; i += 2) {
|
|
5977
|
-
const lo = spec.charCodeAt(i);
|
|
5978
|
-
const hi = spec.charCodeAt(i + 1);
|
|
5979
|
-
validateClassRange(lo, hi);
|
|
5980
|
-
ranges.push({ lo, hi });
|
|
5981
|
-
}
|
|
5982
|
-
return ranges;
|
|
5983
|
-
}
|
|
5984
|
-
function resolveClass(spec) {
|
|
5985
|
-
const ascii = new Uint8Array(128);
|
|
5986
|
-
const hi = [];
|
|
5987
|
-
for (const { lo, hi: up } of decodeClassSpec(spec)) {
|
|
5988
|
-
if (lo < 128) for (let c = lo; c <= Math.min(up, 127); c++) ascii[c] = 1;
|
|
5989
|
-
if (up >= 128) hi.push(Math.max(lo, 128), up);
|
|
5990
|
-
}
|
|
5991
|
-
return { ascii, hi };
|
|
5992
|
-
}
|
|
5993
|
-
function classHas2(cls, code) {
|
|
5994
|
-
if (code < 0) return false;
|
|
5995
|
-
if (code < 128) return cls.ascii[code] === 1;
|
|
5996
|
-
const hi = cls.hi;
|
|
5997
|
-
for (let i = 0; i < hi.length; i += 2) if (code >= hi[i] && code <= hi[i + 1]) return true;
|
|
5998
|
-
return false;
|
|
5957
|
+
function adjacent() {
|
|
5958
|
+
return adjacencyCombinator({ tag: "adjacency", polarity: "adjacent" });
|
|
5999
5959
|
}
|
|
6000
|
-
function
|
|
6001
|
-
const
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
let exclusive = true;
|
|
6006
|
-
let hiOwners = 0;
|
|
6007
|
-
for (let a = 0; a < arms.length; a++) {
|
|
6008
|
-
const ci = arms[a];
|
|
6009
|
-
if (ci < 0) {
|
|
6010
|
-
open.push(a);
|
|
6011
|
-
armCls.push(null);
|
|
6012
|
-
exclusive = false;
|
|
6013
|
-
continue;
|
|
5960
|
+
function notAdjacent(options) {
|
|
5961
|
+
const kinds = options?.kinds;
|
|
5962
|
+
if (kinds !== void 0) {
|
|
5963
|
+
if (!Array.isArray(kinds) || kinds.length === 0) {
|
|
5964
|
+
throw new TypeError("notAdjacent({ kinds }): kinds must be a non-empty array of trivia category names.");
|
|
6014
5965
|
}
|
|
6015
|
-
const
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
if (ascii[c] === 0) ascii[c] = a + 1;
|
|
6020
|
-
else exclusive = false;
|
|
5966
|
+
for (const k of kinds) {
|
|
5967
|
+
if (typeof k !== "string" || k.length === 0) {
|
|
5968
|
+
throw new TypeError(`notAdjacent({ kinds }): every kind must be a non-empty string, got ${JSON.stringify(k)}.`);
|
|
5969
|
+
}
|
|
6021
5970
|
}
|
|
6022
|
-
if (cls.hi.length > 0 && ++hiOwners > 1) exclusive = false;
|
|
6023
|
-
for (let i = 0; i < cls.hi.length; i += 2) hi.push(cls.hi[i], cls.hi[i + 1], a);
|
|
6024
5971
|
}
|
|
6025
|
-
return
|
|
5972
|
+
return adjacencyCombinator(
|
|
5973
|
+
kinds === void 0 ? { tag: "adjacency", polarity: "notAdjacent" } : { tag: "adjacency", polarity: "notAdjacent", kinds: [...kinds] }
|
|
5974
|
+
);
|
|
6026
5975
|
}
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
5976
|
+
|
|
5977
|
+
// src/combinators/node.ts
|
|
5978
|
+
function unwrapChild(child) {
|
|
5979
|
+
return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
|
|
5980
|
+
}
|
|
5981
|
+
function isCstChild(value) {
|
|
5982
|
+
return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "parseError");
|
|
5983
|
+
}
|
|
5984
|
+
function missingInferredType() {
|
|
5985
|
+
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
5986
|
+
}
|
|
5987
|
+
function normalizeBuildArity(arity) {
|
|
5988
|
+
if (arity === void 0) return void 0;
|
|
5989
|
+
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
5990
|
+
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
6035
5991
|
}
|
|
6036
|
-
|
|
6037
|
-
for (const [name, source, flags] of spec.arms) arms[name] = regex(new RegExp(source, flags));
|
|
6038
|
-
return classifiedTrivia(arms);
|
|
5992
|
+
return arity;
|
|
6039
5993
|
}
|
|
6040
|
-
function
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
5994
|
+
function normalizeProject(project) {
|
|
5995
|
+
if (project === void 0) return void 0;
|
|
5996
|
+
if (!Number.isInteger(project) || project < 0) {
|
|
5997
|
+
throw new Error("node() project child must be a non-negative integer");
|
|
5998
|
+
}
|
|
5999
|
+
return project;
|
|
6000
|
+
}
|
|
6001
|
+
function projectChild(children2, project, type) {
|
|
6002
|
+
if (!(project in children2)) {
|
|
6003
|
+
throw new Error(`node(${JSON.stringify(type)}) project child ${project} was not captured`);
|
|
6004
|
+
}
|
|
6005
|
+
return unwrapChild(children2[project]);
|
|
6006
|
+
}
|
|
6007
|
+
function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
6008
|
+
const hasExplicitType = typeof typeOrCombinator === "string";
|
|
6009
|
+
const type = hasExplicitType ? typeOrCombinator : void 0;
|
|
6010
|
+
const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
|
|
6011
|
+
const buildArg = hasExplicitType ? buildOrOpts : combinatorOrBuild;
|
|
6012
|
+
const build = typeof buildArg === "function" ? buildArg : void 0;
|
|
6013
|
+
const opts = typeof buildArg === "function" ? maybeOpts : buildArg ?? maybeOpts;
|
|
6014
|
+
const project = normalizeProject(opts?.project);
|
|
6015
|
+
if (project !== void 0 && build !== void 0) {
|
|
6016
|
+
throw new Error("node() options cannot combine project with a build callback");
|
|
6017
|
+
}
|
|
6018
|
+
const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
|
|
6019
|
+
const meta = {
|
|
6020
|
+
firstSet: combinator._meta.firstSet,
|
|
6021
|
+
canMatchNewline: combinator._meta.canMatchNewline,
|
|
6022
|
+
isTrivia: false
|
|
6068
6023
|
};
|
|
6069
|
-
|
|
6070
|
-
|
|
6024
|
+
const unwrap = opts?.unwrap === true;
|
|
6025
|
+
const collapse = opts?.collapse === true;
|
|
6026
|
+
const captureTrivia = opts?.captureTrivia === true;
|
|
6027
|
+
const trailingTrivia = opts?.trailingTrivia === true;
|
|
6028
|
+
const tags = opts?.tags;
|
|
6029
|
+
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
6030
|
+
if (unwrap && collapse) {
|
|
6031
|
+
throw new Error("node() options cannot set both unwrap and collapse");
|
|
6032
|
+
}
|
|
6033
|
+
if (project !== void 0 && (unwrap || collapse)) {
|
|
6034
|
+
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
6035
|
+
}
|
|
6036
|
+
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || buildArity !== void 0 || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...buildArity !== void 0 ? { buildArity } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
6037
|
+
const capturesTrivia = captureTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
6038
|
+
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
6039
|
+
const hasOwnFields = parserHasOwnFields(combinator);
|
|
6040
|
+
const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
|
|
6041
|
+
const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
|
|
6042
|
+
let failExpected;
|
|
6043
|
+
return {
|
|
6044
|
+
_tag: "node",
|
|
6045
|
+
_meta: meta,
|
|
6046
|
+
_def: def,
|
|
6047
|
+
parse(input, pos, ctx) {
|
|
6048
|
+
if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
|
|
6049
|
+
if (failExpected === void 0) {
|
|
6050
|
+
const e = deriveExpected(combinator);
|
|
6051
|
+
failExpected = e.length > 0 ? e : [combinator._tag];
|
|
6052
|
+
}
|
|
6053
|
+
return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
|
|
6054
|
+
}
|
|
6055
|
+
const hasDirectValue = build !== void 0 || project !== void 0;
|
|
6056
|
+
const hostCst = hasDirectValue && cstOutputHost(ctx.build);
|
|
6057
|
+
const structural = !hasDirectValue;
|
|
6058
|
+
const hostCapturesThisType = structural && def.type !== void 0 && ctx.build?._parsemanCaptureTrivia !== void 0 ? ctx.build._parsemanCaptureTrivia(def.type) : void 0;
|
|
6059
|
+
const effTrivia = structural ? captureTrivia || trailingTrivia || hostCapturesThisType !== false : capturesTrivia || hostCst;
|
|
6060
|
+
const effFields = capturesFields || hostCst && hasOwnFields;
|
|
6061
|
+
const saved = beginCstNodeCapture(ctx);
|
|
6062
|
+
const savedFields = ctx._fields;
|
|
6063
|
+
ctx._fields = effFields ? [] : void 0;
|
|
6064
|
+
const savedMask = ctx._triviaCaptureMask;
|
|
6065
|
+
if (build === void 0 && project === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
|
|
6066
|
+
ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
|
|
6067
|
+
}
|
|
6068
|
+
if (!effTrivia) ctx.captureTrivia = false;
|
|
6069
|
+
let r = combinator.parse(input, pos, ctx);
|
|
6070
|
+
if (r.ok && trailingTrivia && ctx.trivia) {
|
|
6071
|
+
const end = consumeTrivia(input, r.span.end, ctx);
|
|
6072
|
+
r = { ...r, span: { start: r.span.start, end } };
|
|
6073
|
+
}
|
|
6074
|
+
const fields = effFields ? buildFieldMap(ctx._fields) : void 0;
|
|
6075
|
+
ctx._fields = savedFields;
|
|
6076
|
+
ctx._triviaCaptureMask = savedMask;
|
|
6077
|
+
const { children: children2, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
|
|
6078
|
+
if (!r.ok) return r;
|
|
6079
|
+
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
6080
|
+
const nodeType = def.type ?? missingInferredType();
|
|
6081
|
+
const cstOutput = cstOutputHost(ctx.build);
|
|
6082
|
+
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
6083
|
+
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
6084
|
+
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, hostState, tags) : build(children2, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
|
|
6085
|
+
const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
6086
|
+
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
6087
|
+
pushCstChild(ctx, built, rawEntry2);
|
|
6088
|
+
}
|
|
6089
|
+
return { ok: true, value: built, span };
|
|
6090
|
+
}
|
|
6091
|
+
};
|
|
6092
|
+
}
|
|
6093
|
+
|
|
6094
|
+
// src/combinators/trivia-boundary.ts
|
|
6095
|
+
var MAX_DEPTH = 12;
|
|
6096
|
+
function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
|
|
6097
|
+
if (depth === 0) return true;
|
|
6098
|
+
const d = p._def;
|
|
6099
|
+
switch (d.tag) {
|
|
6100
|
+
// Multi-term forms: the gaps BETWEEN terms are the ambient-trivia positions.
|
|
6101
|
+
case "sequence":
|
|
6102
|
+
return d.parsers.length > 1;
|
|
6103
|
+
case "many":
|
|
6104
|
+
case "oneOrMore":
|
|
6105
|
+
case "sepBy":
|
|
6106
|
+
return true;
|
|
6107
|
+
// Transparent wrappers — they add no position, so ask what they wrap.
|
|
6108
|
+
case "node":
|
|
6109
|
+
case "transform":
|
|
6110
|
+
case "leaf":
|
|
6111
|
+
case "label":
|
|
6112
|
+
case "field":
|
|
6113
|
+
case "token":
|
|
6114
|
+
case "attempt":
|
|
6115
|
+
case "optional":
|
|
6116
|
+
case "expect":
|
|
6117
|
+
case "withCtx":
|
|
6118
|
+
case "recover":
|
|
6119
|
+
case "trivia":
|
|
6120
|
+
return hasOwnTriviaBoundary(d.parser, depth - 1);
|
|
6121
|
+
// An alternation adds no position either, but ONE arm that has one is enough
|
|
6122
|
+
// to make the scope meaningful for this rule.
|
|
6123
|
+
case "choice":
|
|
6124
|
+
return d.parsers.some((a) => hasOwnTriviaBoundary(a, depth - 1));
|
|
6125
|
+
default:
|
|
6126
|
+
return false;
|
|
6127
|
+
}
|
|
6071
6128
|
}
|
|
6072
6129
|
|
|
6073
6130
|
// src/compiler/direct-projection.ts
|
|
@@ -6618,6 +6675,7 @@ var Encoder = class {
|
|
|
6618
6675
|
case "expect":
|
|
6619
6676
|
case "recover":
|
|
6620
6677
|
case "scanTo":
|
|
6678
|
+
case "lines":
|
|
6621
6679
|
case "unknown":
|
|
6622
6680
|
return true;
|
|
6623
6681
|
case "lazy": {
|
|
@@ -6838,6 +6896,18 @@ var Encoder = class {
|
|
|
6838
6896
|
open: bal.open,
|
|
6839
6897
|
close: bal.close
|
|
6840
6898
|
}));
|
|
6899
|
+
if (d.tag === "lines") {
|
|
6900
|
+
return this.emit(OP_SCAN, this.scanSlot({
|
|
6901
|
+
kind: 2,
|
|
6902
|
+
flags: 0,
|
|
6903
|
+
skip: [],
|
|
6904
|
+
prefix: this.subtree(d.prefix),
|
|
6905
|
+
body: this.subtree(d.body),
|
|
6906
|
+
...d.first === void 0 ? {} : { first: this.subtree(d.first) },
|
|
6907
|
+
...d.lazy === void 0 ? {} : { lazy: this.subtree(d.lazy) }
|
|
6908
|
+
}));
|
|
6909
|
+
}
|
|
6910
|
+
if (d.tag === "columns") return this.emit(OP_SCAN, this.scanSlot({ kind: 3, flags: 0, skip: [], n: d.n }));
|
|
6841
6911
|
if (d.tag === "scanTo") {
|
|
6842
6912
|
const sentDef = d.sentinel._def;
|
|
6843
6913
|
return this.emit(OP_SCAN, this.scanSlot({
|
|
@@ -7284,12 +7354,7 @@ var Encoder = class {
|
|
|
7284
7354
|
};
|
|
7285
7355
|
const seen = /* @__PURE__ */ new Set();
|
|
7286
7356
|
const refs = [];
|
|
7287
|
-
for (const s of this.scans)
|
|
7288
|
-
if (s.sentinel !== void 0) refs.push(s.sentinel);
|
|
7289
|
-
if (s.recoverAt !== void 0) refs.push(s.recoverAt);
|
|
7290
|
-
if (s.stopAt !== void 0) refs.push(s.stopAt);
|
|
7291
|
-
refs.push(...s.skip);
|
|
7292
|
-
}
|
|
7357
|
+
for (const s of this.scans) refs.push(...scanRefs(s));
|
|
7293
7358
|
for (const set of this.scanSkipSets) refs.push(...set);
|
|
7294
7359
|
const stack = [...Object.values(this.rules), ...refs.map((r) => r[0])];
|
|
7295
7360
|
while (stack.length > 0) {
|
|
@@ -7309,7 +7374,11 @@ var Encoder = class {
|
|
|
7309
7374
|
skip: s.skip.map(res),
|
|
7310
7375
|
...s.sentinel === void 0 ? {} : { sentinel: res(s.sentinel) },
|
|
7311
7376
|
...s.recoverAt === void 0 ? {} : { recoverAt: res(s.recoverAt) },
|
|
7312
|
-
...s.stopAt === void 0 ? {} : { stopAt: res(s.stopAt) }
|
|
7377
|
+
...s.stopAt === void 0 ? {} : { stopAt: res(s.stopAt) },
|
|
7378
|
+
...s.prefix === void 0 ? {} : { prefix: res(s.prefix) },
|
|
7379
|
+
...s.body === void 0 ? {} : { body: res(s.body) },
|
|
7380
|
+
...s.first === void 0 ? {} : { first: res(s.first) },
|
|
7381
|
+
...s.lazy === void 0 ? {} : { lazy: res(s.lazy) }
|
|
7313
7382
|
}));
|
|
7314
7383
|
this.scanSkipSets = this.scanSkipSets.map((set) => set.map(res));
|
|
7315
7384
|
}
|
|
@@ -8151,7 +8220,7 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8151
8220
|
if (shape.kind === "alt") {
|
|
8152
8221
|
const okV = mint("_ok");
|
|
8153
8222
|
const endV2 = mint("_end");
|
|
8154
|
-
const
|
|
8223
|
+
const lines2 = [`${ind}let ${okV} = false`, `${ind}let ${endV2} = ${start}`];
|
|
8155
8224
|
if (shape.arms.length >= 2 && shape.arms.every((a) => a.kind === "litFold" && a.open.length >= 1)) {
|
|
8156
8225
|
const groups = /* @__PURE__ */ new Map();
|
|
8157
8226
|
for (const a of shape.arms) {
|
|
@@ -8160,60 +8229,60 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8160
8229
|
const lower = f >= 65 && f <= 90 ? f + 32 : f;
|
|
8161
8230
|
(groups.get(lower) ?? groups.set(lower, []).get(lower)).push(open);
|
|
8162
8231
|
}
|
|
8163
|
-
|
|
8232
|
+
lines2.push(`${ind}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
8164
8233
|
for (const [lower, arms] of groups) {
|
|
8165
8234
|
const labels = lower >= 97 && lower <= 122 ? `case ${lower}: case ${lower - 32}:` : `case ${lower}:`;
|
|
8166
|
-
|
|
8235
|
+
lines2.push(`${ind} ${labels} {`);
|
|
8167
8236
|
for (const open of arms) {
|
|
8168
8237
|
const tail = open.slice(1).map((cp, i) => foldEq(`input.charCodeAt(${start} + ${i + 1})`, cp));
|
|
8169
8238
|
const cond = tail.length ? ` && ${tail.join(" && ")}` : "";
|
|
8170
|
-
|
|
8239
|
+
lines2.push(`${ind} if (${start} + ${open.length} <= input.length${cond}) { ${okV} = true; ${endV2} = ${start} + ${open.length}; break }`);
|
|
8171
8240
|
}
|
|
8172
|
-
|
|
8173
|
-
|
|
8241
|
+
lines2.push(`${ind} break`);
|
|
8242
|
+
lines2.push(`${ind} }`);
|
|
8174
8243
|
}
|
|
8175
|
-
|
|
8176
|
-
return { setup:
|
|
8244
|
+
lines2.push(`${ind}}`);
|
|
8245
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
8177
8246
|
}
|
|
8178
8247
|
if (shape.disjoint) {
|
|
8179
8248
|
const plan = planAltSwitch(shape.firsts);
|
|
8180
8249
|
if (plan.kind === "switch") {
|
|
8181
|
-
|
|
8250
|
+
lines2.push(`${ind}if (${start} < input.length) switch (${codeAt(start, firstChar)}) {`);
|
|
8182
8251
|
shape.arms.forEach((arm, k) => {
|
|
8183
8252
|
const labels = plan.cases[k].map((cp) => `case ${cp}:`).join(" ");
|
|
8184
8253
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8254
|
+
lines2.push(`${ind} ${labels} {`);
|
|
8255
|
+
lines2.push(...m.setup);
|
|
8256
|
+
lines2.push(`${ind} ${okV} = ${m.ok}`);
|
|
8257
|
+
lines2.push(`${ind} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
8258
|
+
lines2.push(`${ind} break`);
|
|
8259
|
+
lines2.push(`${ind} }`);
|
|
8191
8260
|
});
|
|
8192
|
-
|
|
8261
|
+
lines2.push(`${ind}}`);
|
|
8193
8262
|
} else {
|
|
8194
8263
|
const c0 = codeAt(start, firstChar);
|
|
8195
8264
|
shape.arms.forEach((arm, k) => {
|
|
8196
8265
|
const fs = shape.firsts[k];
|
|
8197
8266
|
const cond = fs.negated ? `!(${classCond(c0, fs.ranges)})` : `(${classCond(c0, fs.ranges)})`;
|
|
8198
8267
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8268
|
+
lines2.push(`${ind}${k === 0 ? "if" : "else if"} (${start} < input.length && ${cond}) {`);
|
|
8269
|
+
lines2.push(...m.setup);
|
|
8270
|
+
lines2.push(`${ind} ${okV} = ${m.ok}`);
|
|
8271
|
+
lines2.push(`${ind} ${endV2} = ${m.ok} ? ${m.end} : ${start}`);
|
|
8272
|
+
lines2.push(`${ind}}`);
|
|
8204
8273
|
});
|
|
8205
8274
|
}
|
|
8206
8275
|
} else {
|
|
8207
8276
|
const lbl = mint("_alt");
|
|
8208
|
-
|
|
8277
|
+
lines2.push(`${ind}${lbl}: {`);
|
|
8209
8278
|
for (const arm of shape.arms) {
|
|
8210
8279
|
const m = emitShapeMatch(arm, start, mint, `${ind} `, firstChar);
|
|
8211
|
-
|
|
8212
|
-
|
|
8280
|
+
lines2.push(...m.setup);
|
|
8281
|
+
lines2.push(`${ind} if (${m.ok}) { ${okV} = true; ${endV2} = ${m.end}; break ${lbl} }`);
|
|
8213
8282
|
}
|
|
8214
|
-
|
|
8283
|
+
lines2.push(`${ind}}`);
|
|
8215
8284
|
}
|
|
8216
|
-
return { setup:
|
|
8285
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
8217
8286
|
}
|
|
8218
8287
|
if (shape.kind === "chars") {
|
|
8219
8288
|
const cur = mint("_e");
|
|
@@ -8248,64 +8317,64 @@ function emitShapeMatch(shape, start, mint, ind, firstChar) {
|
|
|
8248
8317
|
const c = classCond(`input.charCodeAt(${at})`, p.ranges);
|
|
8249
8318
|
return p.negated ? `!(${c})` : `(${c})`;
|
|
8250
8319
|
};
|
|
8251
|
-
const
|
|
8320
|
+
const lines2 = [`${ind}let ${endV2} = ${start}`, `${ind}let ${okV} = false`, `${ind}do {`];
|
|
8252
8321
|
let first = true;
|
|
8253
8322
|
for (const p of shape.parts) {
|
|
8254
8323
|
if (p.part === "lit") {
|
|
8255
8324
|
const L = p.cps.length;
|
|
8256
8325
|
const cond = litCond(endV2, p.cps, first ? firstChar : void 0);
|
|
8257
8326
|
if (p.optional) {
|
|
8258
|
-
|
|
8327
|
+
lines2.push(`${ind} if (${endV2} + ${L} <= input.length && (${cond})) ${endV2} += ${L}`);
|
|
8259
8328
|
} else {
|
|
8260
|
-
|
|
8261
|
-
|
|
8329
|
+
lines2.push(`${ind} if (!(${endV2} + ${L} <= input.length && (${cond}))) break`);
|
|
8330
|
+
lines2.push(`${ind} ${endV2} += ${L}`);
|
|
8262
8331
|
}
|
|
8263
8332
|
} else if (p.part === "run" && p.max === Infinity) {
|
|
8264
8333
|
const s = mint("_s");
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
if (p.min === 1)
|
|
8268
|
-
else if (p.min > 1)
|
|
8334
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
8335
|
+
lines2.push(`${ind} while (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
8336
|
+
if (p.min === 1) lines2.push(`${ind} if (${endV2} === ${s}) break`);
|
|
8337
|
+
else if (p.min > 1) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
8269
8338
|
} else if (p.part === "run" && p.max === 1) {
|
|
8270
8339
|
if (p.min === 1) {
|
|
8271
|
-
|
|
8272
|
-
|
|
8340
|
+
lines2.push(`${ind} if (!(${endV2} < input.length && ${runCond(p, endV2)})) break`);
|
|
8341
|
+
lines2.push(`${ind} ${endV2}++`);
|
|
8273
8342
|
} else {
|
|
8274
|
-
|
|
8343
|
+
lines2.push(`${ind} if (${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
8275
8344
|
}
|
|
8276
8345
|
} else if (p.part === "run") {
|
|
8277
8346
|
const s = mint("_s");
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
if (p.min > 0)
|
|
8347
|
+
lines2.push(`${ind} const ${s} = ${endV2}`);
|
|
8348
|
+
lines2.push(`${ind} while (${endV2} - ${s} < ${p.max} && ${endV2} < input.length && ${runCond(p, endV2)}) ${endV2}++`);
|
|
8349
|
+
if (p.min > 0) lines2.push(`${ind} if (${endV2} - ${s} < ${p.min}) break`);
|
|
8281
8350
|
} else {
|
|
8282
8351
|
const inner = emitShapeMatch(p.inner, endV2, mint, `${ind} `, first ? firstChar : void 0);
|
|
8283
8352
|
if (!p.unbounded) {
|
|
8284
|
-
|
|
8353
|
+
lines2.push(...inner.setup);
|
|
8285
8354
|
if (p.min === 1) {
|
|
8286
|
-
|
|
8287
|
-
|
|
8355
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
8356
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
8288
8357
|
} else {
|
|
8289
|
-
|
|
8358
|
+
lines2.push(`${ind} if (${inner.ok}) ${endV2} = ${inner.end}`);
|
|
8290
8359
|
}
|
|
8291
8360
|
} else {
|
|
8292
8361
|
const progV = mint("_prog");
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
if (p.min === 1)
|
|
8362
|
+
lines2.push(`${ind} let ${progV} = false`);
|
|
8363
|
+
lines2.push(`${ind} while (true) {`);
|
|
8364
|
+
lines2.push(...inner.setup);
|
|
8365
|
+
lines2.push(`${ind} if (!(${inner.ok})) break`);
|
|
8366
|
+
lines2.push(`${ind} ${endV2} = ${inner.end}`);
|
|
8367
|
+
lines2.push(`${ind} ${progV} = true`);
|
|
8368
|
+
lines2.push(`${ind} }`);
|
|
8369
|
+
if (p.min === 1) lines2.push(`${ind} if (!${progV}) break`);
|
|
8301
8370
|
}
|
|
8302
8371
|
}
|
|
8303
8372
|
first = false;
|
|
8304
8373
|
}
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
return { setup:
|
|
8374
|
+
lines2.push(`${ind} ${okV} = true`);
|
|
8375
|
+
lines2.push(`${ind}} while (false)`);
|
|
8376
|
+
lines2.push(`${ind}if (!${okV}) ${endV2} = ${start}`);
|
|
8377
|
+
return { setup: lines2, ok: okV, end: endV2 };
|
|
8309
8378
|
}
|
|
8310
8379
|
if (shape.kind === "litFold") {
|
|
8311
8380
|
const openLen2 = shape.open.length;
|
|
@@ -10582,6 +10651,188 @@ finish:_finish
|
|
|
10582
10651
|
};
|
|
10583
10652
|
}
|
|
10584
10653
|
|
|
10654
|
+
// src/combinators/lines.ts
|
|
10655
|
+
function lineIndexAt(view, offset) {
|
|
10656
|
+
const lines2 = view.lines;
|
|
10657
|
+
let lo = 0, hi = lines2.length - 1;
|
|
10658
|
+
while (lo < hi) {
|
|
10659
|
+
const mid = lo + hi + 1 >> 1;
|
|
10660
|
+
if (lines2[mid].offset <= offset) lo = mid;
|
|
10661
|
+
else hi = mid - 1;
|
|
10662
|
+
}
|
|
10663
|
+
return lo;
|
|
10664
|
+
}
|
|
10665
|
+
var lineAt = (view, offset) => view.lines[lineIndexAt(view, offset)];
|
|
10666
|
+
function sourceOffset(view, offset) {
|
|
10667
|
+
const line = lineAt(view, offset);
|
|
10668
|
+
return line === void 0 ? offset : line.source + (offset - line.offset);
|
|
10669
|
+
}
|
|
10670
|
+
function columnAt(input, pos, ctx) {
|
|
10671
|
+
const view = ctx.lineView;
|
|
10672
|
+
let start, column, split;
|
|
10673
|
+
const line = view === void 0 ? void 0 : lineAt(view, pos);
|
|
10674
|
+
if (line !== void 0 && pos >= line.offset) {
|
|
10675
|
+
start = line.offset;
|
|
10676
|
+
column = line.column;
|
|
10677
|
+
split = line.split;
|
|
10678
|
+
} else {
|
|
10679
|
+
start = input.lastIndexOf("\n", pos - 1) + 1;
|
|
10680
|
+
column = 0;
|
|
10681
|
+
split = 0;
|
|
10682
|
+
}
|
|
10683
|
+
for (let i = start; i < pos; i++) {
|
|
10684
|
+
if (input.charCodeAt(i) === 9) {
|
|
10685
|
+
const width = 4 - (column - (i === start ? split : 0)) % 4 - (i === start ? split : 0);
|
|
10686
|
+
column += width;
|
|
10687
|
+
} else column++;
|
|
10688
|
+
split = 0;
|
|
10689
|
+
}
|
|
10690
|
+
return { column, split: pos === start ? split : 0 };
|
|
10691
|
+
}
|
|
10692
|
+
function columns(n) {
|
|
10693
|
+
if (!Number.isInteger(n) || n < 0) throw new TypeError(`columns(n) needs a non-negative integer, got ${n}`);
|
|
10694
|
+
const expected = [`columns(${n})`];
|
|
10695
|
+
const meta = {
|
|
10696
|
+
firstSet: n === 0 ? any() : { kind: "ranges", ranges: [{ lo: 9, hi: 9 }, { lo: 32, hi: 32 }] },
|
|
10697
|
+
canMatchNewline: false,
|
|
10698
|
+
isTrivia: false
|
|
10699
|
+
};
|
|
10700
|
+
return {
|
|
10701
|
+
_tag: "columns",
|
|
10702
|
+
_meta: meta,
|
|
10703
|
+
_def: { tag: "columns", n },
|
|
10704
|
+
parse(input, pos, ctx) {
|
|
10705
|
+
const c = ctx;
|
|
10706
|
+
let { column, split } = columnAt(input, pos, c);
|
|
10707
|
+
const goal = column + n;
|
|
10708
|
+
let at = pos;
|
|
10709
|
+
while (column < goal) {
|
|
10710
|
+
const code = input.charCodeAt(at);
|
|
10711
|
+
if (code === 32) {
|
|
10712
|
+
column++;
|
|
10713
|
+
split = 0;
|
|
10714
|
+
at++;
|
|
10715
|
+
continue;
|
|
10716
|
+
}
|
|
10717
|
+
if (code !== 9) return { ok: false, expected, span: { start: at, end: at } };
|
|
10718
|
+
const width = 4 - (column - split) % 4 - split;
|
|
10719
|
+
if (column + width > goal) {
|
|
10720
|
+
c._columnsSplit = { at, split: split + (goal - column) };
|
|
10721
|
+
return { ok: true, value: input.slice(pos, at), span: { start: pos, end: at } };
|
|
10722
|
+
}
|
|
10723
|
+
column += width;
|
|
10724
|
+
split = 0;
|
|
10725
|
+
at++;
|
|
10726
|
+
}
|
|
10727
|
+
return { ok: true, value: input.slice(pos, at), span: { start: pos, end: at } };
|
|
10728
|
+
}
|
|
10729
|
+
};
|
|
10730
|
+
}
|
|
10731
|
+
function lines(prefix, body, options = {}) {
|
|
10732
|
+
const { first, lazy } = options;
|
|
10733
|
+
const opening = first ?? prefix;
|
|
10734
|
+
const meta = {
|
|
10735
|
+
// An opening that matches empty starts a run at any character.
|
|
10736
|
+
firstSet: matchesEmpty(opening) ? any() : opening._meta.firstSet,
|
|
10737
|
+
canMatchNewline: true,
|
|
10738
|
+
isTrivia: false
|
|
10739
|
+
};
|
|
10740
|
+
return {
|
|
10741
|
+
_tag: "lines",
|
|
10742
|
+
_meta: meta,
|
|
10743
|
+
_def: { tag: "lines", prefix, body, ...first === void 0 ? {} : { first }, ...lazy === void 0 ? {} : { lazy } },
|
|
10744
|
+
parse(input, pos, ctx) {
|
|
10745
|
+
const c = ctx;
|
|
10746
|
+
const probe = createDetachedParseContext(false, ctx.state);
|
|
10747
|
+
probe.lineView = c.lineView;
|
|
10748
|
+
const run = [];
|
|
10749
|
+
const parts = [];
|
|
10750
|
+
let offset = 0;
|
|
10751
|
+
for (let start = pos; start < input.length || start === pos; ) {
|
|
10752
|
+
let end2 = input.indexOf("\n", start);
|
|
10753
|
+
if (end2 < 0) end2 = input.length;
|
|
10754
|
+
probe._columnsSplit = void 0;
|
|
10755
|
+
const head = (run.length === 0 ? opening : prefix).parse(input, start, probe);
|
|
10756
|
+
let content;
|
|
10757
|
+
let joined;
|
|
10758
|
+
if (head.ok && head.span.end <= end2) {
|
|
10759
|
+
content = head.span.end;
|
|
10760
|
+
joined = "prefix";
|
|
10761
|
+
} else if (run.length === 0) {
|
|
10762
|
+
return { ok: false, expected: head.ok ? ["line prefix"] : head.expected, span: { start, end: start } };
|
|
10763
|
+
} else if (lazy !== void 0 && lazy.parse(input, start, probe).ok) {
|
|
10764
|
+
content = start;
|
|
10765
|
+
joined = "lazy";
|
|
10766
|
+
} else break;
|
|
10767
|
+
const mark = probe._columnsSplit;
|
|
10768
|
+
const here = columnAt(input, content, c);
|
|
10769
|
+
const split = joined === "prefix" && mark !== void 0 && mark.at === content ? mark.split : here.split;
|
|
10770
|
+
run.push({ offset, source: content, end: end2, column: here.column + (split - here.split), split, lazy: joined === "lazy" });
|
|
10771
|
+
const text = input.slice(content, end2);
|
|
10772
|
+
const newline = end2 < input.length;
|
|
10773
|
+
parts.push(newline ? `${text}
|
|
10774
|
+
` : text);
|
|
10775
|
+
offset += text.length + (newline ? 1 : 0);
|
|
10776
|
+
start = end2 + 1;
|
|
10777
|
+
if (!newline) break;
|
|
10778
|
+
}
|
|
10779
|
+
const view = { lines: run, parent: c.lineView };
|
|
10780
|
+
const saved = c.lineView, starts = c._lineStarts, lineIndex = c._lineIndex, scanned = c._lineScannedTo, probing = c._probe;
|
|
10781
|
+
const errors = c._errors?.length ?? 0;
|
|
10782
|
+
let cursor = -1;
|
|
10783
|
+
if (probing !== void 0) for (const line2 of run) {
|
|
10784
|
+
if (probing.offset >= line2.source && probing.offset <= line2.end) {
|
|
10785
|
+
cursor = line2.offset + probing.offset - line2.source;
|
|
10786
|
+
break;
|
|
10787
|
+
}
|
|
10788
|
+
}
|
|
10789
|
+
const inner = cursor < 0 ? void 0 : { offset: cursor, best: null };
|
|
10790
|
+
c.lineView = view;
|
|
10791
|
+
c._lineStarts = void 0;
|
|
10792
|
+
c._lineIndex = void 0;
|
|
10793
|
+
c._lineScannedTo = void 0;
|
|
10794
|
+
c._probe = inner;
|
|
10795
|
+
let result;
|
|
10796
|
+
try {
|
|
10797
|
+
result = body.parse(parts.join(""), 0, ctx);
|
|
10798
|
+
} finally {
|
|
10799
|
+
c.lineView = saved;
|
|
10800
|
+
c._lineStarts = starts;
|
|
10801
|
+
c._lineIndex = lineIndex;
|
|
10802
|
+
c._lineScannedTo = scanned;
|
|
10803
|
+
c._probe = probing;
|
|
10804
|
+
}
|
|
10805
|
+
if (inner?.best) failAt(c, inner.best.expected, sourceOffset(view, inner.best.span.start));
|
|
10806
|
+
if (c._errors !== void 0) for (let i = errors; i < c._errors.length; i++) {
|
|
10807
|
+
const error = c._errors[i];
|
|
10808
|
+
error.span = { start: sourceOffset(view, error.span.start), end: sourceOffset(view, error.span.end) };
|
|
10809
|
+
}
|
|
10810
|
+
if (!result.ok) {
|
|
10811
|
+
const at = sourceOffset(view, result.span.start);
|
|
10812
|
+
return { ...result, span: { start: at, end: at } };
|
|
10813
|
+
}
|
|
10814
|
+
const stop = result.span.end;
|
|
10815
|
+
const index = lineIndexAt(view, stop);
|
|
10816
|
+
const line = run[index];
|
|
10817
|
+
const end = stop === line.offset && index > 0 ? run[index - 1].end + 1 : stop - line.offset > line.end - line.source ? line.end + 1 : line.source + (stop - line.offset);
|
|
10818
|
+
recordLineRangeFromContext(c, input, pos, end);
|
|
10819
|
+
return { ok: true, value: result.value, span: { start: pos, end } };
|
|
10820
|
+
}
|
|
10821
|
+
};
|
|
10822
|
+
}
|
|
10823
|
+
|
|
10824
|
+
// src/table/line-scan.ts
|
|
10825
|
+
function rebuildLineScan(s, subtree) {
|
|
10826
|
+
if (s.kind === 2) {
|
|
10827
|
+
return lines(subtree(s.prefix), subtree(s.body), {
|
|
10828
|
+
...s.first === void 0 ? {} : { first: subtree(s.first) },
|
|
10829
|
+
...s.lazy === void 0 ? {} : { lazy: subtree(s.lazy) }
|
|
10830
|
+
});
|
|
10831
|
+
}
|
|
10832
|
+
if (s.kind === 3) return columns(s.n);
|
|
10833
|
+
return void 0;
|
|
10834
|
+
}
|
|
10835
|
+
|
|
10585
10836
|
// src/combinators/literal.ts
|
|
10586
10837
|
function asciiFoldEq(a, b) {
|
|
10587
10838
|
if (a.length !== b.length) return false;
|
|
@@ -11297,7 +11548,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11297
11548
|
...prog.labels === void 0 ? {} : { triviaKindLabels: prog.labels },
|
|
11298
11549
|
...prog.classified === 1 ? { rootTriviaClassified: true } : {}
|
|
11299
11550
|
};
|
|
11300
|
-
const
|
|
11551
|
+
const lines2 = prog.lines === 1;
|
|
11301
11552
|
const mode = prog.hostMode ?? "ast";
|
|
11302
11553
|
const elided = mode === "ast" && hasDirectBuilder(prog);
|
|
11303
11554
|
const coverageDefinitions = prog.cov === void 0 ? void 0 : Object.freeze(covDefinitions(prog).map(Object.freeze));
|
|
@@ -11325,7 +11576,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11325
11576
|
ctx._fe = -1;
|
|
11326
11577
|
ctx._fx = EMPTY_FX;
|
|
11327
11578
|
ctx._fc = false;
|
|
11328
|
-
if (
|
|
11579
|
+
if (lines2 && ctx._lineStarts === void 0) {
|
|
11329
11580
|
ctx._lineStarts = [0];
|
|
11330
11581
|
ctx._lineScannedTo = 0;
|
|
11331
11582
|
}
|
|
@@ -11333,10 +11584,10 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
|
|
|
11333
11584
|
if (end < 0) {
|
|
11334
11585
|
const fe = ctx._fe;
|
|
11335
11586
|
const at = fe === void 0 || fe < 0 ? pos : fe;
|
|
11336
|
-
const fspan =
|
|
11587
|
+
const fspan = lines2 ? spanLines(ctx, at, at) : { start: at, end: at };
|
|
11337
11588
|
return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
|
|
11338
11589
|
}
|
|
11339
|
-
return { ok: true, value: d.lastValue(), span:
|
|
11590
|
+
return { ok: true, value: d.lastValue(), span: lines2 ? spanLines(ctx, pos, end) : { start: pos, end } };
|
|
11340
11591
|
};
|
|
11341
11592
|
const ownTrivia = triviaOfRule(prog.rules[name]);
|
|
11342
11593
|
const meta = ownTrivia === void 0 ? baseMeta : { ...baseMeta, grammarTrivia: ownTrivia };
|
|
@@ -11437,12 +11688,7 @@ function assemble(t2, prog, cfg) {
|
|
|
11437
11688
|
return recognize;
|
|
11438
11689
|
}
|
|
11439
11690
|
const labelExtraIps = [];
|
|
11440
|
-
for (const s of prog.scans ?? [])
|
|
11441
|
-
for (const r of s.skip) labelExtraIps.push(r[0]);
|
|
11442
|
-
if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
|
|
11443
|
-
if (s.recoverAt !== void 0) labelExtraIps.push(s.recoverAt[0]);
|
|
11444
|
-
if (s.stopAt !== void 0) labelExtraIps.push(s.stopAt[0]);
|
|
11445
|
-
}
|
|
11691
|
+
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) labelExtraIps.push(r[0]);
|
|
11446
11692
|
for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
|
|
11447
11693
|
const closureLabels = computeSiteLabels(
|
|
11448
11694
|
code,
|
|
@@ -14253,12 +14499,7 @@ function assemble(t2, prog, cfg) {
|
|
|
14253
14499
|
let emitReached;
|
|
14254
14500
|
{
|
|
14255
14501
|
const extraIps = [];
|
|
14256
|
-
for (const s of prog.scans ?? [])
|
|
14257
|
-
for (const r of s.skip) extraIps.push(r[0]);
|
|
14258
|
-
if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
|
|
14259
|
-
if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
|
|
14260
|
-
if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
|
|
14261
|
-
}
|
|
14502
|
+
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
|
|
14262
14503
|
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
14263
14504
|
const roots = [...Object.values(prog.rules), ...extraIps];
|
|
14264
14505
|
for (const ip of reachableSites(code, roots)) {
|
|
@@ -14455,6 +14696,11 @@ function assemble(t2, prog, cfg) {
|
|
|
14455
14696
|
return link(ip);
|
|
14456
14697
|
}
|
|
14457
14698
|
for (const s of prog.scans ?? []) {
|
|
14699
|
+
const rebuilt = rebuildLineScan(s, subtreeComb);
|
|
14700
|
+
if (rebuilt !== void 0) {
|
|
14701
|
+
scansArr.push(rebuilt);
|
|
14702
|
+
continue;
|
|
14703
|
+
}
|
|
14458
14704
|
const skip = s.skip.map((r) => subtreeComb(r));
|
|
14459
14705
|
const raw = (s.flags & 1) !== 0;
|
|
14460
14706
|
if (s.kind === 1) {
|
|
@@ -14640,7 +14886,8 @@ function tableRules(source, metadataOrEntry = {}) {
|
|
|
14640
14886
|
scanSkipFor: (ri, ctx) => {
|
|
14641
14887
|
const a = cache.forCtx(ctx);
|
|
14642
14888
|
selected = a;
|
|
14643
|
-
|
|
14889
|
+
const slot = skipOf?.[ri];
|
|
14890
|
+
return slot === void 0 || slot < 0 ? void 0 : a.scanSkip[slot];
|
|
14644
14891
|
}
|
|
14645
14892
|
}, artifactMetadata, resolved);
|
|
14646
14893
|
if (entry === void 0) return map;
|
|
@@ -14695,6 +14942,11 @@ function emitScanSpec(s) {
|
|
|
14695
14942
|
if (s.sent !== void 0) parts.push(`sent:${s.sent === null ? "null" : jsString(s.sent)}`);
|
|
14696
14943
|
if (s.open !== void 0) parts.push(`open:${jsString(s.open)}`);
|
|
14697
14944
|
if (s.close !== void 0) parts.push(`close:${jsString(s.close)}`);
|
|
14945
|
+
for (const key of ["prefix", "body", "first", "lazy"]) {
|
|
14946
|
+
const r = s[key];
|
|
14947
|
+
if (r !== void 0) parts.push(`${key}:${emitRef(r)}`);
|
|
14948
|
+
}
|
|
14949
|
+
if (s.n !== void 0) parts.push(`n:${s.n}`);
|
|
14698
14950
|
return `{${parts.join(",")}}`;
|
|
14699
14951
|
}
|
|
14700
14952
|
function emitDispatchSpec(d) {
|
|
@@ -14704,12 +14956,7 @@ function emitAssemblies(prog, cfgs) {
|
|
|
14704
14956
|
if (cfgs.length === 0) return ["a:[],"];
|
|
14705
14957
|
const t2 = resolveTable(prog);
|
|
14706
14958
|
const extraIps = [];
|
|
14707
|
-
for (const s of prog.scans ?? [])
|
|
14708
|
-
for (const r of s.skip) extraIps.push(r[0]);
|
|
14709
|
-
if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
|
|
14710
|
-
if (s.recoverAt !== void 0) extraIps.push(s.recoverAt[0]);
|
|
14711
|
-
if (s.stopAt !== void 0) extraIps.push(s.stopAt[0]);
|
|
14712
|
-
}
|
|
14959
|
+
for (const s of prog.scans ?? []) for (const r of scanRefs(s)) extraIps.push(r[0]);
|
|
14713
14960
|
for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
|
|
14714
14961
|
const out = [];
|
|
14715
14962
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14861,6 +15108,8 @@ function children(def, winners) {
|
|
|
14861
15108
|
...def.recoverAt === void 0 ? [] : [def.recoverAt],
|
|
14862
15109
|
...def.stopAt === void 0 ? [] : [def.stopAt]
|
|
14863
15110
|
];
|
|
15111
|
+
case "lines":
|
|
15112
|
+
return [def.prefix, def.body, ...def.first === void 0 ? [] : [def.first], ...def.lazy === void 0 ? [] : [def.lazy]];
|
|
14864
15113
|
case "lazy": {
|
|
14865
15114
|
let resolved;
|
|
14866
15115
|
try {
|
|
@@ -15004,6 +15253,10 @@ function payloadKey(p, d) {
|
|
|
15004
15253
|
return `expect\0${d.label ?? ""}\0${d.expected.join("")}`;
|
|
15005
15254
|
case "scanTo":
|
|
15006
15255
|
return `scanTo\0${d.raw}\0${d.orEOF}\0${d.recoverAt !== void 0}\0${d.stopAt !== void 0}`;
|
|
15256
|
+
case "lines":
|
|
15257
|
+
return `lines\0${d.first !== void 0}\0${d.lazy !== void 0}`;
|
|
15258
|
+
case "columns":
|
|
15259
|
+
return `columns\0${d.n}`;
|
|
15007
15260
|
case "guard":
|
|
15008
15261
|
return `guard\0${fnKey(d.predSrc, d.predicate)}`;
|
|
15009
15262
|
case "adjacency":
|
|
@@ -15124,6 +15377,8 @@ function segment(d, index) {
|
|
|
15124
15377
|
if (d.recoverAt !== void 0 && index === d.skip.length + 1) return "scanTo.recoverAt";
|
|
15125
15378
|
return "scanTo.stopAt";
|
|
15126
15379
|
}
|
|
15380
|
+
case "lines":
|
|
15381
|
+
return ["lines.prefix", "lines.body", d.first === void 0 ? "lines.lazy" : "lines.first", "lines.lazy"][index] ?? "lines";
|
|
15127
15382
|
default:
|
|
15128
15383
|
return d.tag;
|
|
15129
15384
|
}
|
|
@@ -16166,60 +16421,60 @@ function findKeywordRegexes(visited) {
|
|
|
16166
16421
|
var sitesLine = (sites) => sites.slice(0, 6).map(siteToString).join("\n ") + (sites.length > 6 ? `
|
|
16167
16422
|
\u2026 and ${sites.length - 6} more` : "");
|
|
16168
16423
|
function formatDuplicationFindings(report) {
|
|
16169
|
-
const
|
|
16424
|
+
const lines2 = [];
|
|
16170
16425
|
for (const f of report.structureLoss) {
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16426
|
+
lines2.push(`parseman BUG [structure-loss] @ ${siteToString(f.site)}: arm[${f.earlier}] flattens \`${f.nodeType}\` where arm[${f.later}] structures it, on ${firstSetToString(f.on)}`);
|
|
16427
|
+
lines2.push(` flat: ${f.earlierShape}`);
|
|
16428
|
+
lines2.push(` rich: ${f.laterShape}`);
|
|
16429
|
+
lines2.push(` lost: ${f.lostNodeTypes.map((t2) => `\`${t2}\``).join(", ")}`);
|
|
16430
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16176
16431
|
}
|
|
16177
16432
|
for (const f of report.rewrites) {
|
|
16178
|
-
|
|
16179
|
-
|
|
16180
|
-
|
|
16181
|
-
|
|
16182
|
-
if (f.perf !== "")
|
|
16433
|
+
lines2.push(`parseman ${f.bug ? "BUG" : "rewrite"} [${f.rewrite}${f.sepByVerdict === void 0 ? "" : `/${f.sepByVerdict}`}] @ ${siteToString(f.site)}${f.astNeutral ? "" : " (candidate \u2014 verify AST identity)"}`);
|
|
16434
|
+
lines2.push(` from: ${f.from}`);
|
|
16435
|
+
lines2.push(` to: ${f.to}`);
|
|
16436
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16437
|
+
if (f.perf !== "") lines2.push(` perf: ${f.perf}`);
|
|
16183
16438
|
}
|
|
16184
16439
|
for (const f of report.divergentNodes) {
|
|
16185
|
-
|
|
16186
|
-
for (const p of f.productions)
|
|
16440
|
+
lines2.push(`parseman divergent-node: \`${f.nodeType}\` is built by ${f.count} different productions sharing ${f.sharedTerms.length} term(s): ${f.sharedTerms.map((t2) => `\`${t2}\``).join(", ")}`);
|
|
16441
|
+
for (const p of f.productions) lines2.push(` ${siteToString(p.site)}
|
|
16187
16442
|
${p.shape}
|
|
16188
16443
|
unique to it: ${p.distinctTerms.length === 0 ? "(none)" : p.distinctTerms.map((t2) => `\`${t2}\``).join(", ")}`);
|
|
16189
|
-
|
|
16444
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16190
16445
|
}
|
|
16191
16446
|
for (const f of report.keywordRegexes) {
|
|
16192
16447
|
const src = f.source.length > 90 ? `${f.source.slice(0, 88)}\u2026` : f.source;
|
|
16193
|
-
|
|
16194
|
-
|
|
16448
|
+
lines2.push(`parseman ${f.bug ? "BUG " : ""}keyword-regex @ ${siteToString(f.site)}: /${src}/${f.flags}${f.vocabulary ? ` [${f.words.length} literal words${f.longestFirst ? "" : ", NOT longest-first"}]` : ""}${f.hazards.length > 0 ? ` [${f.hazards.length} prefix hazard(s)${f.bug ? ", UNRESCUED" : ""}]` : ""}${f.caseFoldRisk ? " [CASE-FOLD RISK]" : ""}`);
|
|
16449
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16195
16450
|
}
|
|
16196
16451
|
for (const f of report.duplicates) {
|
|
16197
|
-
|
|
16198
|
-
|
|
16199
|
-
|
|
16452
|
+
lines2.push(`parseman duplication: ${f.count}\xD7 identical ${f.size}-node shape (saves ${f.savings} nodes) \u2014 ${f.shape}`);
|
|
16453
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
16454
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16200
16455
|
}
|
|
16201
16456
|
for (const f of report.nearDuplicates) {
|
|
16202
|
-
|
|
16203
|
-
|
|
16204
|
-
|
|
16205
|
-
|
|
16457
|
+
lines2.push(`parseman near-duplication: ${f.count} clones of a ${f.sharedSize}-node shape differing at ONE slot (saves ${f.savings} nodes) \u2014 ${f.shape}`);
|
|
16458
|
+
lines2.push(` slot: ${f.slotPath} \u2208 { ${f.variants.join(" | ")} }`);
|
|
16459
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
16460
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16206
16461
|
}
|
|
16207
16462
|
for (const f of report.regexFragments) {
|
|
16208
|
-
|
|
16209
|
-
|
|
16210
|
-
|
|
16463
|
+
lines2.push(`parseman regex-fragment: \`${f.fragment}\` (${f.branches} branches) re-spelled in ${f.count} regex() terminals`);
|
|
16464
|
+
lines2.push(` at: ${sitesLine(f.sites)}`);
|
|
16465
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16211
16466
|
}
|
|
16212
16467
|
for (const f of report.regexClasses) {
|
|
16213
|
-
|
|
16214
|
-
for (const v of f.variants)
|
|
16468
|
+
lines2.push(`parseman regex-class${f.drifted ? " DRIFT" : ""}: [${f.canonical}] across ${f.count} regex() terminals${f.bmpCeiling ? " [BMP ceiling]" : ""}`);
|
|
16469
|
+
for (const v of f.variants) lines2.push(` [${v.source}] \xD7${v.count} ${v.delta}
|
|
16215
16470
|
${sitesLine(v.sites)}`);
|
|
16216
|
-
|
|
16471
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16217
16472
|
}
|
|
16218
16473
|
for (const f of report.overlaps) {
|
|
16219
|
-
|
|
16220
|
-
|
|
16474
|
+
lines2.push(`parseman overlap @ ${siteToString(f.site)}: arm[${f.a}] \u2229 arm[${f.b}] on ${firstSetToString(f.on)}${f.sharedPrefix === null ? "" : ` \u2014 shared prefix: ${f.sharedPrefix}`}${f.handledByStrategy ? " [sharedPrefix strategy already handles this]" : ""}`);
|
|
16475
|
+
lines2.push(` fix: ${f.suggestion}`);
|
|
16221
16476
|
}
|
|
16222
|
-
return
|
|
16477
|
+
return lines2;
|
|
16223
16478
|
}
|
|
16224
16479
|
function duplicationFindingCount(report) {
|
|
16225
16480
|
return report.duplicates.length + report.nearDuplicates.length + report.regexFragments.length + report.regexClasses.length + report.overlaps.length + report.rewrites.length + report.divergentNodes.length + report.structureLoss.length + report.keywordRegexes.length;
|
|
@@ -16253,11 +16508,11 @@ function reportDuplication(opt, analyze) {
|
|
|
16253
16508
|
);
|
|
16254
16509
|
return void 0;
|
|
16255
16510
|
}
|
|
16256
|
-
const
|
|
16257
|
-
if (
|
|
16511
|
+
const lines2 = formatDuplicationFindings(report);
|
|
16512
|
+
if (lines2.length > 0) {
|
|
16258
16513
|
if (level === "error") throw new Error(`parseman: ${duplicationFindingCount(report)} duplication/overlap finding(s)
|
|
16259
|
-
${
|
|
16260
|
-
for (const l of
|
|
16514
|
+
${lines2.join("\n")}`);
|
|
16515
|
+
for (const l of lines2) console.warn(l);
|
|
16261
16516
|
}
|
|
16262
16517
|
return report;
|
|
16263
16518
|
}
|
|
@@ -16873,7 +17128,7 @@ function cellsOf(line) {
|
|
|
16873
17128
|
}
|
|
16874
17129
|
return cells;
|
|
16875
17130
|
}
|
|
16876
|
-
var plain = (
|
|
17131
|
+
var plain = (lines2) => lines2.map((l) => cellsOf(l).map((c) => c.text).join("")).join("\n");
|
|
16877
17132
|
var CODE_CACHE = /* @__PURE__ */ new Map();
|
|
16878
17133
|
function codesFor(style) {
|
|
16879
17134
|
if (style === void 0) return { pre: "", post: "" };
|
|
@@ -16934,10 +17189,10 @@ function linked(text, path) {
|
|
|
16934
17189
|
const trail = text.slice(body.length);
|
|
16935
17190
|
return `${tpl.pre}${path}${tpl.mid}${body}${tpl.post}${trail}`;
|
|
16936
17191
|
}
|
|
16937
|
-
function render2(
|
|
16938
|
-
if (target.color !== true) return plain(
|
|
17192
|
+
function render2(lines2, target = {}) {
|
|
17193
|
+
if (target.color !== true) return plain(lines2);
|
|
16939
17194
|
const wantLinks = target.links !== false;
|
|
16940
|
-
return
|
|
17195
|
+
return lines2.map((line) => {
|
|
16941
17196
|
if (line.length === 1 && line[0].raw === true) return line[0].text;
|
|
16942
17197
|
return cellsOf(line).map((c) => {
|
|
16943
17198
|
const { pre, post } = codesFor(c.style);
|
|
@@ -17553,8 +17808,11 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
|
|
|
17553
17808
|
// falls back to regex-scanning generated hooks; a table has no hooks to scan,
|
|
17554
17809
|
// so this is the channel.
|
|
17555
17810
|
...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
|
|
17556
|
-
parse
|
|
17557
|
-
|
|
17811
|
+
// The same three arguments as a combinator's own `parse`, so a compiled
|
|
17812
|
+
// parser runs where a combinator does. A caller probing many positions
|
|
17813
|
+
// passes one context and pays for none per call.
|
|
17814
|
+
parse(input, pos = 0, ctx) {
|
|
17815
|
+
return runOnce(input, pos, ctx ?? createParseContext());
|
|
17558
17816
|
},
|
|
17559
17817
|
parseWithContext(input, parseCtx, pos = 0) {
|
|
17560
17818
|
return runOnce(input, pos, parseCtx);
|
|
@@ -17820,9 +18078,11 @@ function attempt(parser2, options) {
|
|
|
17820
18078
|
const mark = saveCstMark(ctx);
|
|
17821
18079
|
const log = ctx._triviaLog?.length;
|
|
17822
18080
|
const rootLog = ctx._rootTriviaLog?.length;
|
|
18081
|
+
const split = ctx._columnsSplit;
|
|
17823
18082
|
const result = parser2.parse(input, pos, ctx);
|
|
17824
18083
|
if (result.ok) return result;
|
|
17825
18084
|
rollbackCstCapture(ctx, mark);
|
|
18085
|
+
ctx._columnsSplit = split;
|
|
17826
18086
|
if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
|
|
17827
18087
|
if (rootLog !== void 0 && ctx._rootTriviaLog && ctx._rootTriviaLog.length !== rootLog) ctx._rootTriviaLog.length = rootLog;
|
|
17828
18088
|
if (result.committed && !contain) return result;
|
|
@@ -17868,7 +18128,9 @@ var FROZEN_TAGS = /* @__PURE__ */ new Set([
|
|
|
17868
18128
|
"withCtx",
|
|
17869
18129
|
"routed",
|
|
17870
18130
|
"trivia",
|
|
17871
|
-
"unknown"
|
|
18131
|
+
"unknown",
|
|
18132
|
+
"lines",
|
|
18133
|
+
"columns"
|
|
17872
18134
|
]);
|
|
17873
18135
|
var CARRIED_META = [
|
|
17874
18136
|
"grammarTrivia",
|
|
@@ -17897,7 +18159,7 @@ function subtreeContains(p, targets) {
|
|
|
17897
18159
|
const kids = [];
|
|
17898
18160
|
if (Array.isArray(rec.parsers)) kids.push(...rec.parsers);
|
|
17899
18161
|
if (Array.isArray(rec.skip)) kids.push(...rec.skip);
|
|
17900
|
-
for (const k of ["parser", "main", "skipped", "separator", "sentinel", "recoverAt", "stopAt", "selector", "otherwise", "fallback", "triviaParser"])
|
|
18162
|
+
for (const k of ["parser", "main", "skipped", "separator", "sentinel", "recoverAt", "stopAt", "selector", "otherwise", "fallback", "triviaParser", "prefix", "body", "first", "lazy"])
|
|
17901
18163
|
if (rec[k]) kids.push(rec[k]);
|
|
17902
18164
|
if (d.tag === "dispatch") {
|
|
17903
18165
|
for (const c2 of d.cases) kids.push(c2.parser);
|
|
@@ -18704,9 +18966,9 @@ function locatedLines(l, opts) {
|
|
|
18704
18966
|
t(l.id, TONE.ident)
|
|
18705
18967
|
]);
|
|
18706
18968
|
out.push([t(" here ", TONE.faint), t(l.site, TONE.quiet)]);
|
|
18707
|
-
const
|
|
18708
|
-
out.push([t(" why ", TONE.quiet), t(
|
|
18709
|
-
for (const x of
|
|
18969
|
+
const lines2 = wrap(`No change can be offered here: ${l.reason}`, width - 12, "");
|
|
18970
|
+
out.push([t(" why ", TONE.quiet), t(lines2[0] ?? "", TONE.warn)]);
|
|
18971
|
+
for (const x of lines2.slice(1)) out.push([t(" "), t(x, TONE.warn)]);
|
|
18710
18972
|
return out;
|
|
18711
18973
|
}
|
|
18712
18974
|
|