parseman 0.51.1 → 0.52.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/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +101 -35
- package/dist/analysis/diagnostics.js.map +1 -1
- package/dist/cli/index.js +103 -37
- package/dist/cli/index.js.map +1 -1
- package/dist/combinators/attempt.d.ts +11 -1
- package/dist/combinators/attempt.d.ts.map +1 -1
- package/dist/combinators/map.d.ts.map +1 -1
- package/dist/combinators/node.d.ts +6 -2
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/token.d.ts +8 -8
- package/dist/combinators/token.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +4 -0
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/trivia-kinds.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +107 -40
- package/dist/index.js.map +1 -1
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.js +107 -41
- package/dist/plugin/index.js.map +1 -1
- package/dist/spec/index.js +55 -10
- package/dist/spec/index.js.map +1 -1
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode-baseline.d.ts.map +1 -1
- package/dist/table/exec-baseline.d.ts.map +1 -1
- package/dist/table/exec.d.ts.map +1 -1
- package/dist/table/index.js +404 -371
- package/dist/table/index.js.map +2 -2
- package/dist/table/ops.d.ts +9 -5
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/types.d.ts +9 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/commitment.ts +3 -1
- package/src/analysis/duplication.ts +1 -1
- package/src/analysis/rebuild.ts +3 -3
- package/src/combinators/attempt.ts +26 -3
- package/src/combinators/first-set.ts +5 -1
- package/src/combinators/map.ts +5 -1
- package/src/combinators/node.ts +12 -3
- package/src/combinators/token.ts +46 -3
- package/src/compiler/ir-serialize.ts +5 -5
- package/src/coverage.ts +3 -4
- package/src/cst/trivia-kinds.ts +6 -0
- package/src/index.ts +2 -1
- package/src/plugin/evaluator.ts +8 -5
- package/src/table/assemble.ts +30 -11
- package/src/table/child-slots.ts +2 -2
- package/src/table/emit-assembly.ts +13 -6
- package/src/table/encode-baseline.ts +8 -3
- package/src/table/encode.ts +16 -16
- package/src/table/exec-baseline.ts +30 -4
- package/src/table/exec.ts +14 -5
- package/src/table/ops.ts +10 -6
- package/src/table/scalar-terminal.ts +5 -5
- package/src/table/site-labels.ts +5 -3
- package/src/types.ts +9 -2
- package/src/version.ts +1 -1
package/dist/table/index.js
CHANGED
|
@@ -257,6 +257,10 @@ function firstSetBody(p, seen, resolve, activeTrivia) {
|
|
|
257
257
|
case "node":
|
|
258
258
|
case "sepBy":
|
|
259
259
|
case "expect":
|
|
260
|
+
// A transaction accepts exactly what its inner accepts. Its own `_meta` is
|
|
261
|
+
// the inner's construction-time set, which reads `any` when the inner opens
|
|
262
|
+
// with a rule reference — resolve through it like any other wrapper.
|
|
263
|
+
case "attempt":
|
|
260
264
|
return fs(d.parser);
|
|
261
265
|
case "grammar":
|
|
262
266
|
return firstSetOf(
|
|
@@ -1621,6 +1625,10 @@ function peelLabel(p) {
|
|
|
1621
1625
|
return null;
|
|
1622
1626
|
}
|
|
1623
1627
|
function analyzeLabeledTrivia(trivia2) {
|
|
1628
|
+
if (trivia2._def.tag === "trivia") {
|
|
1629
|
+
const own = trivia2._meta.labeledTriviaSpec;
|
|
1630
|
+
if (own !== void 0) return own;
|
|
1631
|
+
}
|
|
1624
1632
|
if (trivia2 === labeledTrivia0) return labeledSpec0;
|
|
1625
1633
|
if (trivia2 === labeledTrivia1) return labeledSpec1;
|
|
1626
1634
|
if (trivia2 === labeledTrivia2) return labeledSpec2;
|
|
@@ -3286,13 +3294,17 @@ function transform(combinator, fn) {
|
|
|
3286
3294
|
};
|
|
3287
3295
|
}
|
|
3288
3296
|
function trivia(combinator) {
|
|
3289
|
-
const
|
|
3297
|
+
const labeled = analyzeLabeledTrivia(combinator);
|
|
3298
|
+
const kindLabels = labeled?.labels;
|
|
3290
3299
|
return {
|
|
3291
3300
|
_tag: combinator._tag,
|
|
3292
3301
|
_meta: {
|
|
3293
3302
|
...combinator._meta,
|
|
3294
3303
|
isTrivia: true,
|
|
3295
3304
|
triviaScanner: fastTriviaScanner(combinator),
|
|
3305
|
+
// Every labeled scan of this trivia reads its spec; the module's four-slot
|
|
3306
|
+
// memo alone thrashes on a grammar with more than four trivia tables.
|
|
3307
|
+
labeledTriviaSpec: labeled,
|
|
3296
3308
|
...kindLabels ? { triviaKindLabels: kindLabels } : {}
|
|
3297
3309
|
},
|
|
3298
3310
|
_def: { tag: "trivia", parser: combinator },
|
|
@@ -3434,6 +3446,271 @@ function ref() {
|
|
|
3434
3446
|
return slot;
|
|
3435
3447
|
}
|
|
3436
3448
|
|
|
3449
|
+
// src/compiler/degradation.ts
|
|
3450
|
+
function formatDegradation(d) {
|
|
3451
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
3452
|
+
}
|
|
3453
|
+
var DETAIL_CAP = 8;
|
|
3454
|
+
function formatDegradations(list) {
|
|
3455
|
+
const byCode = /* @__PURE__ */ new Map();
|
|
3456
|
+
for (const d of list) {
|
|
3457
|
+
const bucket = byCode.get(d.code);
|
|
3458
|
+
if (bucket) bucket.push(d);
|
|
3459
|
+
else byCode.set(d.code, [d]);
|
|
3460
|
+
}
|
|
3461
|
+
const out = [];
|
|
3462
|
+
for (const [code, items] of byCode) {
|
|
3463
|
+
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
3464
|
+
if (items.length > DETAIL_CAP) {
|
|
3465
|
+
out.push(
|
|
3466
|
+
`[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.`
|
|
3467
|
+
);
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
return out;
|
|
3471
|
+
}
|
|
3472
|
+
var _sinks = [];
|
|
3473
|
+
function beginDegradationCapture() {
|
|
3474
|
+
_sinks.push(/* @__PURE__ */ new Map());
|
|
3475
|
+
}
|
|
3476
|
+
function degradationCaptureDepth() {
|
|
3477
|
+
return _sinks.length;
|
|
3478
|
+
}
|
|
3479
|
+
function unwindDegradationCapture(depth) {
|
|
3480
|
+
const found = [];
|
|
3481
|
+
while (_sinks.length > depth) {
|
|
3482
|
+
const sink = _sinks.pop();
|
|
3483
|
+
found.unshift(...sink.values());
|
|
3484
|
+
}
|
|
3485
|
+
return found;
|
|
3486
|
+
}
|
|
3487
|
+
function resolveDegradationLevel(explicit) {
|
|
3488
|
+
if (explicit !== void 0) return explicit;
|
|
3489
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
3490
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
3491
|
+
return "warn";
|
|
3492
|
+
}
|
|
3493
|
+
function degradationKey(d) {
|
|
3494
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
3495
|
+
}
|
|
3496
|
+
function recordDegradation(d) {
|
|
3497
|
+
const level = resolveDegradationLevel();
|
|
3498
|
+
if (level === "off") return;
|
|
3499
|
+
const key = degradationKey(d);
|
|
3500
|
+
const sink = _sinks[_sinks.length - 1];
|
|
3501
|
+
if (sink) {
|
|
3502
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
3503
|
+
return;
|
|
3504
|
+
}
|
|
3505
|
+
if (_immediate.has(key)) return;
|
|
3506
|
+
_immediate.add(key);
|
|
3507
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
3508
|
+
${formatDegradation(d)}`);
|
|
3509
|
+
console.warn(formatDegradation(d));
|
|
3510
|
+
}
|
|
3511
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
3512
|
+
function beginCompileDegradationDrain() {
|
|
3513
|
+
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
3514
|
+
};
|
|
3515
|
+
const depth = degradationCaptureDepth();
|
|
3516
|
+
beginDegradationCapture();
|
|
3517
|
+
return (report) => {
|
|
3518
|
+
const found = unwindDegradationCapture(depth);
|
|
3519
|
+
if (!report || found.length === 0) return;
|
|
3520
|
+
const fresh = found.filter((d) => {
|
|
3521
|
+
const k = degradationKey(d);
|
|
3522
|
+
if (_immediate.has(k)) return false;
|
|
3523
|
+
_immediate.add(k);
|
|
3524
|
+
return true;
|
|
3525
|
+
});
|
|
3526
|
+
if (fresh.length === 0) return;
|
|
3527
|
+
const lines = formatDegradations(fresh);
|
|
3528
|
+
if (resolveDegradationLevel() === "error") {
|
|
3529
|
+
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
3530
|
+
${lines.join("\n")}`);
|
|
3531
|
+
}
|
|
3532
|
+
for (const l of lines) console.warn(l);
|
|
3533
|
+
};
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
// src/compiler/build-arity.ts
|
|
3537
|
+
function cstOutputHost(build) {
|
|
3538
|
+
return build?._parsemanCstOutput === true;
|
|
3539
|
+
}
|
|
3540
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
3541
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
3542
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
3543
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
3544
|
+
function confirmedBuildArity(src) {
|
|
3545
|
+
const s = src.trim();
|
|
3546
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
3547
|
+
if (/\barguments\b/.test(s)) return null;
|
|
3548
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
3549
|
+
const inner = paramListText(s);
|
|
3550
|
+
if (inner === null) return null;
|
|
3551
|
+
if (inner.trim() === "") return 0;
|
|
3552
|
+
const parts = splitTopLevel(inner);
|
|
3553
|
+
if (parts === null) return null;
|
|
3554
|
+
for (const part of parts) {
|
|
3555
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
3556
|
+
}
|
|
3557
|
+
return parts.length;
|
|
3558
|
+
}
|
|
3559
|
+
function paramListText(s) {
|
|
3560
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
3561
|
+
if (!open) return null;
|
|
3562
|
+
const start = open[0].length;
|
|
3563
|
+
const end = matchingParen(s, start);
|
|
3564
|
+
if (end === null) return null;
|
|
3565
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
3566
|
+
return s.slice(start, end);
|
|
3567
|
+
}
|
|
3568
|
+
function matchingParen(s, start) {
|
|
3569
|
+
let depth = 0;
|
|
3570
|
+
for (let i = start; i < s.length; i++) {
|
|
3571
|
+
const c = s[i];
|
|
3572
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
3573
|
+
const close = skipString(s, i);
|
|
3574
|
+
if (close === null) return null;
|
|
3575
|
+
i = close;
|
|
3576
|
+
continue;
|
|
3577
|
+
}
|
|
3578
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3579
|
+
else if (c === "]" || c === "}") {
|
|
3580
|
+
if (--depth < 0) return null;
|
|
3581
|
+
} else if (c === ")") {
|
|
3582
|
+
if (depth === 0) return i;
|
|
3583
|
+
depth--;
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
return null;
|
|
3587
|
+
}
|
|
3588
|
+
function skipString(s, open) {
|
|
3589
|
+
const quote = s[open];
|
|
3590
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
3591
|
+
if (s[i] === "\\") {
|
|
3592
|
+
i++;
|
|
3593
|
+
continue;
|
|
3594
|
+
}
|
|
3595
|
+
if (s[i] === quote) return i;
|
|
3596
|
+
}
|
|
3597
|
+
return null;
|
|
3598
|
+
}
|
|
3599
|
+
function splitTopLevel(inner) {
|
|
3600
|
+
const parts = [];
|
|
3601
|
+
let depth = 0;
|
|
3602
|
+
let angle = 0;
|
|
3603
|
+
let last = 0;
|
|
3604
|
+
for (let i = 0; i < inner.length; i++) {
|
|
3605
|
+
const c = inner[i];
|
|
3606
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
3607
|
+
i++;
|
|
3608
|
+
continue;
|
|
3609
|
+
}
|
|
3610
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
3611
|
+
const close = skipString(inner, i);
|
|
3612
|
+
if (close === null) return null;
|
|
3613
|
+
i = close;
|
|
3614
|
+
continue;
|
|
3615
|
+
}
|
|
3616
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3617
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
3618
|
+
if (--depth < 0) return null;
|
|
3619
|
+
} else if (c === "<") angle++;
|
|
3620
|
+
else if (c === ">") {
|
|
3621
|
+
if (--angle < 0) return null;
|
|
3622
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
3623
|
+
parts.push(inner.slice(last, i));
|
|
3624
|
+
last = i + 1;
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
3628
|
+
parts.push(inner.slice(last));
|
|
3629
|
+
return parts;
|
|
3630
|
+
}
|
|
3631
|
+
function isConfirmableParam(part) {
|
|
3632
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
3633
|
+
if (!head) return false;
|
|
3634
|
+
const rest = part.slice(head[0].length);
|
|
3635
|
+
if (rest === "") return true;
|
|
3636
|
+
if (rest[0] !== ":") return false;
|
|
3637
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
3638
|
+
}
|
|
3639
|
+
function hasDefaultAssign(annotation) {
|
|
3640
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
3641
|
+
if (annotation[i] !== "=") continue;
|
|
3642
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
3643
|
+
i++;
|
|
3644
|
+
continue;
|
|
3645
|
+
}
|
|
3646
|
+
const prev = annotation[i - 1];
|
|
3647
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
3648
|
+
return true;
|
|
3649
|
+
}
|
|
3650
|
+
return false;
|
|
3651
|
+
}
|
|
3652
|
+
function buildAnalysisSrc(def) {
|
|
3653
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
3654
|
+
}
|
|
3655
|
+
var RESOLVER_REASONS = {
|
|
3656
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
3657
|
+
"arguments": "its body references `arguments`",
|
|
3658
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
3659
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
3660
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
3661
|
+
"not-found": "the name did not resolve to any binding",
|
|
3662
|
+
"computed": "it is a computed expression",
|
|
3663
|
+
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
3664
|
+
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
3665
|
+
};
|
|
3666
|
+
function unconfirmableReason(def, src) {
|
|
3667
|
+
const declared = def.buildArityUnresolved;
|
|
3668
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
3669
|
+
const s = src.trim();
|
|
3670
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
3671
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
3672
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
3673
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
3674
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
3675
|
+
}
|
|
3676
|
+
return "its parameter list could not be parsed";
|
|
3677
|
+
}
|
|
3678
|
+
function confirmedArityForDef(def) {
|
|
3679
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
3680
|
+
const src = buildAnalysisSrc(def);
|
|
3681
|
+
const arity = confirmedBuildArity(src);
|
|
3682
|
+
if (arity !== null) return arity;
|
|
3683
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
3684
|
+
recordDegradation({
|
|
3685
|
+
code: "build-arity-unconfirmed",
|
|
3686
|
+
severity: "warn",
|
|
3687
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
3688
|
+
subject,
|
|
3689
|
+
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`,
|
|
3690
|
+
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"
|
|
3691
|
+
});
|
|
3692
|
+
return null;
|
|
3693
|
+
}
|
|
3694
|
+
function buildReadsRaw(def) {
|
|
3695
|
+
if (!def.build) return true;
|
|
3696
|
+
if (def.buildRawUnused === true) return false;
|
|
3697
|
+
const arity = confirmedArityForDef(def);
|
|
3698
|
+
if (arity === null) return true;
|
|
3699
|
+
return arity >= 4;
|
|
3700
|
+
}
|
|
3701
|
+
function buildReadsTrivia(def) {
|
|
3702
|
+
if (!def.build) return true;
|
|
3703
|
+
const arity = confirmedArityForDef(def);
|
|
3704
|
+
if (arity === null) return true;
|
|
3705
|
+
return arity >= 5;
|
|
3706
|
+
}
|
|
3707
|
+
function buildReadsState(def) {
|
|
3708
|
+
if (!def.build) return true;
|
|
3709
|
+
const arity = confirmedArityForDef(def);
|
|
3710
|
+
if (arity === null) return true;
|
|
3711
|
+
return arity >= 6;
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3437
3714
|
// src/combinators/token.ts
|
|
3438
3715
|
function token(root) {
|
|
3439
3716
|
const meta = {
|
|
@@ -3638,363 +3915,98 @@ function scanTo(sentinel, { skip, raw = false, orEOF = false, recoverAt, stopAt
|
|
|
3638
3915
|
if (recover.span.end <= cur) {
|
|
3639
3916
|
throw new TypeError("scanTo recoverAt must consume input");
|
|
3640
3917
|
}
|
|
3641
|
-
if (recovery < 0) {
|
|
3642
|
-
recovery = cur;
|
|
3643
|
-
recoveryErrorCount = errorCount;
|
|
3644
|
-
}
|
|
3645
|
-
if (firstSentinel >= 0 && (sentinelCount & 1) === 1) {
|
|
3646
|
-
return succeed(recoveredEnd());
|
|
3647
|
-
}
|
|
3648
|
-
cur = recover.span.end;
|
|
3649
|
-
continue;
|
|
3650
|
-
}
|
|
3651
|
-
}
|
|
3652
|
-
cur++;
|
|
3653
|
-
}
|
|
3654
|
-
if (recovery >= 0) return succeed(recoveredEnd());
|
|
3655
|
-
if (orEOF) {
|
|
3656
|
-
return succeed(cur);
|
|
3657
|
-
}
|
|
3658
|
-
const sentDef = sentinel._def;
|
|
3659
|
-
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|
|
3660
|
-
return { ok: false, expected, span: { start: pos, end: cur } };
|
|
3661
|
-
}
|
|
3662
|
-
};
|
|
3663
|
-
}
|
|
3664
|
-
function markSpec(outer, open, close, ownSkip, strict, raw) {
|
|
3665
|
-
;
|
|
3666
|
-
outer._balancedSpec = { open, close, ownSkip, strict, raw };
|
|
3667
|
-
return outer;
|
|
3668
|
-
}
|
|
3669
|
-
function balanced(open, close, options = {}) {
|
|
3670
|
-
const ownSkip = options.skip ?? [];
|
|
3671
|
-
const strict = options.strict ?? false;
|
|
3672
|
-
const combi = buildBalancedInterior(open, close, ownSkip, strict);
|
|
3673
|
-
if (options.raw) return markSpec(token(combi), open, close, ownSkip, strict, true);
|
|
3674
|
-
const eagerParse = combi.parse.bind(combi);
|
|
3675
|
-
const cache = /* @__PURE__ */ new Map();
|
|
3676
|
-
combi._balancedAmbient = { open, close, ownSkip, strict };
|
|
3677
|
-
combi.parse = (input, pos, ctx) => {
|
|
3678
|
-
const amb = ctx.scanSkip;
|
|
3679
|
-
if (!amb || amb.length === 0) return eagerParse(input, pos, ctx);
|
|
3680
|
-
let interior = cache.get(amb);
|
|
3681
|
-
if (!interior) {
|
|
3682
|
-
interior = buildBalancedInterior(open, close, [...amb, ...ownSkip], strict);
|
|
3683
|
-
cache.set(amb, interior);
|
|
3684
|
-
}
|
|
3685
|
-
return interior.parse(input, pos, ctx);
|
|
3686
|
-
};
|
|
3687
|
-
return markSpec(token(combi), open, close, ownSkip, strict, false);
|
|
3688
|
-
}
|
|
3689
|
-
function buildBalancedInterior(open, close, skips, strict = false) {
|
|
3690
|
-
const self = ref();
|
|
3691
|
-
const stop = /* @__PURE__ */ new Set([open, close]);
|
|
3692
|
-
let bounded = true;
|
|
3693
|
-
for (const sk of skips) {
|
|
3694
|
-
const cs = firstSetClassChars(sk);
|
|
3695
|
-
if (cs === null) {
|
|
3696
|
-
bounded = false;
|
|
3697
|
-
break;
|
|
3698
|
-
}
|
|
3699
|
-
for (const ch2 of cs) stop.add(ch2);
|
|
3700
|
-
}
|
|
3701
|
-
const cls = [...stop].map(escapeClassChar).join("");
|
|
3702
|
-
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
3703
|
-
const inner = many(choice(self, ...skips, content));
|
|
3704
|
-
const closer = strict ? literal(close) : expect(literal(close));
|
|
3705
|
-
const combi = transform(
|
|
3706
|
-
sequence(literal(open), inner, closer),
|
|
3707
|
-
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
3708
|
-
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
3709
|
-
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
3710
|
-
);
|
|
3711
|
-
if (combi._def.tag === "transform") {
|
|
3712
|
-
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
3713
|
-
combi._def.recognitionOnly = true;
|
|
3714
|
-
}
|
|
3715
|
-
;
|
|
3716
|
-
combi._balanced = { open, close };
|
|
3717
|
-
self.define(combi);
|
|
3718
|
-
return combi;
|
|
3719
|
-
}
|
|
3720
|
-
function firstSetClassChars(c) {
|
|
3721
|
-
const fs = c._meta.firstSet;
|
|
3722
|
-
if (fs.kind === "empty") return [];
|
|
3723
|
-
if (fs.kind !== "ranges") return null;
|
|
3724
|
-
const out = [];
|
|
3725
|
-
for (const { lo, hi } of fs.ranges) {
|
|
3726
|
-
if (hi - lo > 8) return null;
|
|
3727
|
-
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
3728
|
-
}
|
|
3729
|
-
return out;
|
|
3730
|
-
}
|
|
3731
|
-
function escapeClassChar(ch2) {
|
|
3732
|
-
return ch2.replace(/[\\\]^-]/g, "\\$&");
|
|
3733
|
-
}
|
|
3734
|
-
|
|
3735
|
-
// src/compiler/degradation.ts
|
|
3736
|
-
function formatDegradation(d) {
|
|
3737
|
-
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
3738
|
-
}
|
|
3739
|
-
var DETAIL_CAP = 8;
|
|
3740
|
-
function formatDegradations(list) {
|
|
3741
|
-
const byCode = /* @__PURE__ */ new Map();
|
|
3742
|
-
for (const d of list) {
|
|
3743
|
-
const bucket = byCode.get(d.code);
|
|
3744
|
-
if (bucket) bucket.push(d);
|
|
3745
|
-
else byCode.set(d.code, [d]);
|
|
3746
|
-
}
|
|
3747
|
-
const out = [];
|
|
3748
|
-
for (const [code, items] of byCode) {
|
|
3749
|
-
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
3750
|
-
if (items.length > DETAIL_CAP) {
|
|
3751
|
-
out.push(
|
|
3752
|
-
`[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.`
|
|
3753
|
-
);
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3756
|
-
return out;
|
|
3757
|
-
}
|
|
3758
|
-
var _sinks = [];
|
|
3759
|
-
function beginDegradationCapture() {
|
|
3760
|
-
_sinks.push(/* @__PURE__ */ new Map());
|
|
3761
|
-
}
|
|
3762
|
-
function degradationCaptureDepth() {
|
|
3763
|
-
return _sinks.length;
|
|
3764
|
-
}
|
|
3765
|
-
function unwindDegradationCapture(depth) {
|
|
3766
|
-
const found = [];
|
|
3767
|
-
while (_sinks.length > depth) {
|
|
3768
|
-
const sink = _sinks.pop();
|
|
3769
|
-
found.unshift(...sink.values());
|
|
3770
|
-
}
|
|
3771
|
-
return found;
|
|
3772
|
-
}
|
|
3773
|
-
function resolveDegradationLevel(explicit) {
|
|
3774
|
-
if (explicit !== void 0) return explicit;
|
|
3775
|
-
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
3776
|
-
if (env === "off" || env === "warn" || env === "error") return env;
|
|
3777
|
-
return "warn";
|
|
3778
|
-
}
|
|
3779
|
-
function degradationKey(d) {
|
|
3780
|
-
return JSON.stringify([d.code, d.where, d.subject]);
|
|
3781
|
-
}
|
|
3782
|
-
function recordDegradation(d) {
|
|
3783
|
-
const level = resolveDegradationLevel();
|
|
3784
|
-
if (level === "off") return;
|
|
3785
|
-
const key = degradationKey(d);
|
|
3786
|
-
const sink = _sinks[_sinks.length - 1];
|
|
3787
|
-
if (sink) {
|
|
3788
|
-
if (!sink.has(key)) sink.set(key, d);
|
|
3789
|
-
return;
|
|
3790
|
-
}
|
|
3791
|
-
if (_immediate.has(key)) return;
|
|
3792
|
-
_immediate.add(key);
|
|
3793
|
-
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
3794
|
-
${formatDegradation(d)}`);
|
|
3795
|
-
console.warn(formatDegradation(d));
|
|
3796
|
-
}
|
|
3797
|
-
var _immediate = /* @__PURE__ */ new Set();
|
|
3798
|
-
function beginCompileDegradationDrain() {
|
|
3799
|
-
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
3800
|
-
};
|
|
3801
|
-
const depth = degradationCaptureDepth();
|
|
3802
|
-
beginDegradationCapture();
|
|
3803
|
-
return (report) => {
|
|
3804
|
-
const found = unwindDegradationCapture(depth);
|
|
3805
|
-
if (!report || found.length === 0) return;
|
|
3806
|
-
const fresh = found.filter((d) => {
|
|
3807
|
-
const k = degradationKey(d);
|
|
3808
|
-
if (_immediate.has(k)) return false;
|
|
3809
|
-
_immediate.add(k);
|
|
3810
|
-
return true;
|
|
3811
|
-
});
|
|
3812
|
-
if (fresh.length === 0) return;
|
|
3813
|
-
const lines = formatDegradations(fresh);
|
|
3814
|
-
if (resolveDegradationLevel() === "error") {
|
|
3815
|
-
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
3816
|
-
${lines.join("\n")}`);
|
|
3918
|
+
if (recovery < 0) {
|
|
3919
|
+
recovery = cur;
|
|
3920
|
+
recoveryErrorCount = errorCount;
|
|
3921
|
+
}
|
|
3922
|
+
if (firstSentinel >= 0 && (sentinelCount & 1) === 1) {
|
|
3923
|
+
return succeed(recoveredEnd());
|
|
3924
|
+
}
|
|
3925
|
+
cur = recover.span.end;
|
|
3926
|
+
continue;
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
cur++;
|
|
3930
|
+
}
|
|
3931
|
+
if (recovery >= 0) return succeed(recoveredEnd());
|
|
3932
|
+
if (orEOF) {
|
|
3933
|
+
return succeed(cur);
|
|
3934
|
+
}
|
|
3935
|
+
const sentDef = sentinel._def;
|
|
3936
|
+
const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
|
|
3937
|
+
return { ok: false, expected, span: { start: pos, end: cur } };
|
|
3817
3938
|
}
|
|
3818
|
-
for (const l of lines) console.warn(l);
|
|
3819
3939
|
};
|
|
3820
3940
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
return
|
|
3825
|
-
}
|
|
3826
|
-
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
3827
|
-
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
3828
|
-
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
3829
|
-
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
3830
|
-
function confirmedBuildArity(src) {
|
|
3831
|
-
const s = src.trim();
|
|
3832
|
-
if (NATIVE_CODE_RE.test(s)) return null;
|
|
3833
|
-
if (/\barguments\b/.test(s)) return null;
|
|
3834
|
-
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
3835
|
-
const inner = paramListText(s);
|
|
3836
|
-
if (inner === null) return null;
|
|
3837
|
-
if (inner.trim() === "") return 0;
|
|
3838
|
-
const parts = splitTopLevel(inner);
|
|
3839
|
-
if (parts === null) return null;
|
|
3840
|
-
for (const part of parts) {
|
|
3841
|
-
if (!isConfirmableParam(part.trim())) return null;
|
|
3842
|
-
}
|
|
3843
|
-
return parts.length;
|
|
3844
|
-
}
|
|
3845
|
-
function paramListText(s) {
|
|
3846
|
-
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
3847
|
-
if (!open) return null;
|
|
3848
|
-
const start = open[0].length;
|
|
3849
|
-
const end = matchingParen(s, start);
|
|
3850
|
-
if (end === null) return null;
|
|
3851
|
-
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
3852
|
-
return s.slice(start, end);
|
|
3853
|
-
}
|
|
3854
|
-
function matchingParen(s, start) {
|
|
3855
|
-
let depth = 0;
|
|
3856
|
-
for (let i = start; i < s.length; i++) {
|
|
3857
|
-
const c = s[i];
|
|
3858
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
3859
|
-
const close = skipString(s, i);
|
|
3860
|
-
if (close === null) return null;
|
|
3861
|
-
i = close;
|
|
3862
|
-
continue;
|
|
3863
|
-
}
|
|
3864
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3865
|
-
else if (c === "]" || c === "}") {
|
|
3866
|
-
if (--depth < 0) return null;
|
|
3867
|
-
} else if (c === ")") {
|
|
3868
|
-
if (depth === 0) return i;
|
|
3869
|
-
depth--;
|
|
3870
|
-
}
|
|
3871
|
-
}
|
|
3872
|
-
return null;
|
|
3941
|
+
function markSpec(outer, open, close, ownSkip, strict, raw) {
|
|
3942
|
+
;
|
|
3943
|
+
outer._balancedSpec = { open, close, ownSkip, strict, raw };
|
|
3944
|
+
return outer;
|
|
3873
3945
|
}
|
|
3874
|
-
function
|
|
3875
|
-
const
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3946
|
+
function balanced(open, close, options = {}) {
|
|
3947
|
+
const ownSkip = options.skip ?? [];
|
|
3948
|
+
const strict = options.strict ?? false;
|
|
3949
|
+
const combi = buildBalancedInterior(open, close, ownSkip, strict);
|
|
3950
|
+
if (options.raw) return markSpec(token(combi), open, close, ownSkip, strict, true);
|
|
3951
|
+
const eagerParse = combi.parse.bind(combi);
|
|
3952
|
+
const cache = /* @__PURE__ */ new Map();
|
|
3953
|
+
combi._balancedAmbient = { open, close, ownSkip, strict };
|
|
3954
|
+
combi.parse = (input, pos, ctx) => {
|
|
3955
|
+
const amb = ctx.scanSkip;
|
|
3956
|
+
if (!amb || amb.length === 0) return eagerParse(input, pos, ctx);
|
|
3957
|
+
let interior = cache.get(amb);
|
|
3958
|
+
if (!interior) {
|
|
3959
|
+
interior = buildBalancedInterior(open, close, [...amb, ...ownSkip], strict);
|
|
3960
|
+
cache.set(amb, interior);
|
|
3880
3961
|
}
|
|
3881
|
-
|
|
3882
|
-
}
|
|
3883
|
-
return
|
|
3962
|
+
return interior.parse(input, pos, ctx);
|
|
3963
|
+
};
|
|
3964
|
+
return markSpec(token(combi), open, close, ownSkip, strict, false);
|
|
3884
3965
|
}
|
|
3885
|
-
function
|
|
3886
|
-
const
|
|
3887
|
-
|
|
3888
|
-
let
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
continue;
|
|
3895
|
-
}
|
|
3896
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
3897
|
-
const close = skipString(inner, i);
|
|
3898
|
-
if (close === null) return null;
|
|
3899
|
-
i = close;
|
|
3900
|
-
continue;
|
|
3901
|
-
}
|
|
3902
|
-
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3903
|
-
else if (c === ")" || c === "]" || c === "}") {
|
|
3904
|
-
if (--depth < 0) return null;
|
|
3905
|
-
} else if (c === "<") angle++;
|
|
3906
|
-
else if (c === ">") {
|
|
3907
|
-
if (--angle < 0) return null;
|
|
3908
|
-
} else if (c === "," && depth === 0 && angle === 0) {
|
|
3909
|
-
parts.push(inner.slice(last, i));
|
|
3910
|
-
last = i + 1;
|
|
3966
|
+
function buildBalancedInterior(open, close, skips, strict = false) {
|
|
3967
|
+
const self = ref();
|
|
3968
|
+
const stop = /* @__PURE__ */ new Set([open, close]);
|
|
3969
|
+
let bounded = true;
|
|
3970
|
+
for (const sk of skips) {
|
|
3971
|
+
const cs = firstSetClassChars(sk);
|
|
3972
|
+
if (cs === null) {
|
|
3973
|
+
bounded = false;
|
|
3974
|
+
break;
|
|
3911
3975
|
}
|
|
3976
|
+
for (const ch2 of cs) stop.add(ch2);
|
|
3912
3977
|
}
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
for (let i = 0; i < annotation.length; i++) {
|
|
3927
|
-
if (annotation[i] !== "=") continue;
|
|
3928
|
-
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
3929
|
-
i++;
|
|
3930
|
-
continue;
|
|
3931
|
-
}
|
|
3932
|
-
const prev = annotation[i - 1];
|
|
3933
|
-
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
3934
|
-
return true;
|
|
3978
|
+
const cls = [...stop].map(escapeClassChar).join("");
|
|
3979
|
+
const content = bounded ? regex(new RegExp(`[^${cls}]+`)) : regex(new RegExp(`[^${escapeClassChar(open)}${escapeClassChar(close)}]`));
|
|
3980
|
+
const inner = many(choice(self, ...skips, content));
|
|
3981
|
+
const closer = strict ? literal(close) : expect(literal(close));
|
|
3982
|
+
const combi = transform(
|
|
3983
|
+
sequence(literal(open), inner, closer),
|
|
3984
|
+
// parts: strings (content/self) or arrays (a sequence-shaped skip) or a
|
|
3985
|
+
// ParseError (recovered close). `c` is the close string or a ParseError.
|
|
3986
|
+
([o, parts, c]) => o + parts.map((p) => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")
|
|
3987
|
+
);
|
|
3988
|
+
if (combi._def.tag === "transform") {
|
|
3989
|
+
combi._def.fnSrc = '([o, parts, c]) => o + parts.map(p => typeof p === "string" ? p : Array.isArray(p) ? p.join("") : "").join("") + (typeof c === "string" ? c : "")';
|
|
3990
|
+
combi._def.recognitionOnly = true;
|
|
3935
3991
|
}
|
|
3936
|
-
|
|
3937
|
-
}
|
|
3938
|
-
|
|
3939
|
-
return
|
|
3992
|
+
;
|
|
3993
|
+
combi._balanced = { open, close };
|
|
3994
|
+
self.define(combi);
|
|
3995
|
+
return combi;
|
|
3940
3996
|
}
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
"
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
"foreign-source": "it is named in a module the resolver was never told about, so its offsets index no scope tree the resolver holds",
|
|
3950
|
-
"ambiguous-source": "two distinct registered modules hold byte-identical text, so that text no longer names the module its offsets index"
|
|
3951
|
-
};
|
|
3952
|
-
function unconfirmableReason(def, src) {
|
|
3953
|
-
const declared = def.buildArityUnresolved;
|
|
3954
|
-
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
3955
|
-
const s = src.trim();
|
|
3956
|
-
const params = s.slice(0, s.indexOf(")") + 1);
|
|
3957
|
-
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
3958
|
-
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
3959
|
-
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
3960
|
-
return "it names a binding this build could not resolve to a function declaration";
|
|
3997
|
+
function firstSetClassChars(c) {
|
|
3998
|
+
const fs = c._meta.firstSet;
|
|
3999
|
+
if (fs.kind === "empty") return [];
|
|
4000
|
+
if (fs.kind !== "ranges") return null;
|
|
4001
|
+
const out = [];
|
|
4002
|
+
for (const { lo, hi } of fs.ranges) {
|
|
4003
|
+
if (hi - lo > 8) return null;
|
|
4004
|
+
for (let cp = lo; cp <= hi; cp++) out.push(String.fromCodePoint(cp));
|
|
3961
4005
|
}
|
|
3962
|
-
return
|
|
3963
|
-
}
|
|
3964
|
-
function confirmedArityForDef(def) {
|
|
3965
|
-
if (def.buildArity !== void 0) return def.buildArity;
|
|
3966
|
-
const src = buildAnalysisSrc(def);
|
|
3967
|
-
const arity = confirmedBuildArity(src);
|
|
3968
|
-
if (arity !== null) return arity;
|
|
3969
|
-
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
3970
|
-
recordDegradation({
|
|
3971
|
-
code: "build-arity-unconfirmed",
|
|
3972
|
-
severity: "warn",
|
|
3973
|
-
where: `node("${def.type ?? "<inferred>"}")`,
|
|
3974
|
-
subject,
|
|
3975
|
-
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`,
|
|
3976
|
-
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"
|
|
3977
|
-
});
|
|
3978
|
-
return null;
|
|
3979
|
-
}
|
|
3980
|
-
function buildReadsRaw(def) {
|
|
3981
|
-
if (!def.build) return true;
|
|
3982
|
-
if (def.buildRawUnused === true) return false;
|
|
3983
|
-
const arity = confirmedArityForDef(def);
|
|
3984
|
-
if (arity === null) return true;
|
|
3985
|
-
return arity >= 4;
|
|
3986
|
-
}
|
|
3987
|
-
function buildReadsTrivia(def) {
|
|
3988
|
-
if (!def.build) return true;
|
|
3989
|
-
const arity = confirmedArityForDef(def);
|
|
3990
|
-
if (arity === null) return true;
|
|
3991
|
-
return arity >= 5;
|
|
4006
|
+
return out;
|
|
3992
4007
|
}
|
|
3993
|
-
function
|
|
3994
|
-
|
|
3995
|
-
const arity = confirmedArityForDef(def);
|
|
3996
|
-
if (arity === null) return true;
|
|
3997
|
-
return arity >= 6;
|
|
4008
|
+
function escapeClassChar(ch2) {
|
|
4009
|
+
return ch2.replace(/[\\\]^-]/g, "\\$&");
|
|
3998
4010
|
}
|
|
3999
4011
|
|
|
4000
4012
|
// src/compiler/fields.ts
|
|
@@ -4181,6 +4193,7 @@ var OP_COV = 40;
|
|
|
4181
4193
|
var OP_SCOPE_PLAIN = 41;
|
|
4182
4194
|
var OP_LEX_BODY = 42;
|
|
4183
4195
|
var OP_LEX_PROGRAM = 43;
|
|
4196
|
+
var OP_SOURCE_LEAF = 44;
|
|
4184
4197
|
var OP_DISPATCH = 25;
|
|
4185
4198
|
var OP_ROUTED = 26;
|
|
4186
4199
|
var OP_NAMES = {
|
|
@@ -4199,6 +4212,7 @@ var OP_NAMES = {
|
|
|
4199
4212
|
[OP_NOT]: "NOT",
|
|
4200
4213
|
[OP_PEEK]: "PEEK",
|
|
4201
4214
|
[OP_LEAF]: "LEAF",
|
|
4215
|
+
[OP_SOURCE_LEAF]: "SOURCE_LEAF",
|
|
4202
4216
|
[OP_EMPTY]: "EMPTY",
|
|
4203
4217
|
[OP_LIT_TRACK]: "LIT_TRACK",
|
|
4204
4218
|
[OP_RX_TRACK]: "RX_TRACK",
|
|
@@ -6047,6 +6061,7 @@ function childSlots(code, ip, out) {
|
|
|
6047
6061
|
case OP_NODE_TRACK:
|
|
6048
6062
|
case OP_FIELD:
|
|
6049
6063
|
case OP_LEAF:
|
|
6064
|
+
case OP_SOURCE_LEAF:
|
|
6050
6065
|
case OP_ARMGATE:
|
|
6051
6066
|
out.push(code[ip + 2]);
|
|
6052
6067
|
return true;
|
|
@@ -6142,7 +6157,7 @@ function transfer(code, ip, at, hostCst) {
|
|
|
6142
6157
|
}
|
|
6143
6158
|
if (op === OP_NODE || op === OP_NODE_TRACK) {
|
|
6144
6159
|
const flags = code[ip + 3];
|
|
6145
|
-
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
|
|
6160
|
+
const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && ((flags & ~128) === 2 || flags === 18 || flags === 34);
|
|
6146
6161
|
if (directChildren) {
|
|
6147
6162
|
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
|
|
6148
6163
|
}
|
|
@@ -6155,7 +6170,7 @@ function transfer(code, ip, at, hostCst) {
|
|
|
6155
6170
|
if (at.tri === TRI_NONE && !at.buf) return at;
|
|
6156
6171
|
return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
6157
6172
|
}
|
|
6158
|
-
if (op === OP_LEAF) {
|
|
6173
|
+
if (op === OP_LEAF || op === OP_SOURCE_LEAF) {
|
|
6159
6174
|
if (!at.buf) return at;
|
|
6160
6175
|
return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
|
|
6161
6176
|
}
|
|
@@ -6242,7 +6257,7 @@ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, th
|
|
|
6242
6257
|
depth++;
|
|
6243
6258
|
continue;
|
|
6244
6259
|
}
|
|
6245
|
-
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
6260
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
|
|
6246
6261
|
at = code[at + 2];
|
|
6247
6262
|
depth++;
|
|
6248
6263
|
continue;
|
|
@@ -6275,7 +6290,7 @@ function leadingScalarSequence(code, ip) {
|
|
|
6275
6290
|
at2 = code[at2 + 1];
|
|
6276
6291
|
continue;
|
|
6277
6292
|
}
|
|
6278
|
-
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
6293
|
+
if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
|
|
6279
6294
|
at2 = code[at2 + 2];
|
|
6280
6295
|
continue;
|
|
6281
6296
|
}
|
|
@@ -6308,7 +6323,7 @@ function leadingScalarSequence(code, ip) {
|
|
|
6308
6323
|
at = code[at + 2];
|
|
6309
6324
|
continue;
|
|
6310
6325
|
}
|
|
6311
|
-
if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
6326
|
+
if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
|
|
6312
6327
|
at = code[at + 2];
|
|
6313
6328
|
continue;
|
|
6314
6329
|
}
|
|
@@ -6338,7 +6353,7 @@ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
|
|
|
6338
6353
|
if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
|
|
6339
6354
|
return walk(code[at + 1], depth + 1);
|
|
6340
6355
|
}
|
|
6341
|
-
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
|
|
6356
|
+
if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || (op === OP_LEAF || op === OP_SOURCE_LEAF)) {
|
|
6342
6357
|
return walk(code[at + 2], depth + 1);
|
|
6343
6358
|
}
|
|
6344
6359
|
if (op === OP_SEQ || op === OP_SEQV) {
|
|
@@ -7224,8 +7239,10 @@ ${rootCap ? "ctx._rootTriviaCapture=sR\n" : ""}return v
|
|
|
7224
7239
|
}
|
|
7225
7240
|
/* ── boundaries ──────────────────────────────────────────────────────── */
|
|
7226
7241
|
case OP_TOKEN:
|
|
7227
|
-
case OP_LEAF:
|
|
7242
|
+
case OP_LEAF:
|
|
7243
|
+
case OP_SOURCE_LEAF: {
|
|
7228
7244
|
const isToken = op === OP_TOKEN;
|
|
7245
|
+
const capturesSource = isToken || op === OP_SOURCE_LEAF && hostCst;
|
|
7229
7246
|
const fn = isToken ? void 0 : fnRef(code[ip + 1]);
|
|
7230
7247
|
const child = link(isToken ? code[ip + 1] : code[ip + 2]);
|
|
7231
7248
|
const wasCap = L.buf ? "true" : "(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)";
|
|
@@ -7258,7 +7275,7 @@ ctx._triviaLog=sOtl
|
|
|
7258
7275
|
if(v===FAIL)return FAIL
|
|
7259
7276
|
const e=EC.e
|
|
7260
7277
|
const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
|
|
7261
|
-
if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
|
|
7278
|
+
if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:${capturesSource ? "input.slice(pos,e)" : "out"},span:{start:pos,end:e}})
|
|
7262
7279
|
EC.e=e
|
|
7263
7280
|
return out
|
|
7264
7281
|
}`;
|
|
@@ -7344,7 +7361,7 @@ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
|
|
|
7344
7361
|
const v=${child}(input,pos,ctx)
|
|
7345
7362
|
if(v!==FAIL)return v
|
|
7346
7363
|
${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
|
|
7347
|
-
if(ctx._fc===true)return FAIL
|
|
7364
|
+
${code[ip + 2] === 1 ? "ctx._fc=false" : "if(ctx._fc===true)return FAIL"}
|
|
7348
7365
|
ctx._fe=pos
|
|
7349
7366
|
return FAIL
|
|
7350
7367
|
}`;
|
|
@@ -7933,7 +7950,8 @@ return nd
|
|
|
7933
7950
|
const unwrap = (flags & 64) !== 0;
|
|
7934
7951
|
const trailingTrivia = (flags & 128) !== 0;
|
|
7935
7952
|
const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
|
|
7936
|
-
|
|
7953
|
+
const leanFlags = flags & ~128;
|
|
7954
|
+
if (!hostCst && !tracked && build !== void 0 && proj < 0 && (leanFlags === 2 || (flags === 18 || flags === 34))) {
|
|
7937
7955
|
const fields = flags === 18;
|
|
7938
7956
|
const collapseChildren = flags === 34;
|
|
7939
7957
|
const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
|
|
@@ -7978,7 +7996,8 @@ ctx._cstTriviaLog=undefined
|
|
|
7978
7996
|
ctx.captureTrivia=false
|
|
7979
7997
|
ctx._fields=${fields ? "[]" : "undefined"}
|
|
7980
7998
|
const v=${child}(input,pos,ctx)
|
|
7981
|
-
|
|
7999
|
+
${trailingTrivia && L.tri !== TRI_NONE ? `if(v!==FAIL${L.tri === TRI_UNKNOWN ? "&&ctx.trivia!==undefined" : ""})EC.e=consumeTrivia(input,EC.e,ctx)
|
|
8000
|
+
` : ""}const captured=_capturedFlatChildren(flat)
|
|
7982
8001
|
${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
|
|
7983
8002
|
ctx._cstBuf=sBuf
|
|
7984
8003
|
ctx._cstChildren=sCh
|
|
@@ -8374,7 +8393,7 @@ function assemble(t, prog, cfg) {
|
|
|
8374
8393
|
const lf = { _tag: "leaf", value, span: { start: s, end: e } };
|
|
8375
8394
|
pushCstLeaf(ctx, lf);
|
|
8376
8395
|
}
|
|
8377
|
-
function plainBuildNode(child, build) {
|
|
8396
|
+
function plainBuildNode(child, build, trailing) {
|
|
8378
8397
|
return (input, pos, ctx) => {
|
|
8379
8398
|
const sCh = ctx._cstChildren;
|
|
8380
8399
|
const sLv = ctx._cstLeaves;
|
|
@@ -8392,6 +8411,7 @@ function assemble(t, prog, cfg) {
|
|
|
8392
8411
|
ctx.captureTrivia = false;
|
|
8393
8412
|
ctx._fields = void 0;
|
|
8394
8413
|
const value = child(input, pos, ctx);
|
|
8414
|
+
if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
|
|
8395
8415
|
const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
|
|
8396
8416
|
const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
|
|
8397
8417
|
ctx._fields = savedFields;
|
|
@@ -8419,7 +8439,7 @@ function assemble(t, prog, cfg) {
|
|
|
8419
8439
|
while (first < children2.length && children2[first] === void 0) first++;
|
|
8420
8440
|
return first === children2.length ? EMPTY_CH : children2.slice(first);
|
|
8421
8441
|
}
|
|
8422
|
-
function childrenOnlyBuildNode(child, build) {
|
|
8442
|
+
function childrenOnlyBuildNode(child, build, trailing) {
|
|
8423
8443
|
return (input, pos, ctx) => {
|
|
8424
8444
|
const sCh = ctx._cstChildren;
|
|
8425
8445
|
const sLv = ctx._cstLeaves;
|
|
@@ -8437,6 +8457,7 @@ function assemble(t, prog, cfg) {
|
|
|
8437
8457
|
ctx.captureTrivia = false;
|
|
8438
8458
|
ctx._fields = void 0;
|
|
8439
8459
|
const value = child(input, pos, ctx);
|
|
8460
|
+
if (trailing && value !== FAIL && ctx.trivia !== void 0) EC.e = consumeTrivia(input, EC.e, ctx);
|
|
8440
8461
|
const captured = capturedFlatChildren(kids);
|
|
8441
8462
|
ctx._fields = savedFields;
|
|
8442
8463
|
ctx._cstBuf = sBuf;
|
|
@@ -9461,6 +9482,7 @@ function assemble(t, prog, cfg) {
|
|
|
9461
9482
|
/* ── transaction ─────────────────────────────────────────────────────── */
|
|
9462
9483
|
case OP_ATTEMPT: {
|
|
9463
9484
|
const child = link(code[ip + 1]);
|
|
9485
|
+
const contain = code[ip + 2] === 1;
|
|
9464
9486
|
return (input, pos, ctx) => {
|
|
9465
9487
|
const need = markCst(ctx);
|
|
9466
9488
|
const mRaw = MRAW;
|
|
@@ -9473,7 +9495,10 @@ function assemble(t, prog, cfg) {
|
|
|
9473
9495
|
const v = child(input, pos, ctx);
|
|
9474
9496
|
if (v !== FAIL) return v;
|
|
9475
9497
|
if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
|
|
9476
|
-
if (committed3(ctx))
|
|
9498
|
+
if (committed3(ctx)) {
|
|
9499
|
+
if (!contain) return FAIL;
|
|
9500
|
+
ctx._fc = false;
|
|
9501
|
+
}
|
|
9477
9502
|
ctx._fe = pos;
|
|
9478
9503
|
return FAIL;
|
|
9479
9504
|
};
|
|
@@ -9691,7 +9716,8 @@ function assemble(t, prog, cfg) {
|
|
|
9691
9716
|
return value;
|
|
9692
9717
|
};
|
|
9693
9718
|
}
|
|
9694
|
-
case OP_LEAF:
|
|
9719
|
+
case OP_LEAF:
|
|
9720
|
+
case OP_SOURCE_LEAF: {
|
|
9695
9721
|
const fn = fns[code[ip + 1]];
|
|
9696
9722
|
const child = link(code[ip + 2]);
|
|
9697
9723
|
return (input, pos, ctx) => {
|
|
@@ -9719,7 +9745,11 @@ function assemble(t, prog, cfg) {
|
|
|
9719
9745
|
if (v === FAIL) return FAIL;
|
|
9720
9746
|
const end = EC.e;
|
|
9721
9747
|
const out = fn(v, { start: pos, end });
|
|
9722
|
-
if (wasCapturing) pushCstLeaf(ctx, {
|
|
9748
|
+
if (wasCapturing) pushCstLeaf(ctx, {
|
|
9749
|
+
_tag: "leaf",
|
|
9750
|
+
value: op === OP_SOURCE_LEAF && hostCst ? input.slice(pos, end) : out,
|
|
9751
|
+
span: { start: pos, end }
|
|
9752
|
+
});
|
|
9723
9753
|
EC.e = end;
|
|
9724
9754
|
return out;
|
|
9725
9755
|
};
|
|
@@ -10919,11 +10949,11 @@ function assemble(t, prog, cfg) {
|
|
|
10919
10949
|
const trailingTrivia = (flags & 128) !== 0;
|
|
10920
10950
|
const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
|
|
10921
10951
|
if (!hostCst && !tracked) {
|
|
10922
|
-
if (build !== void 0 && proj < 0 && flags === 0) {
|
|
10923
|
-
return plainBuildNode(child, build);
|
|
10952
|
+
if (build !== void 0 && proj < 0 && (flags & ~128) === 0) {
|
|
10953
|
+
return plainBuildNode(child, build, trailingTrivia);
|
|
10924
10954
|
}
|
|
10925
|
-
if (build !== void 0 && proj < 0 && flags === 2) {
|
|
10926
|
-
return childrenOnlyBuildNode(child, build);
|
|
10955
|
+
if (build !== void 0 && proj < 0 && (flags & ~128) === 2) {
|
|
10956
|
+
return childrenOnlyBuildNode(child, build, trailingTrivia);
|
|
10927
10957
|
}
|
|
10928
10958
|
if (build !== void 0 && proj < 0 && flags === 18) {
|
|
10929
10959
|
return childrenOnlyFieldsBuildNode(child, build);
|
|
@@ -11801,10 +11831,12 @@ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
|
11801
11831
|
case "choice":
|
|
11802
11832
|
case "sequence":
|
|
11803
11833
|
return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
|
|
11834
|
+
// A contained transaction reports every failure uncommitted.
|
|
11835
|
+
case "attempt":
|
|
11836
|
+
return d.contain !== true && mayCommitFailure(d.parser, seen, resolve);
|
|
11804
11837
|
case "many":
|
|
11805
11838
|
case "oneOrMore":
|
|
11806
11839
|
case "optional":
|
|
11807
|
-
case "attempt":
|
|
11808
11840
|
case "transform":
|
|
11809
11841
|
case "label":
|
|
11810
11842
|
case "field":
|
|
@@ -13136,7 +13168,7 @@ var Encoder = class {
|
|
|
13136
13168
|
}
|
|
13137
13169
|
case "leaf": {
|
|
13138
13170
|
const child = this.node(d.parser).ip;
|
|
13139
|
-
return this.emit(OP_LEAF, this.fn(d.fn, d.fnSrc ?? null), child);
|
|
13171
|
+
return this.emit(d.cstValue === "source" ? OP_SOURCE_LEAF : OP_LEAF, this.fn(d.fn, d.fnSrc ?? null), child);
|
|
13140
13172
|
}
|
|
13141
13173
|
case "node": {
|
|
13142
13174
|
if (d.type === void 0) missingInferredType();
|
|
@@ -13148,7 +13180,7 @@ var Encoder = class {
|
|
|
13148
13180
|
const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
|
|
13149
13181
|
const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
|
|
13150
13182
|
const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
|
|
13151
|
-
const flags = (cstOut || d.captureTrivia === true ||
|
|
13183
|
+
const flags = (cstOut || d.captureTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
|
|
13152
13184
|
const body = this.emit(
|
|
13153
13185
|
this.track ? OP_NODE_TRACK : OP_NODE,
|
|
13154
13186
|
d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
|
|
@@ -13274,7 +13306,7 @@ var Encoder = class {
|
|
|
13274
13306
|
// A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
|
|
13275
13307
|
// lowering was correct only for a choice arm.
|
|
13276
13308
|
case "attempt": {
|
|
13277
|
-
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
|
|
13309
|
+
const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip, d.contain === true ? 1 : 0);
|
|
13278
13310
|
if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
|
|
13279
13311
|
const fs = d.parser._def.tag === "lazy" ? firstSetOf(d.parser, /* @__PURE__ */ new Set(), this.refResolver(), this.activeTrivia) : d.parser._meta.firstSet;
|
|
13280
13312
|
if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
|
|
@@ -13361,6 +13393,7 @@ var Encoder = class {
|
|
|
13361
13393
|
case OP_WITHCTX:
|
|
13362
13394
|
case OP_XFORM:
|
|
13363
13395
|
case OP_LEAF:
|
|
13396
|
+
case OP_SOURCE_LEAF:
|
|
13364
13397
|
case OP_NODE:
|
|
13365
13398
|
case OP_NODE_TRACK:
|
|
13366
13399
|
return [ip + 2];
|
|
@@ -13853,7 +13886,7 @@ function payloadKey(p, d) {
|
|
|
13853
13886
|
case "transform":
|
|
13854
13887
|
return `transform\0${fnKey(d.fnSrc, d.fn)}\0${d.recognitionOnly === true}`;
|
|
13855
13888
|
case "leaf":
|
|
13856
|
-
return `leaf\0${fnKey(d.fnSrc, d.fn)}`;
|
|
13889
|
+
return `leaf\0${d.cstValue ?? "value"}\0${fnKey(d.fnSrc, d.fn)}`;
|
|
13857
13890
|
case "many":
|
|
13858
13891
|
case "oneOrMore":
|
|
13859
13892
|
return `${d.tag}\0${d.min}\0${d.max ?? ""}`;
|