parseman 0.44.0 → 0.45.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/diagnose.d.ts +118 -0
- package/dist/analysis/diagnose.d.ts.map +1 -0
- package/dist/analysis/gating.d.ts +9 -9
- package/dist/analysis/gating.d.ts.map +1 -1
- package/dist/analysis/grammar.d.ts.map +1 -1
- package/dist/combinators/choice.d.ts.map +1 -1
- package/dist/combinators/dispatch.d.ts +19 -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/node.d.ts +19 -0
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +28 -0
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +80 -60
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/degradation.d.ts +123 -0
- package/dist/compiler/degradation.d.ts.map +1 -0
- package/dist/compiler/fields.d.ts.map +1 -1
- package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
- package/dist/compiler/inline-build.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +1 -1
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/coverage.d.ts +13 -0
- package/dist/coverage.d.ts.map +1 -1
- package/dist/cst/reflection.d.ts.map +1 -1
- package/dist/functional/run.d.ts.map +1 -1
- package/dist/index.cjs +707 -471
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +707 -471
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs +40 -30
- package/dist/language-service/index.cjs.map +3 -3
- package/dist/language-service/index.js +40 -30
- package/dist/language-service/index.js.map +3 -3
- package/dist/oracle/digest.d.ts +132 -6
- package/dist/oracle/digest.d.ts.map +1 -1
- package/dist/oracle/index.cjs +136 -305
- package/dist/oracle/index.cjs.map +4 -4
- package/dist/oracle/index.d.ts +43 -31
- package/dist/oracle/index.d.ts.map +1 -1
- package/dist/oracle/index.js +136 -305
- package/dist/oracle/index.js.map +4 -4
- package/dist/plugin/evaluator.d.ts +3 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.cjs +1127 -747
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts +18 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1127 -747
- package/dist/plugin/index.js.map +4 -4
- package/dist/plugin/reducer-resolver.d.ts +41 -0
- package/dist/plugin/reducer-resolver.d.ts.map +1 -0
- package/dist/run/index.cjs +33 -30
- package/dist/run/index.cjs.map +2 -2
- package/dist/run/index.js +33 -30
- package/dist/run/index.js.map +2 -2
- package/dist/spec/index.cjs +221 -34
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +221 -34
- package/dist/spec/index.js.map +4 -4
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +7 -3
- package/dist/combinators/guard.d.ts +0 -8
- package/dist/combinators/guard.d.ts.map +0 -1
- package/dist/cst/offset-model.d.ts +0 -119
- package/dist/cst/offset-model.d.ts.map +0 -1
- package/dist/oracle/corpus.d.ts +0 -32
- package/dist/oracle/corpus.d.ts.map +0 -1
- package/dist/oracle/identity.d.ts +0 -117
- package/dist/oracle/identity.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -21,7 +21,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
GRAMMAR_COVERAGE_DEFINITIONS: () => GRAMMAR_COVERAGE_DEFINITIONS,
|
|
24
|
-
OffsetIndex: () => OffsetIndex,
|
|
25
24
|
absoluteSpanAt: () => absoluteSpanAt,
|
|
26
25
|
absoluteSpanCST: () => absoluteSpanCST,
|
|
27
26
|
absolutize: () => absolutize,
|
|
@@ -37,16 +36,12 @@ __export(index_exports, {
|
|
|
37
36
|
applyEdit: () => applyEdit,
|
|
38
37
|
attempt: () => attempt,
|
|
39
38
|
balanced: () => balanced,
|
|
40
|
-
blankLinesIn: () => blankLinesIn,
|
|
41
39
|
buildLineIndex: () => buildLineIndex,
|
|
42
|
-
buildOffsetIndex: () => buildOffsetIndex,
|
|
43
40
|
buildRootTriviaIndex: () => buildRootTriviaIndex,
|
|
44
41
|
buildTriviaIndex: () => buildTriviaIndex,
|
|
45
42
|
charClassMembers: () => charClassMembers,
|
|
46
43
|
choice: () => choice,
|
|
47
44
|
classifiedTrivia: () => classifiedTrivia,
|
|
48
|
-
collectLeafSlots: () => collectLeafSlots,
|
|
49
|
-
commentsIn: () => commentsIn,
|
|
50
45
|
compile: () => compile,
|
|
51
46
|
compiledGrammarCoverageDefinitions: () => compiledGrammarCoverageDefinitions,
|
|
52
47
|
completionsAt: () => completionsAt,
|
|
@@ -59,6 +54,7 @@ __export(index_exports, {
|
|
|
59
54
|
createLineIndex: () => createLineIndex,
|
|
60
55
|
createVisitor: () => createVisitor,
|
|
61
56
|
cstBuildHost: () => cstBuildHost,
|
|
57
|
+
diagnoseGrammar: () => diagnoseGrammar,
|
|
62
58
|
dispatch: () => dispatch,
|
|
63
59
|
duplicationFindingCount: () => duplicationFindingCount,
|
|
64
60
|
endsWith: () => endsWith,
|
|
@@ -68,21 +64,15 @@ __export(index_exports, {
|
|
|
68
64
|
firstSetToString: () => firstSetToString,
|
|
69
65
|
formatDuplicationFindings: () => formatDuplicationFindings,
|
|
70
66
|
formatGatingWarnings: () => formatGatingWarnings,
|
|
71
|
-
|
|
72
|
-
gapText: () => gapText,
|
|
67
|
+
formatGrammarDiagnosis: () => formatGrammarDiagnosis,
|
|
73
68
|
gate: () => gate,
|
|
74
69
|
grammarCoverageDefinitions: () => grammarCoverageDefinitions,
|
|
75
|
-
guard: () => guard,
|
|
76
|
-
indentMixed: () => indentMixed,
|
|
77
|
-
indentWidth: () => indentWidth,
|
|
78
70
|
isParseError: () => isParseError,
|
|
79
71
|
keywordAlternationHazards: () => keywordAlternationHazards,
|
|
80
72
|
keywordRegexShape: () => keywordRegexShape,
|
|
81
73
|
keywords: () => keywords,
|
|
82
74
|
label: () => label,
|
|
83
75
|
leaf: () => leaf,
|
|
84
|
-
lineBreaksIn: () => lineBreaksIn,
|
|
85
|
-
lineStartWithin: () => lineStartWithin,
|
|
86
76
|
literal: () => literal,
|
|
87
77
|
makeWhen: () => makeWhen,
|
|
88
78
|
makeWord: () => makeWord,
|
|
@@ -181,8 +171,9 @@ function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
|
|
|
181
171
|
return d.value.length === 0;
|
|
182
172
|
case "keywords":
|
|
183
173
|
return false;
|
|
174
|
+
// The routed token itself is the selector's match, never empty; a fallback can be.
|
|
184
175
|
case "routed":
|
|
185
|
-
return false;
|
|
176
|
+
return d.fallback === void 0 ? false : me(d.fallback);
|
|
186
177
|
case "regex":
|
|
187
178
|
try {
|
|
188
179
|
const m = new RegExp(d.source).exec("");
|
|
@@ -1944,8 +1935,11 @@ function derive(c, seen) {
|
|
|
1944
1935
|
case "not":
|
|
1945
1936
|
case "peek":
|
|
1946
1937
|
return deriveExpected2(def.parser);
|
|
1938
|
+
// A bare routed() can only fail as "there is no routed token here". With a
|
|
1939
|
+
// fallback, THAT is the branch that can fail, so its expectations are the useful
|
|
1940
|
+
// ones — the routed path either succeeds or is not taken.
|
|
1947
1941
|
case "routed":
|
|
1948
|
-
return ["routed()"];
|
|
1942
|
+
return def.fallback === void 0 ? ["routed()"] : deriveExpected2(def.fallback);
|
|
1949
1943
|
case "lazy": {
|
|
1950
1944
|
const name = c._ruleName;
|
|
1951
1945
|
if (seen.has(c)) return name ? [name] : [];
|
|
@@ -2135,7 +2129,7 @@ function detectStrategy(parsers) {
|
|
|
2135
2129
|
function bareLeadingTermKey(term) {
|
|
2136
2130
|
const d = term._def;
|
|
2137
2131
|
if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
|
|
2138
|
-
if (d.tag === "regex") return `R:${d.source
|
|
2132
|
+
if (d.tag === "regex") return `R:${JSON.stringify([d.source, d.flags])}`;
|
|
2139
2133
|
return null;
|
|
2140
2134
|
}
|
|
2141
2135
|
function detectSharedPrefix(parsers) {
|
|
@@ -2393,17 +2387,21 @@ function makeWhen(opts = {}) {
|
|
|
2393
2387
|
function otherwise(parser2) {
|
|
2394
2388
|
return { kind: "otherwise", parser: parser2, usesRouted: parserUsesRouted(parser2) };
|
|
2395
2389
|
}
|
|
2396
|
-
function routed() {
|
|
2390
|
+
function routed(fallback) {
|
|
2397
2391
|
return {
|
|
2398
2392
|
_tag: "routed",
|
|
2399
|
-
_meta: {
|
|
2400
|
-
|
|
2393
|
+
_meta: {
|
|
2394
|
+
// The routed token is whatever the selector matched, so the first set stays
|
|
2395
|
+
// `any` even with a fallback — `any` already subsumes the fallback's.
|
|
2396
|
+
firstSet: { kind: "any" },
|
|
2397
|
+
canMatchNewline: fallback?._meta.canMatchNewline ?? false,
|
|
2398
|
+
isTrivia: false
|
|
2399
|
+
},
|
|
2400
|
+
_def: fallback === void 0 ? { tag: "routed" } : { tag: "routed", fallback },
|
|
2401
2401
|
parse(_input, pos, ctx) {
|
|
2402
2402
|
const item = ctx._routed;
|
|
2403
|
-
if (item === void 0) {
|
|
2404
|
-
|
|
2405
|
-
}
|
|
2406
|
-
if (pos !== item.span.start) {
|
|
2403
|
+
if (item === void 0 || pos !== item.span.start) {
|
|
2404
|
+
if (fallback !== void 0) return fallback.parse(_input, pos, ctx);
|
|
2407
2405
|
return { ok: false, expected: ["routed()"], span: { start: pos, end: pos } };
|
|
2408
2406
|
}
|
|
2409
2407
|
if (cstCaptureActive(ctx)) {
|
|
@@ -2947,12 +2945,12 @@ function markUnusedValues(root) {
|
|
|
2947
2945
|
}
|
|
2948
2946
|
};
|
|
2949
2947
|
const resolveRoot = (c) => {
|
|
2950
|
-
const
|
|
2948
|
+
const guard = /* @__PURE__ */ new Set();
|
|
2951
2949
|
let cur = c;
|
|
2952
|
-
while (!
|
|
2950
|
+
while (!guard.has(cur)) {
|
|
2953
2951
|
const d = cur._def;
|
|
2954
2952
|
if (d.tag !== "lazy") return cur;
|
|
2955
|
-
|
|
2953
|
+
guard.add(cur);
|
|
2956
2954
|
try {
|
|
2957
2955
|
cur = d.thunk();
|
|
2958
2956
|
} catch {
|
|
@@ -3121,10 +3119,11 @@ function childrenOf(def) {
|
|
|
3121
3119
|
return [def.main, def.skipped];
|
|
3122
3120
|
case "scanTo":
|
|
3123
3121
|
return [def.sentinel, ...def.skip];
|
|
3122
|
+
case "routed":
|
|
3123
|
+
return def.fallback ? [def.fallback] : [];
|
|
3124
3124
|
case "literal":
|
|
3125
3125
|
case "regex":
|
|
3126
3126
|
case "keywords":
|
|
3127
|
-
case "routed":
|
|
3128
3127
|
case "guard":
|
|
3129
3128
|
case "lazy":
|
|
3130
3129
|
case "unknown":
|
|
@@ -3350,54 +3349,271 @@ function peek(combinator) {
|
|
|
3350
3349
|
};
|
|
3351
3350
|
}
|
|
3352
3351
|
|
|
3352
|
+
// src/compiler/degradation.ts
|
|
3353
|
+
function formatDegradation(d) {
|
|
3354
|
+
return `[parseman] degraded [${d.code}] ${d.where}: ${d.subject} \u2014 ${d.fellBackTo}; otherwise ${d.otherwise}`;
|
|
3355
|
+
}
|
|
3356
|
+
var DETAIL_CAP = 8;
|
|
3357
|
+
function formatDegradations(list) {
|
|
3358
|
+
const byCode = /* @__PURE__ */ new Map();
|
|
3359
|
+
for (const d of list) {
|
|
3360
|
+
const bucket = byCode.get(d.code);
|
|
3361
|
+
if (bucket) bucket.push(d);
|
|
3362
|
+
else byCode.set(d.code, [d]);
|
|
3363
|
+
}
|
|
3364
|
+
const out = [];
|
|
3365
|
+
for (const [code, items] of byCode) {
|
|
3366
|
+
for (const d of items.slice(0, DETAIL_CAP)) out.push(formatDegradation(d));
|
|
3367
|
+
if (items.length > DETAIL_CAP) {
|
|
3368
|
+
out.push(
|
|
3369
|
+
`[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.`
|
|
3370
|
+
);
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
return out;
|
|
3374
|
+
}
|
|
3375
|
+
var _sinks = [];
|
|
3376
|
+
function beginDegradationCapture() {
|
|
3377
|
+
_sinks.push(/* @__PURE__ */ new Map());
|
|
3378
|
+
}
|
|
3379
|
+
function degradationCaptureDepth() {
|
|
3380
|
+
return _sinks.length;
|
|
3381
|
+
}
|
|
3382
|
+
function unwindDegradationCapture(depth) {
|
|
3383
|
+
const found = [];
|
|
3384
|
+
while (_sinks.length > depth) {
|
|
3385
|
+
const sink = _sinks.pop();
|
|
3386
|
+
found.unshift(...sink.values());
|
|
3387
|
+
}
|
|
3388
|
+
return found;
|
|
3389
|
+
}
|
|
3390
|
+
function resolveDegradationLevel(explicit) {
|
|
3391
|
+
if (explicit !== void 0) return explicit;
|
|
3392
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_DEGRADATION : void 0;
|
|
3393
|
+
if (env === "off" || env === "warn" || env === "error") return env;
|
|
3394
|
+
return "warn";
|
|
3395
|
+
}
|
|
3396
|
+
function degradationKey(d) {
|
|
3397
|
+
return JSON.stringify([d.code, d.where, d.subject]);
|
|
3398
|
+
}
|
|
3399
|
+
function recordDegradation(d) {
|
|
3400
|
+
const level = resolveDegradationLevel();
|
|
3401
|
+
if (level === "off") return;
|
|
3402
|
+
const key = degradationKey(d);
|
|
3403
|
+
const sink = _sinks[_sinks.length - 1];
|
|
3404
|
+
if (sink) {
|
|
3405
|
+
if (!sink.has(key)) sink.set(key, d);
|
|
3406
|
+
return;
|
|
3407
|
+
}
|
|
3408
|
+
if (_immediate.has(key)) return;
|
|
3409
|
+
_immediate.add(key);
|
|
3410
|
+
if (level === "error") throw new Error(`parseman: degraded compilation path
|
|
3411
|
+
${formatDegradation(d)}`);
|
|
3412
|
+
console.warn(formatDegradation(d));
|
|
3413
|
+
}
|
|
3414
|
+
var _immediate = /* @__PURE__ */ new Set();
|
|
3415
|
+
function beginCompileDegradationDrain() {
|
|
3416
|
+
if (resolveDegradationLevel() === "off" || _sinks.length > 0) return () => {
|
|
3417
|
+
};
|
|
3418
|
+
const depth = degradationCaptureDepth();
|
|
3419
|
+
beginDegradationCapture();
|
|
3420
|
+
return (report) => {
|
|
3421
|
+
const found = unwindDegradationCapture(depth);
|
|
3422
|
+
if (!report || found.length === 0) return;
|
|
3423
|
+
const fresh = found.filter((d) => {
|
|
3424
|
+
const k = degradationKey(d);
|
|
3425
|
+
if (_immediate.has(k)) return false;
|
|
3426
|
+
_immediate.add(k);
|
|
3427
|
+
return true;
|
|
3428
|
+
});
|
|
3429
|
+
if (fresh.length === 0) return;
|
|
3430
|
+
const lines = formatDegradations(fresh);
|
|
3431
|
+
if (resolveDegradationLevel() === "error") {
|
|
3432
|
+
throw new Error(`parseman: ${fresh.length} degraded compilation path(s)
|
|
3433
|
+
${lines.join("\n")}`);
|
|
3434
|
+
}
|
|
3435
|
+
for (const l of lines) console.warn(l);
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3353
3439
|
// src/compiler/build-arity.ts
|
|
3354
3440
|
function cstOutputHost(build) {
|
|
3355
3441
|
return build?._parsemanCstOutput === true;
|
|
3356
3442
|
}
|
|
3357
|
-
var
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
var CONFIRMABLE_PARAM_RE = /^[A-Za-z_$][\w$]*\s*\??\s*(?::[^,=]+)?$/;
|
|
3443
|
+
var SINGLE_IDENT_ARROW_RE = /^[A-Za-z_$][\w$]*\s*=>/;
|
|
3444
|
+
var PARAM_LIST_OPEN_RE = /^(?:function\b[^(]*)?\(/;
|
|
3445
|
+
var NATIVE_CODE_RE = /\{\s*\[native code\]\s*\}/;
|
|
3446
|
+
var PARAM_HEAD_RE = /^[A-Za-z_$][\w$]*\s*\??\s*/;
|
|
3362
3447
|
function confirmedBuildArity(src) {
|
|
3363
3448
|
const s = src.trim();
|
|
3364
|
-
|
|
3365
|
-
if (
|
|
3366
|
-
if (
|
|
3367
|
-
const inner = (
|
|
3368
|
-
if (inner ===
|
|
3369
|
-
|
|
3449
|
+
if (NATIVE_CODE_RE.test(s)) return null;
|
|
3450
|
+
if (/\barguments\b/.test(s)) return null;
|
|
3451
|
+
if (SINGLE_IDENT_ARROW_RE.test(s)) return 1;
|
|
3452
|
+
const inner = paramListText(s);
|
|
3453
|
+
if (inner === null) return null;
|
|
3454
|
+
if (inner.trim() === "") return 0;
|
|
3455
|
+
const parts = splitTopLevel(inner);
|
|
3456
|
+
if (parts === null) return null;
|
|
3370
3457
|
for (const part of parts) {
|
|
3371
|
-
if (!
|
|
3458
|
+
if (!isConfirmableParam(part.trim())) return null;
|
|
3372
3459
|
}
|
|
3373
|
-
if (/\barguments\b/.test(s)) return null;
|
|
3374
3460
|
return parts.length;
|
|
3375
3461
|
}
|
|
3462
|
+
function paramListText(s) {
|
|
3463
|
+
const open = PARAM_LIST_OPEN_RE.exec(s);
|
|
3464
|
+
if (!open) return null;
|
|
3465
|
+
const start = open[0].length;
|
|
3466
|
+
const end = matchingParen(s, start);
|
|
3467
|
+
if (end === null) return null;
|
|
3468
|
+
if (!s.startsWith("function") && !/^\s*=>/.test(s.slice(end + 1))) return null;
|
|
3469
|
+
return s.slice(start, end);
|
|
3470
|
+
}
|
|
3471
|
+
function matchingParen(s, start) {
|
|
3472
|
+
let depth = 0;
|
|
3473
|
+
for (let i = start; i < s.length; i++) {
|
|
3474
|
+
const c = s[i];
|
|
3475
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
3476
|
+
const close = skipString(s, i);
|
|
3477
|
+
if (close === null) return null;
|
|
3478
|
+
i = close;
|
|
3479
|
+
continue;
|
|
3480
|
+
}
|
|
3481
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3482
|
+
else if (c === "]" || c === "}") {
|
|
3483
|
+
if (--depth < 0) return null;
|
|
3484
|
+
} else if (c === ")") {
|
|
3485
|
+
if (depth === 0) return i;
|
|
3486
|
+
depth--;
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
return null;
|
|
3490
|
+
}
|
|
3491
|
+
function skipString(s, open) {
|
|
3492
|
+
const quote = s[open];
|
|
3493
|
+
for (let i = open + 1; i < s.length; i++) {
|
|
3494
|
+
if (s[i] === "\\") {
|
|
3495
|
+
i++;
|
|
3496
|
+
continue;
|
|
3497
|
+
}
|
|
3498
|
+
if (s[i] === quote) return i;
|
|
3499
|
+
}
|
|
3500
|
+
return null;
|
|
3501
|
+
}
|
|
3502
|
+
function splitTopLevel(inner) {
|
|
3503
|
+
const parts = [];
|
|
3504
|
+
let depth = 0;
|
|
3505
|
+
let angle = 0;
|
|
3506
|
+
let last = 0;
|
|
3507
|
+
for (let i = 0; i < inner.length; i++) {
|
|
3508
|
+
const c = inner[i];
|
|
3509
|
+
if (c === "=" && inner[i + 1] === ">") {
|
|
3510
|
+
i++;
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
3514
|
+
const close = skipString(inner, i);
|
|
3515
|
+
if (close === null) return null;
|
|
3516
|
+
i = close;
|
|
3517
|
+
continue;
|
|
3518
|
+
}
|
|
3519
|
+
if (c === "(" || c === "[" || c === "{") depth++;
|
|
3520
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
3521
|
+
if (--depth < 0) return null;
|
|
3522
|
+
} else if (c === "<") angle++;
|
|
3523
|
+
else if (c === ">") {
|
|
3524
|
+
if (--angle < 0) return null;
|
|
3525
|
+
} else if (c === "," && depth === 0 && angle === 0) {
|
|
3526
|
+
parts.push(inner.slice(last, i));
|
|
3527
|
+
last = i + 1;
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
if (depth !== 0 || angle !== 0) return null;
|
|
3531
|
+
parts.push(inner.slice(last));
|
|
3532
|
+
return parts;
|
|
3533
|
+
}
|
|
3534
|
+
function isConfirmableParam(part) {
|
|
3535
|
+
const head = PARAM_HEAD_RE.exec(part);
|
|
3536
|
+
if (!head) return false;
|
|
3537
|
+
const rest = part.slice(head[0].length);
|
|
3538
|
+
if (rest === "") return true;
|
|
3539
|
+
if (rest[0] !== ":") return false;
|
|
3540
|
+
return !hasDefaultAssign(rest.slice(1));
|
|
3541
|
+
}
|
|
3542
|
+
function hasDefaultAssign(annotation) {
|
|
3543
|
+
for (let i = 0; i < annotation.length; i++) {
|
|
3544
|
+
if (annotation[i] !== "=") continue;
|
|
3545
|
+
if (annotation[i + 1] === ">" || annotation[i + 1] === "=") {
|
|
3546
|
+
i++;
|
|
3547
|
+
continue;
|
|
3548
|
+
}
|
|
3549
|
+
const prev = annotation[i - 1];
|
|
3550
|
+
if (prev === "<" || prev === ">" || prev === "!" || prev === "=") continue;
|
|
3551
|
+
return true;
|
|
3552
|
+
}
|
|
3553
|
+
return false;
|
|
3554
|
+
}
|
|
3555
|
+
function buildAnalysisSrc(def) {
|
|
3556
|
+
return def.buildSigSrc ?? def.buildSrc ?? def.build.toString();
|
|
3557
|
+
}
|
|
3558
|
+
var RESOLVER_REASONS = {
|
|
3559
|
+
"rest-parameter": "its parameter list uses a rest parameter, so the declared arity is unbounded",
|
|
3560
|
+
"arguments": "its body references `arguments`",
|
|
3561
|
+
"reassigned": "the binding it names is reassigned, so the function read here is not decidable",
|
|
3562
|
+
"not-a-function": "the binding it names is not a function declaration",
|
|
3563
|
+
"unresolved-import": "its module could not be resolved or parsed",
|
|
3564
|
+
"not-found": "the name did not resolve to any binding",
|
|
3565
|
+
"computed": "it is a computed expression",
|
|
3566
|
+
"foreign-source": "it is named inside an imported factory, whose offsets the entry-file resolver cannot index"
|
|
3567
|
+
};
|
|
3568
|
+
function unconfirmableReason(def, src) {
|
|
3569
|
+
const declared = def.buildArityUnresolved;
|
|
3570
|
+
if (declared !== void 0 && RESOLVER_REASONS[declared]) return RESOLVER_REASONS[declared];
|
|
3571
|
+
const s = src.trim();
|
|
3572
|
+
const params = s.slice(0, s.indexOf(")") + 1);
|
|
3573
|
+
if (params.includes("...")) return RESOLVER_REASONS["rest-parameter"];
|
|
3574
|
+
if (/\barguments\b/.test(s)) return RESOLVER_REASONS["arguments"];
|
|
3575
|
+
if (/^[A-Za-z_$][\w$]*(\s*\.\s*[A-Za-z_$][\w$]*)?$/.test(s)) {
|
|
3576
|
+
return "it names a binding this build could not resolve to a function declaration";
|
|
3577
|
+
}
|
|
3578
|
+
return "its parameter list could not be parsed";
|
|
3579
|
+
}
|
|
3580
|
+
function confirmedArityForDef(def) {
|
|
3581
|
+
if (def.buildArity !== void 0) return def.buildArity;
|
|
3582
|
+
const src = buildAnalysisSrc(def);
|
|
3583
|
+
const arity = confirmedBuildArity(src);
|
|
3584
|
+
if (arity !== null) return arity;
|
|
3585
|
+
const subject = `build reducer \`${(def.buildSrc ?? "<runtime fn>").trim().split("\n")[0].slice(0, 60)}\``;
|
|
3586
|
+
recordDegradation({
|
|
3587
|
+
code: "build-arity-unconfirmed",
|
|
3588
|
+
severity: "warn",
|
|
3589
|
+
where: `node("${def.type ?? "<inferred>"}")`,
|
|
3590
|
+
subject,
|
|
3591
|
+
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`,
|
|
3592
|
+
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"
|
|
3593
|
+
});
|
|
3594
|
+
return null;
|
|
3595
|
+
}
|
|
3376
3596
|
function buildReadsChildren(def) {
|
|
3377
3597
|
if (!def.build) return true;
|
|
3378
|
-
const
|
|
3379
|
-
const arity = confirmedBuildArity(src);
|
|
3598
|
+
const arity = confirmedArityForDef(def);
|
|
3380
3599
|
if (arity === null) return true;
|
|
3381
3600
|
return arity >= 1;
|
|
3382
3601
|
}
|
|
3383
3602
|
function buildReadsRaw(def) {
|
|
3384
3603
|
if (!def.build) return true;
|
|
3385
|
-
const
|
|
3386
|
-
const arity = confirmedBuildArity(src);
|
|
3604
|
+
const arity = confirmedArityForDef(def);
|
|
3387
3605
|
if (arity === null) return true;
|
|
3388
3606
|
return arity >= 4;
|
|
3389
3607
|
}
|
|
3390
3608
|
function buildReadsTrivia(def) {
|
|
3391
3609
|
if (!def.build) return true;
|
|
3392
|
-
const
|
|
3393
|
-
const arity = confirmedBuildArity(src);
|
|
3610
|
+
const arity = confirmedArityForDef(def);
|
|
3394
3611
|
if (arity === null) return true;
|
|
3395
3612
|
return arity >= 5;
|
|
3396
3613
|
}
|
|
3397
3614
|
function buildReadsState(def) {
|
|
3398
3615
|
if (!def.build) return true;
|
|
3399
|
-
const
|
|
3400
|
-
const arity = confirmedBuildArity(src);
|
|
3616
|
+
const arity = confirmedArityForDef(def);
|
|
3401
3617
|
if (arity === null) return true;
|
|
3402
3618
|
return arity >= 6;
|
|
3403
3619
|
}
|
|
@@ -3405,8 +3621,7 @@ function buildReadsState(def) {
|
|
|
3405
3621
|
// src/compiler/fields.ts
|
|
3406
3622
|
function buildReadsFields(def) {
|
|
3407
3623
|
if (!def.build) return true;
|
|
3408
|
-
const
|
|
3409
|
-
const arity = confirmedBuildArity(src);
|
|
3624
|
+
const arity = confirmedArityForDef(def);
|
|
3410
3625
|
if (arity === null) return true;
|
|
3411
3626
|
return arity >= 2;
|
|
3412
3627
|
}
|
|
@@ -3587,6 +3802,13 @@ function isCstChild(value) {
|
|
|
3587
3802
|
function missingInferredType() {
|
|
3588
3803
|
throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
|
|
3589
3804
|
}
|
|
3805
|
+
function normalizeBuildArity(arity) {
|
|
3806
|
+
if (arity === void 0) return void 0;
|
|
3807
|
+
if (!Number.isInteger(arity) || arity < 0 || arity > 6) {
|
|
3808
|
+
throw new Error("node() buildArity must be an integer 0..6 (children, fields, span, rawChildren, triviaLog, state)");
|
|
3809
|
+
}
|
|
3810
|
+
return arity;
|
|
3811
|
+
}
|
|
3590
3812
|
function normalizeProject(project) {
|
|
3591
3813
|
if (project === void 0) return void 0;
|
|
3592
3814
|
if (!Number.isInteger(project) || project < 0) {
|
|
@@ -3622,13 +3844,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3622
3844
|
const captureTrivia = opts?.captureTrivia === true;
|
|
3623
3845
|
const trailingTrivia = opts?.trailingTrivia === true;
|
|
3624
3846
|
const tags = opts?.tags;
|
|
3847
|
+
const buildArity = normalizeBuildArity(opts?.buildArity);
|
|
3625
3848
|
if (unwrap && collapse) {
|
|
3626
3849
|
throw new Error("node() options cannot set both unwrap and collapse");
|
|
3627
3850
|
}
|
|
3628
3851
|
if (project !== void 0 && (unwrap || collapse)) {
|
|
3629
3852
|
throw new Error("node() options cannot combine project with unwrap or collapse");
|
|
3630
3853
|
}
|
|
3631
|
-
const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia || tags !== void 0 && tags.length > 0 ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {}, ...tags !== void 0 && tags.length > 0 ? { tags } : {} } : baseDef;
|
|
3854
|
+
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;
|
|
3632
3855
|
const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
|
|
3633
3856
|
const clonesState = build ? buildReadsState(def) : project === void 0;
|
|
3634
3857
|
const hasOwnFields = parserHasOwnFields(combinator);
|
|
@@ -3674,7 +3897,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
3674
3897
|
const cstOutput = cstOutputHost(ctx.build);
|
|
3675
3898
|
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
3676
3899
|
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
3677
|
-
const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !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 };
|
|
3900
|
+
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 };
|
|
3678
3901
|
const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
|
|
3679
3902
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
3680
3903
|
pushCstChild(ctx, built, rawEntry);
|
|
@@ -3869,7 +4092,7 @@ function leaf(root, fn) {
|
|
|
3869
4092
|
}
|
|
3870
4093
|
|
|
3871
4094
|
// src/version.ts
|
|
3872
|
-
var PARSEMAN_VERSION = "0.
|
|
4095
|
+
var PARSEMAN_VERSION = "0.45.0";
|
|
3873
4096
|
|
|
3874
4097
|
// src/cst/host-mode.ts
|
|
3875
4098
|
var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
|
|
@@ -4744,7 +4967,7 @@ function findDivergentSlot(members, shapeOf) {
|
|
|
4744
4967
|
const path = [];
|
|
4745
4968
|
const defs = [];
|
|
4746
4969
|
let cur = [...members];
|
|
4747
|
-
for (let
|
|
4970
|
+
for (let guard = 0; guard < 64; guard++) {
|
|
4748
4971
|
const d0 = cur[0]._def;
|
|
4749
4972
|
const kidLists = cur.map((c) => childrenOf2(c._def));
|
|
4750
4973
|
const arity = kidLists[0].length;
|
|
@@ -5703,7 +5926,15 @@ function children(def, winners) {
|
|
|
5703
5926
|
let resolved;
|
|
5704
5927
|
try {
|
|
5705
5928
|
resolved = def.thunk();
|
|
5706
|
-
} catch {
|
|
5929
|
+
} catch (e) {
|
|
5930
|
+
recordDegradation({
|
|
5931
|
+
code: "coverage-definitions-unavailable",
|
|
5932
|
+
severity: "warn",
|
|
5933
|
+
where: "<lazy rule reference>",
|
|
5934
|
+
subject: `unresolvable reference (${e.message})`,
|
|
5935
|
+
fellBackTo: "the coverage walk stopped at this reference, so every definition below it is ABSENT from the denominator \u2014 which raises the reported ratio rather than lowering it",
|
|
5936
|
+
otherwise: "the referenced rule and its whole subtree would contribute definitions"
|
|
5937
|
+
});
|
|
5707
5938
|
return [];
|
|
5708
5939
|
}
|
|
5709
5940
|
const name = resolved._ruleName;
|
|
@@ -7204,27 +7435,53 @@ function emitScannableTerminal(shape, c) {
|
|
|
7204
7435
|
}
|
|
7205
7436
|
|
|
7206
7437
|
// src/compiler/inline-build.ts
|
|
7207
|
-
var
|
|
7438
|
+
var ANN = String.raw`\s*\??\s*(?::[^,)=]+)?`;
|
|
7439
|
+
var ANY_P = String.raw`\w+${ANN}`;
|
|
7440
|
+
var MK_BUILD_RE = new RegExp(
|
|
7441
|
+
String.raw`^\(\s*(\w+)${ANN}\s*,\s*${ANY_P}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*\)\s*=>\s*mk\s*\(\s*(['"])([^'"]+)\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
7442
|
+
);
|
|
7208
7443
|
function escapeRegExp(s) {
|
|
7209
7444
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7210
7445
|
}
|
|
7446
|
+
function identMkBuildRe(typeIdent) {
|
|
7447
|
+
return new RegExp(
|
|
7448
|
+
String.raw`^\(\s*(\w+)${ANN}\s*,\s*${ANY_P}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*\)\s*=>\s*(?:[\w$.]*\.)?mk\s*\(\s*${escapeRegExp(typeIdent)}\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
7449
|
+
);
|
|
7450
|
+
}
|
|
7211
7451
|
function looseMkBuildRe(type) {
|
|
7212
7452
|
return new RegExp(
|
|
7213
|
-
String.raw`^\(\s*(\w+)\s*,\s
|
|
7453
|
+
String.raw`^\(\s*(\w+)${ANN}\s*,\s*${ANY_P}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*,\s*(\w+)${ANN}\s*\)\s*=>\s*.+\(\s*(['"])${escapeRegExp(type)}\5\s*,\s*\1\s*,\s*\3\s*,\s*\2\s*,\s*\4\s*\)\s*$`
|
|
7214
7454
|
);
|
|
7215
7455
|
}
|
|
7456
|
+
var LOOKS_LIKE_MK_RE = /=>\s*(?:[\w$.]*\.)?mk\s*\(/;
|
|
7216
7457
|
function analyzeMkInlineBuild(def) {
|
|
7217
7458
|
if (!def.build) return null;
|
|
7218
7459
|
if (def.type === void 0) return null;
|
|
7219
|
-
const src = (def
|
|
7460
|
+
const src = buildAnalysisSrc(def).trim();
|
|
7220
7461
|
const strict = src.match(MK_BUILD_RE);
|
|
7221
7462
|
if (strict) {
|
|
7222
7463
|
const mkType = strict[6];
|
|
7223
|
-
|
|
7464
|
+
if (mkType === def.type) return def.type;
|
|
7465
|
+
reportMkMiss(def.type, src, `it builds a "${mkType}" node, not "${def.type}"`);
|
|
7466
|
+
return null;
|
|
7224
7467
|
}
|
|
7225
7468
|
if (looseMkBuildRe(def.type).test(src)) return def.type;
|
|
7469
|
+
if (def.typeSrc !== void 0 && identMkBuildRe(def.typeSrc).test(src)) return def.type;
|
|
7470
|
+
if (LOOKS_LIKE_MK_RE.test(src)) {
|
|
7471
|
+
reportMkMiss(def.type, src, "its parameter list or argument order does not match `(children, fields, span, rawChildren, triviaLog) => mk(type, children, rawChildren, span, triviaLog)`");
|
|
7472
|
+
}
|
|
7226
7473
|
return null;
|
|
7227
7474
|
}
|
|
7475
|
+
function reportMkMiss(type, src, why) {
|
|
7476
|
+
recordDegradation({
|
|
7477
|
+
code: "mk-inline-missed",
|
|
7478
|
+
severity: "warn",
|
|
7479
|
+
where: `node("${type}")`,
|
|
7480
|
+
subject: `build reducer \`${src.split("\n")[0].slice(0, 80)}\``,
|
|
7481
|
+
fellBackTo: `looks like an inline-\`mk\` builder but ${why}, so every match pays a \`_build[n](...)\` call instead of an inlined object literal`,
|
|
7482
|
+
otherwise: "the node object would be constructed at the call site with no call frame"
|
|
7483
|
+
});
|
|
7484
|
+
}
|
|
7228
7485
|
function emitInlineMkNodeExpr(type, chV, rawV, spanExpr, tlV) {
|
|
7229
7486
|
return `{ _tag: 'node', type: ${JSON.stringify(type)}, span: ${spanExpr}, children: ${chV}, rawCount: ${rawV}.length, localTriviaLen: ${tlV}.length }`;
|
|
7230
7487
|
}
|
|
@@ -7407,10 +7664,34 @@ function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
|
|
|
7407
7664
|
seen.delete(p);
|
|
7408
7665
|
}
|
|
7409
7666
|
}
|
|
7667
|
+
function tern(cond, whenTrue, whenFalse) {
|
|
7668
|
+
if (cond === "false") return whenFalse;
|
|
7669
|
+
if (cond === "true") return whenTrue;
|
|
7670
|
+
return `${cond} ? ${whenTrue} : ${whenFalse}`;
|
|
7671
|
+
}
|
|
7672
|
+
function notGate(cond) {
|
|
7673
|
+
if (cond === "false") return "true";
|
|
7674
|
+
if (cond === "true") return "false";
|
|
7675
|
+
return `!(${cond})`;
|
|
7676
|
+
}
|
|
7677
|
+
function orGate(a, b) {
|
|
7678
|
+
if (a === "false") return b;
|
|
7679
|
+
if (b === "false") return a;
|
|
7680
|
+
if (a === "true" || b === "true") return "true";
|
|
7681
|
+
return `${a} || ${b}`;
|
|
7682
|
+
}
|
|
7683
|
+
function andGate(a, b) {
|
|
7684
|
+
if (a === "false" || b === "false") return "false";
|
|
7685
|
+
if (a === "true") return b;
|
|
7686
|
+
if (b === "true") return a;
|
|
7687
|
+
return `${a} && ${b}`;
|
|
7688
|
+
}
|
|
7410
7689
|
var HOST_READS_DECL = "const _hostReads = (b, n) => { if (b === undefined) return false; let s; try { s = Function.prototype.toString.call(b) } catch (e) { return true } if (/\\barguments\\b/.test(s)) return true; const m = /^[^(]*\\(([\\s\\S]*?)\\)/.exec(s); if (m && /\\.\\.\\.|=/.test(m[1])) return true; return b.length > n }";
|
|
7690
|
+
var RAW_ENTRY_DECL = "const _rawEntry = (v, input, s, e, span) => (typeof v === 'object' && v !== null && (v._tag === 'node' || v._tag === 'leaf' || v._tag === 'parseError')) ? v : { _tag: 'leaf', value: typeof v === 'string' ? v : (typeof v === 'object' && v !== null ? input.slice(s, e) : ''), span: span ?? { start: s, end: e } }";
|
|
7411
7691
|
var LINE_TRACK_DECL = "const _trackLines = (_ctx, input, start, end) => { const from = _ctx._lineScannedTo ?? 0; if (end <= from) return; for (let i = from; i < end; i++) if (input.charCodeAt(i) === 10) _ctx._lineStarts.push(i + 1); _ctx._lineScannedTo = end }";
|
|
7412
7692
|
var LINE_SPAN_DECL = "const _lineCol = (_ctx, offset) => { const starts = _ctx._lineStarts; let lo = 0, hi = starts.length - 1; while (lo < hi) { const mid = (lo + hi + 1) >> 1; if (starts[mid] <= offset) lo = mid; else hi = mid - 1 } return [lo + 1, offset - starts[lo] + 1] }\nconst _spanLines = (_ctx, start, end) => { const s = _lineCol(_ctx, start), e = _lineCol(_ctx, end); return { start, end, startLine: s[0], startColumn: s[1], endLine: e[0], endColumn: e[1] } }";
|
|
7413
7693
|
var _loweringSink = null;
|
|
7694
|
+
var _inlineCapSink = null;
|
|
7414
7695
|
function hasSelectedRootTrivia(ctx) {
|
|
7415
7696
|
return ctx.rootTriviaClassified === true;
|
|
7416
7697
|
}
|
|
@@ -8159,9 +8440,11 @@ function emitSeqValues(def, ctx, pos) {
|
|
|
8159
8440
|
const markLog = v(ctx, "_mklg");
|
|
8160
8441
|
const markRootLog = hasSelectedRootTrivia(ctx) ? v(ctx, "_mkrlg") : null;
|
|
8161
8442
|
const scanEndV = v(ctx, "_sne");
|
|
8162
|
-
const
|
|
8443
|
+
const logV = v(ctx, "_tlg");
|
|
8444
|
+
const capArg = ctx.noHoist ? "0" : hasSelectedRootTrivia(ctx) ? `(${logV} !== undefined || _ctx._rootTriviaLog !== undefined) ? 2 : 0` : `${logV} !== undefined ? 2 : 0`;
|
|
8163
8445
|
stmts.push(
|
|
8164
|
-
`${ind(ctx)}const ${
|
|
8446
|
+
`${ind(ctx)}const ${logV} = _ctx._triviaLog`,
|
|
8447
|
+
`${ind(ctx)}const ${markLog} = ${logV} !== undefined ? ${logV}.length : 0`,
|
|
8165
8448
|
...markRootLog ? [`${ind(ctx)}const ${markRootLog} = _ctx._rootTriviaLog ? _ctx._rootTriviaLog.length : 0`] : [],
|
|
8166
8449
|
`${ind(ctx)}const ${scanEndV} = ${trivFn}(input, ${curV}, _ctx, ${capArg})`,
|
|
8167
8450
|
...emitLineTrack(ctx, curV, scanEndV)
|
|
@@ -8171,7 +8454,7 @@ function emitSeqValues(def, ctx, pos) {
|
|
|
8171
8454
|
const endAfterV = v(ctx, "_sea");
|
|
8172
8455
|
stmts.push(
|
|
8173
8456
|
`${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
|
|
8174
|
-
`${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}; else { if (
|
|
8457
|
+
`${ind(ctx)}if (${endAfterV} > ${scanEndV}) ${curV} = ${endAfterV}; else { if (${logV} !== undefined && ${logV}.length !== ${markLog}) ${logV}.length = ${markLog};${markRootLog ? ` if (_ctx._rootTriviaLog && _ctx._rootTriviaLog.length !== ${markRootLog}) _ctx._rootTriviaLog.length = ${markRootLog};` : ""} }`
|
|
8175
8458
|
);
|
|
8176
8459
|
valueVars.push(r2.valueVar);
|
|
8177
8460
|
continue;
|
|
@@ -9243,9 +9526,18 @@ function emitPeek(def, ctx, pos) {
|
|
|
9243
9526
|
endVar: pos
|
|
9244
9527
|
};
|
|
9245
9528
|
}
|
|
9246
|
-
function emitRouted(ctx, pos) {
|
|
9529
|
+
function emitRouted(ctx, pos, def) {
|
|
9247
9530
|
const local = ctx.routedLocal;
|
|
9531
|
+
const fallback = def.fallback;
|
|
9248
9532
|
if (local !== void 0) {
|
|
9533
|
+
if (fallback !== void 0 && local.startVar !== pos) {
|
|
9534
|
+
return emitRoutedWithFallback(ctx, pos, fallback, {
|
|
9535
|
+
test: `${local.startVar} === ${pos}`,
|
|
9536
|
+
valExpr: local.valueVar,
|
|
9537
|
+
startExpr: local.startVar,
|
|
9538
|
+
endExpr: local.endVar
|
|
9539
|
+
});
|
|
9540
|
+
}
|
|
9249
9541
|
return {
|
|
9250
9542
|
stmts: [
|
|
9251
9543
|
...emitIfFail(ctx, `${local.startVar} !== ${pos}`, failBody(ctx, '"routed()"', pos)),
|
|
@@ -9256,9 +9548,19 @@ function emitRouted(ctx, pos) {
|
|
|
9256
9548
|
};
|
|
9257
9549
|
}
|
|
9258
9550
|
const item = v(ctx, "_rt");
|
|
9551
|
+
const read = `${ind(ctx)}const ${item} = _ctx._routed`;
|
|
9552
|
+
if (fallback !== void 0) {
|
|
9553
|
+
const r = emitRoutedWithFallback(ctx, pos, fallback, {
|
|
9554
|
+
test: `${item} !== undefined && ${item}.span.start === ${pos}`,
|
|
9555
|
+
valExpr: `${item}.value`,
|
|
9556
|
+
startExpr: `${item}.span.start`,
|
|
9557
|
+
endExpr: `${item}.span.end`
|
|
9558
|
+
});
|
|
9559
|
+
return { ...r, stmts: [read, ...r.stmts] };
|
|
9560
|
+
}
|
|
9259
9561
|
return {
|
|
9260
9562
|
stmts: [
|
|
9261
|
-
|
|
9563
|
+
read,
|
|
9262
9564
|
...emitIfFail(ctx, `${item} === undefined || ${item}.span.start !== ${pos}`, failBody(ctx, '"routed()"', pos)),
|
|
9263
9565
|
...emitLeafCapture(ctx, `${item}.value`, `${item}.span.start`, `${item}.span.end`)
|
|
9264
9566
|
],
|
|
@@ -9266,6 +9568,30 @@ function emitRouted(ctx, pos) {
|
|
|
9266
9568
|
endVar: `${item}.span.end`
|
|
9267
9569
|
};
|
|
9268
9570
|
}
|
|
9571
|
+
function emitRoutedWithFallback(ctx, pos, fallback, routed2) {
|
|
9572
|
+
const valV = v(ctx, "_rtv");
|
|
9573
|
+
const endV = v(ctx, "_rte");
|
|
9574
|
+
const i = ind(ctx);
|
|
9575
|
+
ctx.indent++;
|
|
9576
|
+
const capture = emitLeafCapture(ctx, routed2.valExpr, routed2.startExpr, routed2.endExpr);
|
|
9577
|
+
const fb = emit(fallback, ctx, pos);
|
|
9578
|
+
const inner = ind(ctx);
|
|
9579
|
+
ctx.indent--;
|
|
9580
|
+
return {
|
|
9581
|
+
stmts: [
|
|
9582
|
+
`${i}let ${valV}, ${endV}`,
|
|
9583
|
+
`${i}if (${routed2.test}) {`,
|
|
9584
|
+
...capture,
|
|
9585
|
+
`${inner}${valV} = ${routed2.valExpr}; ${endV} = ${routed2.endExpr}`,
|
|
9586
|
+
`${i}} else {`,
|
|
9587
|
+
...fb.stmts,
|
|
9588
|
+
`${inner}${valV} = ${fb.valueVar}; ${endV} = ${fb.endVar}`,
|
|
9589
|
+
`${i}}`
|
|
9590
|
+
],
|
|
9591
|
+
valueVar: valV,
|
|
9592
|
+
endVar: endV
|
|
9593
|
+
};
|
|
9594
|
+
}
|
|
9269
9595
|
function escapeTokenLiteral(value) {
|
|
9270
9596
|
return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
|
9271
9597
|
}
|
|
@@ -9447,22 +9773,16 @@ function emitNode(def, ctx, pos) {
|
|
|
9447
9773
|
const smk = structural ? v(ctx, "_smk") : null;
|
|
9448
9774
|
if (structural) ctx.needsHostReads = true;
|
|
9449
9775
|
const hostTriviaGate = `_ctx.build !== undefined && (_ctx.build._parsemanCaptureTrivia !== undefined ? _ctx.build._parsemanCaptureTrivia(${JSON.stringify(def.type)}) : (_ctx._pmCapTL ??= _hostReads(_ctx.build, 5)))`;
|
|
9450
|
-
const
|
|
9451
|
-
const
|
|
9452
|
-
const profileRecognizer = recV;
|
|
9453
|
-
const profileCapture = capV;
|
|
9454
|
-
const cstMode = ctx.hostMode === "cst";
|
|
9455
|
-
const directCstV = !structural && !cstMode && (!capturesChildren || !capturesRaw) ? v(ctx, "_dcst") : null;
|
|
9456
|
-
const directCstGate = directCstV === null ? "false" : profileCapture;
|
|
9776
|
+
const profileRecognizer = "false";
|
|
9777
|
+
const profileCapture = "false";
|
|
9457
9778
|
const structuralCapturesTrivia = structural && (def.captureTrivia === true || def.trailingTrivia === true);
|
|
9458
9779
|
const chNeededExpr = def.unwrap || def.collapse ? "true" : `(_ctx._pmReadsCh ??= (_ctx.build === undefined || _ctx.build._parsemanReadsChildren !== false || _ctx.build._parsemanCstCollapse !== undefined))`;
|
|
9459
|
-
const chAlloc = def.unwrap || def.collapse ?
|
|
9460
|
-
const
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
` : ""}${i}const ${chV} = ${profileRecognizer} ? undefined : ${capturesChildren ? "[]" : `${directCstV} ? [] : undefined`}, ${rawV} = ${profileRecognizer} ? undefined : ${capturesRaw ? "[]" : `${directCstV} ? [] : undefined`}`;
|
|
9780
|
+
const chAlloc = def.unwrap || def.collapse ? tern(profileRecognizer, "undefined", "[]") : tern(profileRecognizer, "undefined", `${tern(orGate(profileCapture, chNeededExpr), "[]", "undefined")}`);
|
|
9781
|
+
const dcstAlloc = "undefined";
|
|
9782
|
+
const allocStmt = structural ? `${i}const ${capTLv} = ${andGate(notGate(profileRecognizer), orGate(profileCapture, structuralCapturesTrivia ? "true" : hostTriviaGate))}, ${capSTv} = ${andGate(notGate(orGate(profileRecognizer, profileCapture)), "(_ctx._pmCapST ??= (_ctx.build === undefined || _hostReads(_ctx.build, 6)))")}${capFv ? `, ${capFv} = ${andGate(notGate(profileRecognizer), orGate(profileCapture, "(_ctx.build !== undefined && _hostReads(_ctx.build, 2))"))}` : ""}
|
|
9783
|
+
${i}const ${chV} = ${chAlloc}, ${rawV} = ${tern(profileRecognizer, "undefined", "[]")}, ${tlV} = ${tern(profileRecognizer, "undefined", innerEnablesTriviaCapture ? "[]" : `${capTLv} ? [] : _EMPTY_TL`)}` : capturesTrivia ? `${i}const ${capTLv} = ${notGate(profileRecognizer)}, ${chV} = ${tern(profileRecognizer, "undefined", capturesChildren ? "[]" : dcstAlloc)}, ${rawV} = ${tern(profileRecognizer, "undefined", capturesRaw ? "[]" : dcstAlloc)}, ${tlV} = ${tern(profileRecognizer, "undefined", "[]")}` : `${i}const ${chV} = ${tern(profileRecognizer, "undefined", capturesChildren ? "[]" : dcstAlloc)}, ${rawV} = ${tern(profileRecognizer, "undefined", capturesRaw ? "[]" : dcstAlloc)}`;
|
|
9464
9784
|
const innerTl = structural || capturesTrivia ? structural && !innerEnablesTriviaCapture ? `${capTLv} ? ${tlV} : undefined` : tlV : "undefined";
|
|
9465
|
-
const fieldsOn = structural ? capFv ?? "false" :
|
|
9785
|
+
const fieldsOn = structural ? capFv ?? "false" : tern(profileRecognizer, "false", capturesFields ? "true" : "false");
|
|
9466
9786
|
const sf = hasFields ? v(ctx, "_sf") : null;
|
|
9467
9787
|
const fArr = hasFields ? v(ctx, "_fa") : null;
|
|
9468
9788
|
const fObj = hasFields ? v(ctx, "_fields") : "undefined";
|
|
@@ -9471,7 +9791,7 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
|
|
|
9471
9791
|
const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
|
|
9472
9792
|
const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
|
|
9473
9793
|
const preGuard = [];
|
|
9474
|
-
if (!ctx.recovery && !ctx.coverage &&
|
|
9794
|
+
if (!ctx.recovery && !ctx.coverage && needsFirstSetGuard(def.parser)) {
|
|
9475
9795
|
const gcV = v(ctx, "_ngc");
|
|
9476
9796
|
const gExp = armStaticExpected(ctx, def.parser);
|
|
9477
9797
|
const gFail = ctx.failLabel ? ctx.recordFail ? `{ _ctx._fe = ${pos}; _ctx._fx = ${gExp}; break ${ctx.failLabel} }` : `break ${ctx.failLabel}` : failReturnArr(ctx, gExp, pos);
|
|
@@ -9482,7 +9802,6 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
|
|
|
9482
9802
|
}
|
|
9483
9803
|
const stmts = [
|
|
9484
9804
|
...preGuard,
|
|
9485
|
-
profHoist,
|
|
9486
9805
|
allocStmt,
|
|
9487
9806
|
`${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
|
|
9488
9807
|
`${i}_ctx._cstChildren = ${chV}; _ctx._cstLeaves = ${chV}; _ctx._cstRawChildren = ${rawV}${installTrivia}${sf ? `; _ctx._fields = ${fieldsOn} ? [] : undefined` : ""}`
|
|
@@ -9499,21 +9818,13 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
|
|
|
9499
9818
|
}
|
|
9500
9819
|
stmts.push(`${i}_ctx._cstChildren = ${sc}; _ctx._cstLeaves = ${sl}; _ctx._cstRawChildren = ${sr}${restoreTrivia}${sf ? `; _ctx._fields = ${sf}` : ""}`);
|
|
9501
9820
|
stmts.push(...emitIfFail(ctx, `!${okVar}`, propagateFailBody(ctx)));
|
|
9502
|
-
stmts.push(
|
|
9503
|
-
`${i}if (_ctx._pmProfile) {`,
|
|
9504
|
-
`${i} _ctx._pmProfile.nodes++`,
|
|
9505
|
-
`${i} if (${profileCapture}) {`,
|
|
9506
|
-
`${i} _ctx._pmProfile.childSlots += ${chV}.length; _ctx._pmProfile.rawSlots += ${rawV}.length; _ctx._pmProfile.triviaSlots += ${tlV}.length${fArr ? `; _ctx._pmProfile.fieldSlots += ${fArr} ? ${fArr}.length : 0` : ""}`,
|
|
9507
|
-
`${i} }`,
|
|
9508
|
-
`${i}}`
|
|
9509
|
-
);
|
|
9510
9821
|
let stV = "undefined";
|
|
9511
9822
|
if (structural) {
|
|
9512
9823
|
stV = v(ctx, "_nst");
|
|
9513
9824
|
stmts.push(`${i}const ${stV} = ${capSTv} && _ctx.state !== undefined ? Object.assign({}, _ctx.state) : undefined`);
|
|
9514
9825
|
} else if (clonesState) {
|
|
9515
9826
|
stV = v(ctx, "_nst");
|
|
9516
|
-
stmts.push(`${i}const ${stV} =
|
|
9827
|
+
stmts.push(`${i}const ${stV} = ${andGate(notGate(orGate(profileRecognizer, profileCapture)), "_ctx.state !== undefined")} ? Object.assign({}, _ctx.state) : undefined`);
|
|
9517
9828
|
}
|
|
9518
9829
|
if (sf && fArr) {
|
|
9519
9830
|
const fe = v(ctx, "_fe");
|
|
@@ -9537,19 +9848,22 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
|
|
|
9537
9848
|
if (ctx.lineTracking) stmts.push(`${i}const ${nodeSpanV} = ${nodeSpanExpr}`);
|
|
9538
9849
|
const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: ${nodeSpanV}, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, nodeSpanV, tlV) : def.project !== void 0 ? emitNodeProjectExpr(def.type, def.project, chV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, ${nodeSpanV}, ${rawV}, ${tlV}, ${stV})`;
|
|
9539
9850
|
const hostBuildArgs = `${JSON.stringify(def.type)}, ${chV}, ${fObj}, ${nodeSpanV}, ${rawV}, ${tlV}, ${stV}${def.tags !== void 0 && def.tags.length > 0 ? `, ${JSON.stringify(def.tags)}` : ""}`;
|
|
9540
|
-
const hostBuildExpr = `_ctx.
|
|
9851
|
+
const hostBuildExpr = `_ctx.build(${hostBuildArgs})`;
|
|
9541
9852
|
const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : cstOut ? hostBuildExpr : buildExpr;
|
|
9542
|
-
const
|
|
9853
|
+
const hostCollapses = structural || cstOut;
|
|
9854
|
+
const hostCollapseExpr = hostCollapses ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
|
|
9543
9855
|
const unwrapExpr = `${chV}.length === 1 ? (${chV}[0] !== null && typeof ${chV}[0] === 'object' && ${chV}[0]._tag === 'leaf' ? ${chV}[0].value : ${chV}[0]) : (${ndExpr})`;
|
|
9544
9856
|
const collapseExpr = `${chV}.length === 1 ? ${chV}[0] : (${ndExpr})`;
|
|
9545
9857
|
const finalExpr = def.unwrap ? unwrapExpr : def.collapse ? collapseExpr : hostCollapseExpr;
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
);
|
|
9858
|
+
const ndGate = orGate(profileRecognizer, profileCapture);
|
|
9859
|
+
const recGate = notGate(profileRecognizer);
|
|
9860
|
+
const pushIndent = recGate === "true" ? i : `${i} `;
|
|
9861
|
+
const pushCh = `${pushIndent}if (${sc}) ${sc}.push(${ndV})`;
|
|
9862
|
+
ctx.needsRawEntry = true;
|
|
9863
|
+
const pushRaw = `${pushIndent}if (${sr}) ${sr}.push(_rawEntry(${ndV}, input, ${pos}, ${endVar}${ctx.lineTracking ? `, ${nodeSpanV}` : ""}))`;
|
|
9864
|
+
stmts.push(`${i}const ${ndV} = ${tern(ndGate, "undefined", `(${finalExpr})`)}`);
|
|
9865
|
+
if (recGate === "true") stmts.push(pushCh, pushRaw);
|
|
9866
|
+
else stmts.push(`${i}if (${recGate}) {`, pushCh, pushRaw, `${i}}`);
|
|
9553
9867
|
return { stmts, valueVar: ndV, endVar };
|
|
9554
9868
|
}
|
|
9555
9869
|
function emitRuntimeFallback(parser2, ctx, pos) {
|
|
@@ -9578,7 +9892,12 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
9578
9892
|
} catch {
|
|
9579
9893
|
return emitRuntimeFallback(p, ctx, pos);
|
|
9580
9894
|
}
|
|
9581
|
-
|
|
9895
|
+
const cost = usage.sizes.get(resolved) ?? 1;
|
|
9896
|
+
if (cost <= ctx.inlineLeft) {
|
|
9897
|
+
ctx.inlineLeft -= cost;
|
|
9898
|
+
return emit(resolved, ctx, pos);
|
|
9899
|
+
}
|
|
9900
|
+
_inlineCapSink?.push({ fn: ctx.currentFnName ?? "<root>", nodes: cost });
|
|
9582
9901
|
}
|
|
9583
9902
|
if (!ctx.namedParsers.has(p)) {
|
|
9584
9903
|
const fnName2 = canonical2 ?? `${nsp(ctx)}_pf${ctx.namedParsers.size}`;
|
|
@@ -9593,6 +9912,9 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
9593
9912
|
const savedIndent = ctx.indent;
|
|
9594
9913
|
const savedFailLabel = ctx.failLabel;
|
|
9595
9914
|
const savedRecord = ctx.recordFail;
|
|
9915
|
+
const savedInlineLeft = ctx.inlineLeft, savedFnName = ctx.currentFnName;
|
|
9916
|
+
ctx.inlineLeft = ctx.inlineMax;
|
|
9917
|
+
ctx.currentFnName = fnName2;
|
|
9596
9918
|
const failureRuleId = p === ctx.coverage?.entry ? void 0 : ctx.coverage?.plan.rules.get(p) ?? ctx.coverage?.plan.rules.get(resolved);
|
|
9597
9919
|
const savedActiveRule = ctx.activeCoverageRuleId;
|
|
9598
9920
|
const savedSuppressFailure = ctx.suppressCoverageFailure;
|
|
@@ -9607,6 +9929,8 @@ function emitLazy(p, def, ctx, pos) {
|
|
|
9607
9929
|
ctx.indent = savedIndent;
|
|
9608
9930
|
ctx.failLabel = savedFailLabel;
|
|
9609
9931
|
ctx.recordFail = savedRecord;
|
|
9932
|
+
ctx.inlineLeft = savedInlineLeft;
|
|
9933
|
+
ctx.currentFnName = savedFnName;
|
|
9610
9934
|
ctx.activeCoverageRuleId = savedActiveRule;
|
|
9611
9935
|
ctx.suppressCoverageFailure = savedSuppressFailure;
|
|
9612
9936
|
pushNamedFnDecl(ctx, fnName2, r.stmts, r.valueVar, r.endVar, failureRuleId);
|
|
@@ -9701,6 +10025,9 @@ function emit(p, ctx, pos) {
|
|
|
9701
10025
|
const savedIndent = ctx.indent;
|
|
9702
10026
|
const savedFailLabel = ctx.failLabel;
|
|
9703
10027
|
const savedRecord = ctx.recordFail;
|
|
10028
|
+
const savedInlineLeft = ctx.inlineLeft, savedFnName = ctx.currentFnName;
|
|
10029
|
+
ctx.inlineLeft = ctx.inlineMax;
|
|
10030
|
+
ctx.currentFnName = fnName;
|
|
9704
10031
|
ctx.indent = 1;
|
|
9705
10032
|
ctx.failLabel = "_pfail";
|
|
9706
10033
|
ctx.recordFail = true;
|
|
@@ -9708,6 +10035,8 @@ function emit(p, ctx, pos) {
|
|
|
9708
10035
|
ctx.indent = savedIndent;
|
|
9709
10036
|
ctx.failLabel = savedFailLabel;
|
|
9710
10037
|
ctx.recordFail = savedRecord;
|
|
10038
|
+
ctx.inlineLeft = savedInlineLeft;
|
|
10039
|
+
ctx.currentFnName = savedFnName;
|
|
9711
10040
|
pushNamedFnDecl(ctx, fnName, r.stmts, r.valueVar, r.endVar);
|
|
9712
10041
|
return instrument(emitNamedFnCall(ctx, fnName, pos));
|
|
9713
10042
|
}
|
|
@@ -9901,7 +10230,7 @@ function emitDispatch(p, ctx, pos) {
|
|
|
9901
10230
|
case "peek":
|
|
9902
10231
|
return emitPeek(def, ctx, pos);
|
|
9903
10232
|
case "routed":
|
|
9904
|
-
return emitRouted(ctx, pos);
|
|
10233
|
+
return emitRouted(ctx, pos, def);
|
|
9905
10234
|
case "node":
|
|
9906
10235
|
return emitNode(def, ctx, pos);
|
|
9907
10236
|
case "scanTo":
|
|
@@ -9936,6 +10265,9 @@ function emitDispatch(p, ctx, pos) {
|
|
|
9936
10265
|
const savedIndent = ctx.indent;
|
|
9937
10266
|
const savedFailLabel = ctx.failLabel;
|
|
9938
10267
|
const savedRecord = ctx.recordFail;
|
|
10268
|
+
const savedInlineLeft = ctx.inlineLeft, savedFnName = ctx.currentFnName;
|
|
10269
|
+
ctx.inlineLeft = ctx.inlineMax;
|
|
10270
|
+
ctx.currentFnName = fnName;
|
|
9939
10271
|
ctx.indent = 1;
|
|
9940
10272
|
ctx.failLabel = "_pfail";
|
|
9941
10273
|
ctx.recordFail = true;
|
|
@@ -9943,6 +10275,8 @@ function emitDispatch(p, ctx, pos) {
|
|
|
9943
10275
|
ctx.indent = savedIndent;
|
|
9944
10276
|
ctx.failLabel = savedFailLabel;
|
|
9945
10277
|
ctx.recordFail = savedRecord;
|
|
10278
|
+
ctx.inlineLeft = savedInlineLeft;
|
|
10279
|
+
ctx.currentFnName = savedFnName;
|
|
9946
10280
|
pushNamedFnDecl(ctx, fnName, innerR.stmts, innerR.valueVar, innerR.endVar);
|
|
9947
10281
|
}
|
|
9948
10282
|
const fn = ctx.namedParsers.get(innerParser);
|
|
@@ -10101,12 +10435,16 @@ function childrenOf3(def) {
|
|
|
10101
10435
|
return [def.parser, def.sentinel];
|
|
10102
10436
|
case "scanTo":
|
|
10103
10437
|
return [def.sentinel, ...def.skip];
|
|
10438
|
+
// A `routed()` fallback IS emitted at this site (emitRouted), so the usage
|
|
10439
|
+
// analysis must see the edge — otherwise a fallback shared by several routed()
|
|
10440
|
+
// sites is miscounted as single-use and inlined at each.
|
|
10441
|
+
case "routed":
|
|
10442
|
+
return def.fallback ? [def.fallback] : [];
|
|
10104
10443
|
case "lazy":
|
|
10105
10444
|
case "literal":
|
|
10106
10445
|
case "regex":
|
|
10107
10446
|
case "keywords":
|
|
10108
10447
|
case "guard":
|
|
10109
|
-
case "routed":
|
|
10110
10448
|
case "unknown":
|
|
10111
10449
|
return [];
|
|
10112
10450
|
}
|
|
@@ -10127,6 +10465,17 @@ function isHoistableTag(tag) {
|
|
|
10127
10465
|
return HOISTABLE_TAGS.has(tag);
|
|
10128
10466
|
}
|
|
10129
10467
|
var HOIST_MIN_SUBTREE = 3;
|
|
10468
|
+
var INLINE_MAX_NODES = 1e3;
|
|
10469
|
+
function resolveInlineMax(explicit) {
|
|
10470
|
+
if (explicit !== void 0) return explicit;
|
|
10471
|
+
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_MAX_INLINE : void 0;
|
|
10472
|
+
if (env !== void 0 && env !== "") {
|
|
10473
|
+
if (env === "off" || env === "infinity") return Infinity;
|
|
10474
|
+
const n = Number(env);
|
|
10475
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
10476
|
+
}
|
|
10477
|
+
return INLINE_MAX_NODES;
|
|
10478
|
+
}
|
|
10130
10479
|
function analyzeLazyUsage(root) {
|
|
10131
10480
|
return analyzeLazyUsageMulti([root]);
|
|
10132
10481
|
}
|
|
@@ -10232,102 +10581,6 @@ function ruleDependencies(ruleMap) {
|
|
|
10232
10581
|
}
|
|
10233
10582
|
return deps;
|
|
10234
10583
|
}
|
|
10235
|
-
function resolveGatingLevel(opt) {
|
|
10236
|
-
const explicit = typeof opt === "string" ? opt : opt?.level;
|
|
10237
|
-
if (explicit !== void 0) return explicit;
|
|
10238
|
-
const env = typeof process !== "undefined" ? process.env?.PARSEMAN_GATING : void 0;
|
|
10239
|
-
if (env === "off" || env === "warn" || env === "error") return env;
|
|
10240
|
-
return "warn";
|
|
10241
|
-
}
|
|
10242
|
-
function runGatingDiagnostic(combinator, opt) {
|
|
10243
|
-
return reportGating(opt, (o) => analyzeGating(combinator, o));
|
|
10244
|
-
}
|
|
10245
|
-
function runGatingDiagnosticRules(ruleMap, opt) {
|
|
10246
|
-
return reportGating(opt, (o) => analyzeGatingRules(ruleMap, o));
|
|
10247
|
-
}
|
|
10248
|
-
function runFusedGatingDiagnostic(getRuleMaps, opt, getOpaque) {
|
|
10249
|
-
if (resolveGatingLevel(opt) === "off") return void 0;
|
|
10250
|
-
const ruleMaps = getRuleMaps();
|
|
10251
|
-
const opaque = getOpaque?.() ?? [];
|
|
10252
|
-
const opaqueFindings = opaque.map((o) => ({
|
|
10253
|
-
rule: o.ruleNames.length > 0 ? o.ruleNames.join(", ") : `<artifact ${o.ns}>`,
|
|
10254
|
-
kind: "opaque-artifact",
|
|
10255
|
-
reason: `precompiled artifact "${o.ns}" carries compiled rule functions, not re-lowerable IR \u2014 its choices were not examined at this fuse.`
|
|
10256
|
-
}));
|
|
10257
|
-
if (!ruleMaps.some((map) => hasExternalRuleRef(map))) {
|
|
10258
|
-
if (opaqueFindings.length === 0) return void 0;
|
|
10259
|
-
return reportGating(opt, () => ({
|
|
10260
|
-
totalChoices: 0,
|
|
10261
|
-
gated: 0,
|
|
10262
|
-
recoverable: 0,
|
|
10263
|
-
unanalysable: opaqueFindings,
|
|
10264
|
-
ungated: [],
|
|
10265
|
-
accepted: [],
|
|
10266
|
-
deferred: [],
|
|
10267
|
-
acceptedUnused: [],
|
|
10268
|
-
choices: [],
|
|
10269
|
-
antiPatterns: []
|
|
10270
|
-
}));
|
|
10271
|
-
}
|
|
10272
|
-
const winners = /* @__PURE__ */ new Map();
|
|
10273
|
-
for (const map of ruleMaps) for (const [name, rule] of map) {
|
|
10274
|
-
if (rule._def.tag === "lazy") {
|
|
10275
|
-
try {
|
|
10276
|
-
rule._def.thunk();
|
|
10277
|
-
} catch {
|
|
10278
|
-
continue;
|
|
10279
|
-
}
|
|
10280
|
-
}
|
|
10281
|
-
winners.set(name, rule);
|
|
10282
|
-
}
|
|
10283
|
-
const entries = [...winners];
|
|
10284
|
-
return reportGating(opt, (o) => {
|
|
10285
|
-
const deferredHere = new Set(analyzeGatingRules(entries, o).deferred.map((c) => c.id));
|
|
10286
|
-
const fused = analyzeGatingRules(entries, { ...o, resolveRef: (name) => winners.get(name) });
|
|
10287
|
-
return {
|
|
10288
|
-
...fused,
|
|
10289
|
-
ungated: fused.ungated.filter((c) => deferredHere.has(c.id)),
|
|
10290
|
-
antiPatterns: [],
|
|
10291
|
-
unanalysable: [...fused.unanalysable, ...opaqueFindings]
|
|
10292
|
-
};
|
|
10293
|
-
});
|
|
10294
|
-
}
|
|
10295
|
-
function reportGating(opt, analyze) {
|
|
10296
|
-
const level = resolveGatingLevel(opt);
|
|
10297
|
-
if (level === "off") return void 0;
|
|
10298
|
-
const obj = opt !== null && typeof opt === "object" ? opt : void 0;
|
|
10299
|
-
const analyzeOpts = obj?.accept !== void 0 || obj?.entryName !== void 0 ? { ...obj.accept !== void 0 ? { accept: obj.accept } : {}, ...obj.entryName !== void 0 ? { entryName: obj.entryName } : {} } : void 0;
|
|
10300
|
-
let report;
|
|
10301
|
-
try {
|
|
10302
|
-
report = analyze(analyzeOpts);
|
|
10303
|
-
} catch (e) {
|
|
10304
|
-
const reason = e instanceof Error ? `${e.name}: ${e.message}` : String(e);
|
|
10305
|
-
const failed = {
|
|
10306
|
-
totalChoices: 0,
|
|
10307
|
-
gated: 0,
|
|
10308
|
-
recoverable: 0,
|
|
10309
|
-
unanalysable: [{ rule: "<whole grammar>", kind: "not-a-combinator", reason: `gating analysis threw \u2014 ${reason}` }],
|
|
10310
|
-
ungated: [],
|
|
10311
|
-
accepted: [],
|
|
10312
|
-
deferred: [],
|
|
10313
|
-
acceptedUnused: [],
|
|
10314
|
-
choices: [],
|
|
10315
|
-
antiPatterns: []
|
|
10316
|
-
};
|
|
10317
|
-
const failLines = formatGatingWarnings(failed);
|
|
10318
|
-
if (level === "error") throw new Error(`parseman: gating analysis FAILED (no verdict available)
|
|
10319
|
-
${failLines.join("\n")}`);
|
|
10320
|
-
for (const l of failLines) console.warn(l);
|
|
10321
|
-
return failed;
|
|
10322
|
-
}
|
|
10323
|
-
const lines = formatGatingWarnings(report);
|
|
10324
|
-
if (lines.length > 0) {
|
|
10325
|
-
if (level === "error") throw new Error(`parseman: ${report.ungated.length} ungated hot choice(s) / ${report.antiPatterns.length} anti-pattern(s) / ${report.unanalysable.length} unanalysable rule(s)
|
|
10326
|
-
${lines.join("\n")}`);
|
|
10327
|
-
for (const l of lines) console.warn(l);
|
|
10328
|
-
}
|
|
10329
|
-
return report;
|
|
10330
|
-
}
|
|
10331
10584
|
function resolveDuplicationLevel(opt) {
|
|
10332
10585
|
const explicit = typeof opt === "string" ? opt : opt?.level;
|
|
10333
10586
|
if (explicit !== void 0) return explicit;
|
|
@@ -10370,7 +10623,17 @@ function runDuplicationDiagnosticRules(ruleMap, opt) {
|
|
|
10370
10623
|
return reportDuplication(opt, (o) => analyzeDuplicationRules(ruleMap, o));
|
|
10371
10624
|
}
|
|
10372
10625
|
function compile(combinator, mapFnSources, opts) {
|
|
10373
|
-
const
|
|
10626
|
+
const drain = beginCompileDegradationDrain();
|
|
10627
|
+
let completed = false;
|
|
10628
|
+
try {
|
|
10629
|
+
const compiled = compileImpl(combinator, mapFnSources, opts);
|
|
10630
|
+
completed = true;
|
|
10631
|
+
return compiled;
|
|
10632
|
+
} finally {
|
|
10633
|
+
drain(completed);
|
|
10634
|
+
}
|
|
10635
|
+
}
|
|
10636
|
+
function compileImpl(combinator, mapFnSources, opts) {
|
|
10374
10637
|
runDuplicationDiagnostic(combinator, opts?.duplication);
|
|
10375
10638
|
markUnusedValues(combinator);
|
|
10376
10639
|
const grammarTrivia = combinator._meta.grammarTrivia;
|
|
@@ -10378,9 +10641,12 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
10378
10641
|
const grammarScanSkip = combinator._meta.grammarScanSkip;
|
|
10379
10642
|
const grammarHostMode = combinator._meta.grammarHostMode;
|
|
10380
10643
|
const grammarTrackLines = combinator._meta.grammarTrackLines;
|
|
10644
|
+
const _inlineMax = resolveInlineMax(opts?.maxInline);
|
|
10381
10645
|
const ctx = {
|
|
10382
10646
|
vars: 0,
|
|
10383
10647
|
indent: 1,
|
|
10648
|
+
inlineMax: _inlineMax,
|
|
10649
|
+
inlineLeft: _inlineMax,
|
|
10384
10650
|
regexDecls: [],
|
|
10385
10651
|
regexMap: /* @__PURE__ */ new Map(),
|
|
10386
10652
|
expectedDecls: [],
|
|
@@ -10426,11 +10692,13 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
10426
10692
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? [...namedFnPrelude(), ""] : [];
|
|
10427
10693
|
const emptyTlDecls = ctx.needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [];
|
|
10428
10694
|
const hostReadsDecls = ctx.needsHostReads ? [HOST_READS_DECL] : [];
|
|
10695
|
+
const rawEntryDecls = ctx.needsRawEntry ? [RAW_ENTRY_DECL] : [];
|
|
10429
10696
|
const lineTrackDecls = ctx.needsLineTrack ? [LINE_TRACK_DECL] : [];
|
|
10430
10697
|
const lineSpanDecls = ctx.needsLineSpan ? [LINE_SPAN_DECL] : [];
|
|
10431
10698
|
const source = [
|
|
10432
10699
|
...emptyTlDecls,
|
|
10433
10700
|
...hostReadsDecls,
|
|
10701
|
+
...rawEntryDecls,
|
|
10434
10702
|
...lineTrackDecls,
|
|
10435
10703
|
...lineSpanDecls,
|
|
10436
10704
|
...ctx.regexDecls,
|
|
@@ -10445,6 +10713,7 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
10445
10713
|
const fn = new Function("input", "_pos", "_rp", "_mf", "_build", "_ctx", [
|
|
10446
10714
|
...emptyTlDecls,
|
|
10447
10715
|
...hostReadsDecls,
|
|
10716
|
+
...rawEntryDecls,
|
|
10448
10717
|
...lineTrackDecls,
|
|
10449
10718
|
...lineSpanDecls,
|
|
10450
10719
|
...ctx.regexDecls,
|
|
@@ -10494,8 +10763,7 @@ function compile(combinator, mapFnSources, opts) {
|
|
|
10494
10763
|
const compiledMeta = {
|
|
10495
10764
|
source,
|
|
10496
10765
|
inlineExpression,
|
|
10497
|
-
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions }
|
|
10498
|
-
...gatingReport === void 0 ? {} : { gating: gatingReport }
|
|
10766
|
+
...ctx.coverage === void 0 ? {} : { coverageDefinitions: ctx.coverage.plan.definitions }
|
|
10499
10767
|
};
|
|
10500
10768
|
if (!ctx.lineTracking) {
|
|
10501
10769
|
return {
|
|
@@ -10561,7 +10829,6 @@ function publicRuleWrapperSource(rule, fnSource, ambientTriviaKindLabels, ambien
|
|
|
10561
10829
|
}
|
|
10562
10830
|
function compileLinkable(ruleMapArg, ns, opts) {
|
|
10563
10831
|
if (!ns) throw new Error("compileLinkable: ns must be a non-empty namespace");
|
|
10564
|
-
if (opts?.gating !== void 0) runGatingDiagnosticRules(ruleMapArg, opts.gating);
|
|
10565
10832
|
if (opts?.duplication !== void 0) runDuplicationDiagnosticRules(ruleMapArg, opts.duplication);
|
|
10566
10833
|
for (const [, rule] of ruleMapArg) markUnusedValues(rule);
|
|
10567
10834
|
const grammarTrivia = opts?.trivia ?? ruleMapArg.map(([, r]) => r._meta.grammarTrivia).find(Boolean);
|
|
@@ -10580,9 +10847,12 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
10580
10847
|
}
|
|
10581
10848
|
});
|
|
10582
10849
|
const nodeMeta = new Map(ruleMap.map(([name, rule]) => [name, collectGrammarReflection([[name, rule]], { followLazy: false })]));
|
|
10850
|
+
const _inlineMax = resolveInlineMax(opts?.maxInline);
|
|
10583
10851
|
const ctx = {
|
|
10584
10852
|
vars: 0,
|
|
10585
10853
|
indent: 1,
|
|
10854
|
+
inlineMax: _inlineMax,
|
|
10855
|
+
inlineLeft: _inlineMax,
|
|
10586
10856
|
regexDecls: [],
|
|
10587
10857
|
regexMap: /* @__PURE__ */ new Map(),
|
|
10588
10858
|
expectedDecls: [],
|
|
@@ -10678,6 +10948,9 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
10678
10948
|
}
|
|
10679
10949
|
}
|
|
10680
10950
|
const savedIndent = ctx.indent, savedFail = ctx.failLabel, savedRec = ctx.recordFail;
|
|
10951
|
+
const savedInlineLeft = ctx.inlineLeft, savedFnName = ctx.currentFnName;
|
|
10952
|
+
ctx.inlineLeft = ctx.inlineMax;
|
|
10953
|
+
ctx.currentFnName = fn;
|
|
10681
10954
|
ctx.indent = 1;
|
|
10682
10955
|
ctx.failLabel = "_pfail";
|
|
10683
10956
|
ctx.recordFail = true;
|
|
@@ -10693,6 +10966,8 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
10693
10966
|
ctx.indent = savedIndent;
|
|
10694
10967
|
ctx.failLabel = savedFail;
|
|
10695
10968
|
ctx.recordFail = savedRec;
|
|
10969
|
+
ctx.inlineLeft = savedInlineLeft;
|
|
10970
|
+
ctx.currentFnName = savedFnName;
|
|
10696
10971
|
const ruleId = ctx.coverage?.plan.rules.get(rule);
|
|
10697
10972
|
const stmts = ruleId === void 0 ? body.stmts : [
|
|
10698
10973
|
`${ind(ctx)}_ctx._grammarCoverage?.(${JSON.stringify(ruleId)})`,
|
|
@@ -10777,6 +11052,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
10777
11052
|
deps: ruleDependencies(ruleMap),
|
|
10778
11053
|
needsEmptyTl: !!ctx.needsEmptyTl,
|
|
10779
11054
|
needsHostReads: !!ctx.needsHostReads,
|
|
11055
|
+
needsRawEntry: !!ctx.needsRawEntry,
|
|
10780
11056
|
hostMode: ctx.hostMode ?? "ast",
|
|
10781
11057
|
hostBranchElided: !!ctx.hostBranchElided,
|
|
10782
11058
|
hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
|
|
@@ -10786,26 +11062,6 @@ function compileLinkable(ruleMapArg, ns, opts) {
|
|
|
10786
11062
|
buildFns: buildSrcs ? [] : ctx.buildFns
|
|
10787
11063
|
};
|
|
10788
11064
|
}
|
|
10789
|
-
function hasExternalRuleRef(ruleMap) {
|
|
10790
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10791
|
-
const visit = (p) => {
|
|
10792
|
-
if (seen.has(p)) return false;
|
|
10793
|
-
seen.add(p);
|
|
10794
|
-
const def = p._def;
|
|
10795
|
-
if (def.tag === "lazy") {
|
|
10796
|
-
let resolved;
|
|
10797
|
-
try {
|
|
10798
|
-
resolved = def.thunk();
|
|
10799
|
-
} catch {
|
|
10800
|
-
resolved = void 0;
|
|
10801
|
-
}
|
|
10802
|
-
if (resolved === void 0) return p._ruleName !== void 0;
|
|
10803
|
-
return visit(resolved);
|
|
10804
|
-
}
|
|
10805
|
-
return childrenOf3(def).some(visit);
|
|
10806
|
-
};
|
|
10807
|
-
return ruleMap.some(([, rule]) => visit(rule));
|
|
10808
|
-
}
|
|
10809
11065
|
function hasSemanticReduction(roots, externalRefs) {
|
|
10810
11066
|
const seen = /* @__PURE__ */ new Set();
|
|
10811
11067
|
const visit = (parser2) => {
|
|
@@ -10851,14 +11107,16 @@ function buildInlineExpression(ctx, r, mapFnSources, buildSources, coverageRootR
|
|
|
10851
11107
|
const buildDecl = buildSources?.length ? ` const _build = [${buildSources.join(", ")}]` : "";
|
|
10852
11108
|
const emptyTlDecl = ctx.needsEmptyTl ? ` const _EMPTY_TL = Object.freeze([])` : "";
|
|
10853
11109
|
const hostReadsDecl = ctx.needsHostReads ? ` ${HOST_READS_DECL}` : "";
|
|
11110
|
+
const rawEntryDecl = ctx.needsRawEntry ? ` ${RAW_ENTRY_DECL}` : "";
|
|
10854
11111
|
const lineTrackDecl = ctx.needsLineTrack ? ` ${LINE_TRACK_DECL}` : "";
|
|
10855
11112
|
const lineSpanDecl = ctx.needsLineSpan ? ` ${LINE_SPAN_DECL}` : "";
|
|
10856
|
-
const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl || !!lineTrackDecl || !!lineSpanDecl;
|
|
11113
|
+
const needsWrapper = ctx.regexDecls.length > 0 || ctx.expectedDecls.length > 0 || ctx.namedFnDecls.length > 0 || !!mfDecl || !!buildDecl || !!emptyTlDecl || !!hostReadsDecl || !!rawEntryDecl || !!lineTrackDecl || !!lineSpanDecl;
|
|
10857
11114
|
if (!needsWrapper) return innerFn;
|
|
10858
11115
|
const namedPrelude = ctx.namedFnDecls.length > 0 ? namedFnPrelude() : [];
|
|
10859
11116
|
const hoistedDecls = [
|
|
10860
11117
|
emptyTlDecl,
|
|
10861
11118
|
hostReadsDecl,
|
|
11119
|
+
rawEntryDecl,
|
|
10862
11120
|
lineTrackDecl,
|
|
10863
11121
|
lineSpanDecl,
|
|
10864
11122
|
...ctx.regexDecls.map((d) => ` ${d}`),
|
|
@@ -10928,11 +11186,12 @@ function childrenOf4(def) {
|
|
|
10928
11186
|
return [def.main, def.skipped];
|
|
10929
11187
|
case "scanTo":
|
|
10930
11188
|
return [def.sentinel, ...def.skip];
|
|
11189
|
+
case "routed":
|
|
11190
|
+
return def.fallback ? [def.fallback] : [];
|
|
10931
11191
|
case "lazy":
|
|
10932
11192
|
case "literal":
|
|
10933
11193
|
case "regex":
|
|
10934
11194
|
case "keywords":
|
|
10935
|
-
case "routed":
|
|
10936
11195
|
case "guard":
|
|
10937
11196
|
case "recover":
|
|
10938
11197
|
case "unknown":
|
|
@@ -11014,7 +11273,7 @@ function evalRuleMapIR(ir) {
|
|
|
11014
11273
|
l._def.fnSrc = src;
|
|
11015
11274
|
return l;
|
|
11016
11275
|
};
|
|
11017
|
-
const _nd = (type, child, src, opts, staticError) => {
|
|
11276
|
+
const _nd = (type, child, src, opts, staticError, sigSrc) => {
|
|
11018
11277
|
if (staticError !== void 0 && staticError.length > 0) {
|
|
11019
11278
|
throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
|
|
11020
11279
|
}
|
|
@@ -11023,6 +11282,7 @@ function evalRuleMapIR(ir) {
|
|
|
11023
11282
|
}), opts);
|
|
11024
11283
|
n._def.buildSrc = src;
|
|
11025
11284
|
if (staticError !== void 0) n._def.buildStaticError = staticError;
|
|
11285
|
+
if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
|
|
11026
11286
|
return n;
|
|
11027
11287
|
};
|
|
11028
11288
|
const _gch = (items) => {
|
|
@@ -11335,7 +11595,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
11335
11595
|
case "peek":
|
|
11336
11596
|
return `peek(${kid(def.parser)})`;
|
|
11337
11597
|
case "routed":
|
|
11338
|
-
return "routed()"
|
|
11598
|
+
return def.fallback === void 0 ? "routed()" : `routed(${kid(def.fallback)})`;
|
|
11339
11599
|
case "trivia":
|
|
11340
11600
|
return `trivia(${kid(def.parser)})`;
|
|
11341
11601
|
case "token":
|
|
@@ -11368,6 +11628,9 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
11368
11628
|
...projectEntry === void 0 ? [] : [projectEntry],
|
|
11369
11629
|
...def.captureTrivia ? ["captureTrivia: true"] : [],
|
|
11370
11630
|
...def.trailingTrivia ? ["trailingTrivia: true"] : [],
|
|
11631
|
+
// Declared or resolved arity. Carried so a re-lowered composed artifact does
|
|
11632
|
+
// not silently re-acquire the fail-open capture cost this module resolved away.
|
|
11633
|
+
...def.buildArity === void 0 ? [] : [`buildArity: ${def.buildArity}`],
|
|
11371
11634
|
...tagEntry === void 0 ? [] : [tagEntry]
|
|
11372
11635
|
];
|
|
11373
11636
|
const opts = optEntries.length > 0 ? `, { ${optEntries.join(", ")} }` : "";
|
|
@@ -11376,8 +11639,14 @@ ${outerDecls.map((d) => " " + d).join("\n")}
|
|
|
11376
11639
|
return opts ? `node(${kid(def.parser)}, undefined${opts})` : `node(${kid(def.parser)})`;
|
|
11377
11640
|
}
|
|
11378
11641
|
if (def.buildSrc !== void 0) {
|
|
11379
|
-
const
|
|
11380
|
-
|
|
11642
|
+
const tail = [];
|
|
11643
|
+
if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0) {
|
|
11644
|
+
if (!opts) tail.push("undefined");
|
|
11645
|
+
tail.push(def.buildStaticError === void 0 ? "undefined" : JSON.stringify(def.buildStaticError));
|
|
11646
|
+
}
|
|
11647
|
+
if (def.buildSigSrc !== void 0) tail.push(JSON.stringify(def.buildSigSrc));
|
|
11648
|
+
const trailing = tail.length > 0 ? `, ${tail.join(", ")}` : "";
|
|
11649
|
+
return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${trailing})`;
|
|
11381
11650
|
}
|
|
11382
11651
|
return opts ? `node(${JSON.stringify(def.type)}, ${kid(def.parser)}, undefined${opts})` : `node(${JSON.stringify(def.type)}, ${kid(def.parser)})`;
|
|
11383
11652
|
}
|
|
@@ -11458,12 +11727,14 @@ function fusedBody(pieces) {
|
|
|
11458
11727
|
const contributingPieces = [...contributing];
|
|
11459
11728
|
const needsEmptyTl = contributingPieces.some((p) => p.needsEmptyTl);
|
|
11460
11729
|
const needsHostReads = contributingPieces.some((p) => p.needsHostReads);
|
|
11730
|
+
const needsRawEntry = contributingPieces.some((p) => p.needsRawEntry);
|
|
11461
11731
|
const lines = [
|
|
11462
11732
|
// Shared sentinel protocol (must match NAMED_FN_FAIL / NAMED_FN_END in codegen).
|
|
11463
11733
|
"const _pfFail = {}",
|
|
11464
11734
|
"let _pfEnd",
|
|
11465
11735
|
...needsEmptyTl ? ["const _EMPTY_TL = Object.freeze([])"] : [],
|
|
11466
11736
|
...needsHostReads ? [HOST_READS_DECL] : [],
|
|
11737
|
+
...needsRawEntry ? [RAW_ENTRY_DECL] : [],
|
|
11467
11738
|
// Each contributing artifact's namespaced private prelude (regexes, _pf, …).
|
|
11468
11739
|
...new Set(contributingPieces.flatMap((p) => p.prelude)),
|
|
11469
11740
|
// The winning `_r_<Name>` function for each rule (one per name → no redeclare).
|
|
@@ -11579,17 +11850,6 @@ var COMPOSED_COVERAGE_RULES = /* @__PURE__ */ Symbol.for("parseman.composedCover
|
|
|
11579
11850
|
function isIRPiece(p) {
|
|
11580
11851
|
return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
|
|
11581
11852
|
}
|
|
11582
|
-
function once(fn) {
|
|
11583
|
-
let done = false;
|
|
11584
|
-
let value;
|
|
11585
|
-
return () => {
|
|
11586
|
-
if (!done) {
|
|
11587
|
-
value = fn();
|
|
11588
|
-
done = true;
|
|
11589
|
-
}
|
|
11590
|
-
return value;
|
|
11591
|
-
};
|
|
11592
|
-
}
|
|
11593
11853
|
function carriedRuleMapsDetailed(carried) {
|
|
11594
11854
|
const maps = [];
|
|
11595
11855
|
const opaque = [];
|
|
@@ -11706,12 +11966,6 @@ function compose(items, opts) {
|
|
|
11706
11966
|
const used = /* @__PURE__ */ new Set();
|
|
11707
11967
|
const trivia2 = composingTriviaOf(items);
|
|
11708
11968
|
const carried = items.flatMap((item) => itemCarried(item, used, trivia2, opts?.hostMode));
|
|
11709
|
-
const detailed = once(() => carriedRuleMapsDetailed(carried));
|
|
11710
|
-
runFusedGatingDiagnostic(
|
|
11711
|
-
() => detailed().maps,
|
|
11712
|
-
void 0,
|
|
11713
|
-
() => detailed().opaque
|
|
11714
|
-
);
|
|
11715
11969
|
const pieces = carried.map((p) => materializePiece(p, trivia2, false, opts?.hostMode));
|
|
11716
11970
|
const map = fuseRules(pieces);
|
|
11717
11971
|
Object.defineProperty(map, COMPOSED_PIECES, { value: carried, enumerable: false });
|
|
@@ -11738,9 +11992,175 @@ function analyzeGrammarGating(grammar, opts) {
|
|
|
11738
11992
|
kind: "opaque-artifact",
|
|
11739
11993
|
reason: `precompiled artifact "${o.ns}" carries compiled rule functions, not re-lowerable IR \u2014 its choices cannot be examined. Recompile the contributing grammar so it carries IR (the macro emits IR by default) to bring it back into analysis.`
|
|
11740
11994
|
}));
|
|
11995
|
+
for (const o of opaque) {
|
|
11996
|
+
recordDegradation({
|
|
11997
|
+
code: "opaque-artifact",
|
|
11998
|
+
// `info`, not `warn`: the artifact is usually someone else's package, so the author
|
|
11999
|
+
// of THIS grammar has nothing to act on — but the blind spot still has to be counted.
|
|
12000
|
+
severity: "info",
|
|
12001
|
+
where: o.ruleNames.length > 0 ? o.ruleNames.join(", ") : `<artifact ${o.ns}>`,
|
|
12002
|
+
subject: `precompiled artifact "${o.ns}"`,
|
|
12003
|
+
fellBackTo: `it carries compiled rule functions rather than re-lowerable IR, so its ${o.ruleNames.length > 0 ? `${o.ruleNames.length} rule(s)` : "rules"} were NOT analysed and a clean gating report must not be read as a pass`,
|
|
12004
|
+
otherwise: "its choices would be walked like any other rule. Recompile the contributing grammar so it carries IR (the macro emits IR by default)"
|
|
12005
|
+
});
|
|
12006
|
+
}
|
|
11741
12007
|
return fromOpaque.length === 0 ? report : { ...report, unanalysable: [...report.unanalysable, ...fromOpaque] };
|
|
11742
12008
|
}
|
|
11743
12009
|
|
|
12010
|
+
// src/analysis/diagnose.ts
|
|
12011
|
+
var isCombinator = (g) => typeof g === "object" && g !== null && "_def" in g;
|
|
12012
|
+
var isRuleEntries = (g) => Array.isArray(g);
|
|
12013
|
+
function diagnoseGrammar(grammar, opts) {
|
|
12014
|
+
const depth = degradationCaptureDepth();
|
|
12015
|
+
beginDegradationCapture();
|
|
12016
|
+
let report;
|
|
12017
|
+
let degradations;
|
|
12018
|
+
try {
|
|
12019
|
+
report = runAnalysis(grammar, opts);
|
|
12020
|
+
} catch (e) {
|
|
12021
|
+
const reason = e instanceof Error ? `${e.name}: ${e.message}` : String(e);
|
|
12022
|
+
report = emptyReport(`gating analysis threw \u2014 ${reason}`);
|
|
12023
|
+
} finally {
|
|
12024
|
+
degradations = unwindDegradationCapture(depth);
|
|
12025
|
+
}
|
|
12026
|
+
return assemble(report, degradations);
|
|
12027
|
+
}
|
|
12028
|
+
function formatGrammarDiagnosis(d) {
|
|
12029
|
+
const s = d.summary;
|
|
12030
|
+
const lines = [];
|
|
12031
|
+
lines.push(
|
|
12032
|
+
d.ok ? `parseman: grammar OK \u2014 ${s.gated}/${s.totalChoices} choice(s) gate on first char${s.recoverable > 0 ? `, ${s.recoverable} recoverable` : ""}${s.accepted > 0 ? `, ${s.accepted} accepted` : ""}${s.deferred > 0 ? `, ${s.deferred} deferred to the fusing artifact` : ""}.` : `parseman: grammar NOT OK \u2014 ${blockingOf(d).length} blocking finding(s) over ${s.totalChoices} examined choice(s).`
|
|
12033
|
+
);
|
|
12034
|
+
if (s.unanalysable > 0) {
|
|
12035
|
+
lines.push(
|
|
12036
|
+
` ${s.unanalysable} rule(s) UNANALYSABLE \u2014 THIS REPORT IS PARTIAL. An empty finding list below does NOT mean the grammar is clean.`
|
|
12037
|
+
);
|
|
12038
|
+
}
|
|
12039
|
+
for (const f of d.findings) {
|
|
12040
|
+
lines.push(`${f.severity === "blocking" ? "\u2717" : "\xB7"} [${f.code}] ${f.id}: ${f.message}`);
|
|
12041
|
+
for (const detail of f.details) lines.push(` ${detail.replace(/\n/g, "\n ")}`);
|
|
12042
|
+
if (f.acceptKey !== void 0) {
|
|
12043
|
+
lines.push(` intentional? add to the gating snapshot: { accept: ['${f.acceptKey}'] }`);
|
|
12044
|
+
}
|
|
12045
|
+
}
|
|
12046
|
+
if (!d.ok && d.acceptSnapshot.length > 0) {
|
|
12047
|
+
lines.push(` accept-all snapshot: { accept: [${d.acceptSnapshot.map((i) => `'${i}'`).join(", ")}] }`);
|
|
12048
|
+
}
|
|
12049
|
+
return lines;
|
|
12050
|
+
}
|
|
12051
|
+
function runAnalysis(grammar, opts) {
|
|
12052
|
+
if (isCombinator(grammar)) return analyzeGating(grammar, opts);
|
|
12053
|
+
if (isRuleEntries(grammar)) return analyzeGatingRules(grammar, opts);
|
|
12054
|
+
return analyzeGrammarGating(grammar, opts);
|
|
12055
|
+
}
|
|
12056
|
+
function emptyReport(reason) {
|
|
12057
|
+
return {
|
|
12058
|
+
totalChoices: 0,
|
|
12059
|
+
gated: 0,
|
|
12060
|
+
recoverable: 0,
|
|
12061
|
+
unanalysable: [{ rule: "<whole grammar>", kind: "not-a-combinator", reason }],
|
|
12062
|
+
ungated: [],
|
|
12063
|
+
accepted: [],
|
|
12064
|
+
deferred: [],
|
|
12065
|
+
acceptedUnused: [],
|
|
12066
|
+
choices: [],
|
|
12067
|
+
antiPatterns: []
|
|
12068
|
+
};
|
|
12069
|
+
}
|
|
12070
|
+
var blockingOf = (d) => d.findings.filter((f) => f.severity === "blocking");
|
|
12071
|
+
var SEVERITY_RANK = { blocking: 0, advisory: 1 };
|
|
12072
|
+
var CODE_RANK = {
|
|
12073
|
+
unanalysable: 0,
|
|
12074
|
+
"ungated-choice": 1,
|
|
12075
|
+
"anti-pattern": 2,
|
|
12076
|
+
degraded: 3,
|
|
12077
|
+
"stale-accept": 4
|
|
12078
|
+
};
|
|
12079
|
+
function assemble(report, degradations) {
|
|
12080
|
+
const findings = [];
|
|
12081
|
+
for (const u of report.unanalysable) {
|
|
12082
|
+
findings.push({
|
|
12083
|
+
id: u.rule,
|
|
12084
|
+
code: "unanalysable",
|
|
12085
|
+
severity: "blocking",
|
|
12086
|
+
rule: u.rule,
|
|
12087
|
+
message: `could not be examined [${u.kind}] \u2014 no verdict about it is available`,
|
|
12088
|
+
details: [u.reason]
|
|
12089
|
+
});
|
|
12090
|
+
}
|
|
12091
|
+
for (const c of report.ungated) {
|
|
12092
|
+
findings.push({
|
|
12093
|
+
id: c.id,
|
|
12094
|
+
code: "ungated-choice",
|
|
12095
|
+
severity: "blocking",
|
|
12096
|
+
rule: c.rule,
|
|
12097
|
+
message: `choice is UNGATED [${c.strategy}] \u2014 no first-char dispatch; every position speculatively enters doomed arms`,
|
|
12098
|
+
details: [
|
|
12099
|
+
...c.anyArms.map((a) => `arm[${a.index}] first-set ANY (${a.cause}): ${a.detail}
|
|
12100
|
+
fix: ${a.suggestion}`),
|
|
12101
|
+
...c.overlaps.map((o) => `arm[${o.a}] \u2229 arm[${o.b}] overlap on ${firstSetToString(o.on)}
|
|
12102
|
+
fix: ${o.suggestion}`)
|
|
12103
|
+
],
|
|
12104
|
+
acceptKey: c.id
|
|
12105
|
+
});
|
|
12106
|
+
}
|
|
12107
|
+
for (const ap of report.antiPatterns) {
|
|
12108
|
+
findings.push({
|
|
12109
|
+
id: `${ap.rule}#arm${ap.armIndex}`,
|
|
12110
|
+
code: "anti-pattern",
|
|
12111
|
+
severity: "blocking",
|
|
12112
|
+
rule: ap.rule,
|
|
12113
|
+
message: `[${ap.kind}] ${ap.message}`,
|
|
12114
|
+
details: []
|
|
12115
|
+
});
|
|
12116
|
+
}
|
|
12117
|
+
for (const d of degradations) {
|
|
12118
|
+
findings.push({
|
|
12119
|
+
// `where` + `code` is the degradation channel's own identity; reuse it so the two
|
|
12120
|
+
// surfaces name the same thing the same way.
|
|
12121
|
+
id: `${d.code}@${d.where}`,
|
|
12122
|
+
code: "degraded",
|
|
12123
|
+
// Mirrors `DegradationSeverity`: 'warn' is a real cost the author can remove,
|
|
12124
|
+
// 'info' is a fact they cannot act on (someone else's package).
|
|
12125
|
+
severity: d.severity === "warn" ? "blocking" : "advisory",
|
|
12126
|
+
rule: d.where,
|
|
12127
|
+
message: formatDegradation(d),
|
|
12128
|
+
details: []
|
|
12129
|
+
});
|
|
12130
|
+
}
|
|
12131
|
+
for (const id of report.acceptedUnused) {
|
|
12132
|
+
findings.push({
|
|
12133
|
+
id,
|
|
12134
|
+
code: "stale-accept",
|
|
12135
|
+
severity: "advisory",
|
|
12136
|
+
rule: id,
|
|
12137
|
+
message: "accept entry matched no ungated choice \u2014 the grammar was fixed; prune this line",
|
|
12138
|
+
details: []
|
|
12139
|
+
});
|
|
12140
|
+
}
|
|
12141
|
+
findings.sort((a, b) => SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity] || CODE_RANK[a.code] - CODE_RANK[b.code] || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
12142
|
+
return {
|
|
12143
|
+
schema: "parseman.diagnosis/1",
|
|
12144
|
+
ok: !findings.some((f) => f.severity === "blocking"),
|
|
12145
|
+
summary: {
|
|
12146
|
+
totalChoices: report.totalChoices,
|
|
12147
|
+
gated: report.gated,
|
|
12148
|
+
recoverable: report.recoverable,
|
|
12149
|
+
ungated: report.ungated.length,
|
|
12150
|
+
accepted: report.accepted.length,
|
|
12151
|
+
deferred: report.deferred.length,
|
|
12152
|
+
antiPatterns: report.antiPatterns.length,
|
|
12153
|
+
unanalysable: report.unanalysable.length,
|
|
12154
|
+
degraded: degradations.length,
|
|
12155
|
+
staleAccepts: report.acceptedUnused.length
|
|
12156
|
+
},
|
|
12157
|
+
findings,
|
|
12158
|
+
acceptSnapshot: report.ungated.map((c) => c.id).sort(),
|
|
12159
|
+
gating: report,
|
|
12160
|
+
degradations
|
|
12161
|
+
};
|
|
12162
|
+
}
|
|
12163
|
+
|
|
11744
12164
|
// src/combinators/gate.ts
|
|
11745
12165
|
function gate(predicate) {
|
|
11746
12166
|
const meta = {
|
|
@@ -11760,9 +12180,6 @@ function gate(predicate) {
|
|
|
11760
12180
|
};
|
|
11761
12181
|
}
|
|
11762
12182
|
|
|
11763
|
-
// src/combinators/guard.ts
|
|
11764
|
-
var guard = gate;
|
|
11765
|
-
|
|
11766
12183
|
// src/combinators/completions.ts
|
|
11767
12184
|
function completionsAt(target, input, offset, options = {}) {
|
|
11768
12185
|
const probe = { offset, best: null };
|
|
@@ -11989,9 +12406,9 @@ function parseMiddle(input, reStart, reEnd, cStart, ruleFn, separator, build, to
|
|
|
11989
12406
|
const ctx = mkCtx(null, build, tolerant);
|
|
11990
12407
|
const out = [];
|
|
11991
12408
|
let pos = reStart;
|
|
11992
|
-
let
|
|
12409
|
+
let guard = 0;
|
|
11993
12410
|
while (pos < reEnd) {
|
|
11994
|
-
if (++
|
|
12411
|
+
if (++guard > reEnd - reStart + 2) return null;
|
|
11995
12412
|
if (separator && out.length > 0 && out[out.length - 1]._tag === "node") {
|
|
11996
12413
|
if (pos + separator.length > reEnd || !input.startsWith(separator, pos)) return null;
|
|
11997
12414
|
out.push({ _tag: "leaf", value: separator, span: { start: pos - cStart, end: pos + separator.length - cStart } });
|
|
@@ -12284,6 +12701,35 @@ function parseDoc(registry, rootRule, input, opts = {}) {
|
|
|
12284
12701
|
}
|
|
12285
12702
|
|
|
12286
12703
|
// src/functional/run.ts
|
|
12704
|
+
var SELECT_EXAMPLE = "run(entry, input, { rootTrivia: { select: ['blockComment', 'lineComment'] } })";
|
|
12705
|
+
var REMOVED_RUN_RESULT_FIELDS = [
|
|
12706
|
+
[
|
|
12707
|
+
"triviaMap",
|
|
12708
|
+
`It was a dense root-trivia index built on every parse; root trivia is now an OPT-IN sparse capture, because most grammars paid for an index they never read. Migration: name the trivia labels your grammar defines \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia\`, whose \`.index\` carries the labels and gap lookups \`triviaMap\` exposed.`
|
|
12709
|
+
],
|
|
12710
|
+
[
|
|
12711
|
+
"triviaLog",
|
|
12712
|
+
`It was the flat \`start, end[, kindIndex]\` log every other trivia view was derived from, and it is no longer allocated at all \u2014 not empty, absent. Migration: request the labels you need \u2014 ${SELECT_EXAMPLE} \u2014 and read \`RunResult.rootTrivia.rows\`. Do NOT reuse a stride-2/3 reader: rows are a different width and a different unit (one row per SELECTED marker, not one per trivia chunk), so an old loop reads confidently wrong offsets rather than failing.`
|
|
12713
|
+
],
|
|
12714
|
+
[
|
|
12715
|
+
"triviaKindLabels",
|
|
12716
|
+
`It was already optional, so nothing ever flagged its disappearance \u2014 and \`triviaKindMask(undefined, \u2026)\` means "capture everything", so reading it now silently WIDENS capture instead of erroring. Migration: request labels \u2014 ${SELECT_EXAMPLE} \u2014 then the set you asked for is \`RunResult.rootTrivia.select\` and the resolved table is \`RunResult.rootTrivia.index.labels\`.`
|
|
12717
|
+
]
|
|
12718
|
+
];
|
|
12719
|
+
function guardRemovedFields(result) {
|
|
12720
|
+
for (const [name, detail] of REMOVED_RUN_RESULT_FIELDS) {
|
|
12721
|
+
Object.defineProperty(result, name, {
|
|
12722
|
+
configurable: true,
|
|
12723
|
+
enumerable: false,
|
|
12724
|
+
get() {
|
|
12725
|
+
throw new TypeError(
|
|
12726
|
+
`RunResult.${name} was REMOVED in parseman 0.44.0 and has no default replacement. ${detail}`
|
|
12727
|
+
);
|
|
12728
|
+
}
|
|
12729
|
+
});
|
|
12730
|
+
}
|
|
12731
|
+
return result;
|
|
12732
|
+
}
|
|
12287
12733
|
var invoke = (r, input, pos, ctx) => typeof r === "function" ? r(input, pos, ctx) : r.parse(input, pos, ctx);
|
|
12288
12734
|
function triviaKindLabelsFromRunnable(r) {
|
|
12289
12735
|
if (!r) return void 0;
|
|
@@ -12386,37 +12832,11 @@ function runOnce(entry, input, options, phase, profileState) {
|
|
|
12386
12832
|
unconsumedFrom
|
|
12387
12833
|
};
|
|
12388
12834
|
}
|
|
12389
|
-
function clonePassState(state) {
|
|
12390
|
-
if (state === null || typeof state !== "object") return state;
|
|
12391
|
-
return Array.isArray(state) ? [...state] : { ...state };
|
|
12392
|
-
}
|
|
12393
|
-
function profilePass(entry, input, options, phase) {
|
|
12394
|
-
const state = { phase, nodes: 0, childSlots: 0, rawSlots: 0, triviaSlots: 0, fieldSlots: 0, hostCalls: 0 };
|
|
12395
|
-
const passOptions = options.state === void 0 ? options : { ...options, state: clonePassState(options.state) };
|
|
12396
|
-
const start = performance.now();
|
|
12397
|
-
const result = runOnce(entry, input, passOptions, phase, state);
|
|
12398
|
-
const { phase: _phase, ...counts } = state;
|
|
12399
|
-
return { result, profile: { ms: performance.now() - start, ...counts } };
|
|
12400
|
-
}
|
|
12401
12835
|
function run(entry, input, options = {}) {
|
|
12402
|
-
if (!options.profile) return runOnce(entry, input, options);
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
const recognizer = profilePass(entry, input, options, "recognizer");
|
|
12407
|
-
const capture = profilePass(entry, input, options, "capture");
|
|
12408
|
-
const host = profilePass(entry, input, options, "host");
|
|
12409
|
-
if (recognizer.result.ok !== host.result.ok || capture.result.ok !== host.result.ok || recognizer.result.unconsumedFrom !== host.result.unconsumedFrom || capture.result.unconsumedFrom !== host.result.unconsumedFrom) {
|
|
12410
|
-
throw new Error("run({ profile: true }) changed recognition; the grammar is not profile-safe");
|
|
12411
|
-
}
|
|
12412
|
-
return {
|
|
12413
|
-
...host.result,
|
|
12414
|
-
profile: {
|
|
12415
|
-
recognizer: recognizer.profile,
|
|
12416
|
-
structuralCapture: capture.profile,
|
|
12417
|
-
hostConstruction: host.profile
|
|
12418
|
-
}
|
|
12419
|
-
};
|
|
12836
|
+
if (!options.profile) return guardRemovedFields(runOnce(entry, input, options));
|
|
12837
|
+
throw new TypeError(
|
|
12838
|
+
"run({ profile: true }) is unavailable: profiling counters are no longer compiled into parser artifacts, and the interpreter does not implement them yet. Profiling is moving to interpreted mode."
|
|
12839
|
+
);
|
|
12420
12840
|
}
|
|
12421
12841
|
|
|
12422
12842
|
// src/coverage.ts
|
|
@@ -12433,7 +12853,7 @@ function dispatchMatcher(entry) {
|
|
|
12433
12853
|
var GRAMMAR_COVERAGE_DEFINITIONS = /* @__PURE__ */ Symbol.for("parseman.grammarCoverageDefinitions");
|
|
12434
12854
|
function compiledGrammarCoverageDefinitions(grammar) {
|
|
12435
12855
|
const definitions = grammar[GRAMMAR_COVERAGE_DEFINITIONS];
|
|
12436
|
-
if (!Array.isArray(definitions) || !definitions.every((definition) => typeof definition === "object" && definition !== null && typeof definition.id === "string" && (definition.kind === "rule" || definition.kind === "choice-arm" || definition.kind === "dispatch-arm" || definition.kind === "label"))) {
|
|
12856
|
+
if (!Array.isArray(definitions) || definitions.length === 0 || !definitions.every((definition) => typeof definition === "object" && definition !== null && typeof definition.id === "string" && (definition.kind === "rule" || definition.kind === "choice-arm" || definition.kind === "dispatch-arm" || definition.kind === "label"))) {
|
|
12437
12857
|
throw new TypeError("grammar has no coverage definitions; enable grammarCoverage for this macro build");
|
|
12438
12858
|
}
|
|
12439
12859
|
return definitions;
|
|
@@ -12487,7 +12907,13 @@ function createGrammarCoverageCollector(definitions) {
|
|
|
12487
12907
|
snapshot() {
|
|
12488
12908
|
const hitList = [...hits].sort();
|
|
12489
12909
|
const unhit = ordered.map((definition) => definition.id).filter((id) => !hits.has(id));
|
|
12490
|
-
return {
|
|
12910
|
+
return {
|
|
12911
|
+
definitions: ordered,
|
|
12912
|
+
hits: hitList,
|
|
12913
|
+
unhit,
|
|
12914
|
+
ratio: hitList.length / ordered.length,
|
|
12915
|
+
measurable: ordered.length > 0
|
|
12916
|
+
};
|
|
12491
12917
|
},
|
|
12492
12918
|
reset() {
|
|
12493
12919
|
hits.clear();
|
|
@@ -12807,13 +13233,13 @@ function buildTriviaIndex(root, input = "", opts) {
|
|
|
12807
13233
|
}
|
|
12808
13234
|
|
|
12809
13235
|
// src/cst/walk.ts
|
|
12810
|
-
function
|
|
13236
|
+
function isCombinator2(value) {
|
|
12811
13237
|
return !!value && typeof value === "object" && "_def" in value && "_meta" in value && typeof value.parse === "function";
|
|
12812
13238
|
}
|
|
12813
13239
|
function reflectionFor(grammar) {
|
|
12814
13240
|
const stamped = grammarReflectionOf(grammar);
|
|
12815
13241
|
if (stamped) return stamped;
|
|
12816
|
-
const entries = Object.entries(grammar).filter((entry) =>
|
|
13242
|
+
const entries = Object.entries(grammar).filter((entry) => isCombinator2(entry[1]));
|
|
12817
13243
|
return collectGrammarReflection(entries);
|
|
12818
13244
|
}
|
|
12819
13245
|
function createVisitor(grammar, spec) {
|
|
@@ -12851,196 +13277,6 @@ function createVisitor(grammar, spec) {
|
|
|
12851
13277
|
};
|
|
12852
13278
|
}
|
|
12853
13279
|
|
|
12854
|
-
// src/cst/offset-model.ts
|
|
12855
|
-
var { isFinite } = Number;
|
|
12856
|
-
function floorIndex(arr, len, x) {
|
|
12857
|
-
let lo = 0;
|
|
12858
|
-
let hi = len - 1;
|
|
12859
|
-
let ans = -1;
|
|
12860
|
-
while (lo <= hi) {
|
|
12861
|
-
const mid = lo + hi >>> 1;
|
|
12862
|
-
if (arr[mid] <= x) {
|
|
12863
|
-
ans = mid;
|
|
12864
|
-
lo = mid + 1;
|
|
12865
|
-
} else {
|
|
12866
|
-
hi = mid - 1;
|
|
12867
|
-
}
|
|
12868
|
-
}
|
|
12869
|
-
return ans;
|
|
12870
|
-
}
|
|
12871
|
-
var OffsetIndex = class {
|
|
12872
|
-
/** Slot starts, sorted ascending. Parallel to `_ends`. */
|
|
12873
|
-
_starts;
|
|
12874
|
-
_ends;
|
|
12875
|
-
count;
|
|
12876
|
-
docStart;
|
|
12877
|
-
docEnd;
|
|
12878
|
-
constructor(slots, docStart = 0, docEnd) {
|
|
12879
|
-
const sorted = [...slots].sort((a, b) => a.start - b.start);
|
|
12880
|
-
const starts = [];
|
|
12881
|
-
const ends = [];
|
|
12882
|
-
let prevEnd = docStart;
|
|
12883
|
-
for (const s of sorted) {
|
|
12884
|
-
if (!isFinite(s.start) || !isFinite(s.end) || s.end < s.start) {
|
|
12885
|
-
throw new RangeError(`OffsetIndex: invalid slot [${s.start}, ${s.end}]`);
|
|
12886
|
-
}
|
|
12887
|
-
if (s.start < prevEnd) {
|
|
12888
|
-
throw new RangeError(`OffsetIndex: overlapping/out-of-order slot [${s.start}, ${s.end}] after end ${prevEnd}`);
|
|
12889
|
-
}
|
|
12890
|
-
starts.push(s.start);
|
|
12891
|
-
ends.push(s.end);
|
|
12892
|
-
prevEnd = s.end;
|
|
12893
|
-
}
|
|
12894
|
-
this._starts = starts;
|
|
12895
|
-
this._ends = ends;
|
|
12896
|
-
this.count = starts.length;
|
|
12897
|
-
this.docStart = docStart;
|
|
12898
|
-
this.docEnd = docEnd ?? (this.count ? Math.max(prevEnd, ends[ends.length - 1]) : docStart);
|
|
12899
|
-
}
|
|
12900
|
-
/** The slot at index `i` (0-based, source order), or undefined. */
|
|
12901
|
-
slot(i) {
|
|
12902
|
-
if (i < 0 || i >= this.count) return void 0;
|
|
12903
|
-
return { start: this._starts[i], end: this._ends[i] };
|
|
12904
|
-
}
|
|
12905
|
-
/**
|
|
12906
|
-
* Index of the gap that CONTAINS `offset`, in `[0, count]`. Gap `i` spans
|
|
12907
|
-
* `[endOf(i-1), startOf(i))` where `endOf(-1)=docStart` and `startOf(count)=docEnd`.
|
|
12908
|
-
* An offset that lands inside a slot returns that slot's TRAILING gap index
|
|
12909
|
-
* (i.e. the gap after it) — callers querying at slot boundaries get the
|
|
12910
|
-
* intuitive answer via `gapBefore`/`gapAfter`.
|
|
12911
|
-
*/
|
|
12912
|
-
gapIndexAt(offset) {
|
|
12913
|
-
const i = floorIndex(this._starts, this.count, offset);
|
|
12914
|
-
if (i < 0) return 0;
|
|
12915
|
-
if (offset < this._ends[i]) return i + 1;
|
|
12916
|
-
return i + 1;
|
|
12917
|
-
}
|
|
12918
|
-
/** The gap at index `i` in `[0, count]`. */
|
|
12919
|
-
gap(i) {
|
|
12920
|
-
if (i < 0 || i > this.count) return void 0;
|
|
12921
|
-
const start = i === 0 ? this.docStart : this._ends[i - 1];
|
|
12922
|
-
const end = i === this.count ? this.docEnd : this._starts[i];
|
|
12923
|
-
return { start, end };
|
|
12924
|
-
}
|
|
12925
|
-
/**
|
|
12926
|
-
* The trivia gap immediately BEFORE `offset` (`[prevSlotEnd, offset)`), where
|
|
12927
|
-
* `prevSlotEnd` is the end of the last slot ending at or before `offset` (or
|
|
12928
|
-
* `docStart`). For a real slot start this is the gap preceding that slot; for an
|
|
12929
|
-
* adjacent slot the gap is empty and agrees with `gapAfter` on the same seam.
|
|
12930
|
-
*/
|
|
12931
|
-
gapBefore(offset) {
|
|
12932
|
-
const e = floorIndex(this._ends, this.count, offset);
|
|
12933
|
-
const start = e >= 0 ? this._ends[e] : this.docStart;
|
|
12934
|
-
return { start, end: offset };
|
|
12935
|
-
}
|
|
12936
|
-
/**
|
|
12937
|
-
* The trivia gap immediately AFTER `offset` (`[offset, nextSlotStart)`), where
|
|
12938
|
-
* `nextSlotStart` is the least slot start at or after `offset` (or `docEnd`).
|
|
12939
|
-
*/
|
|
12940
|
-
gapAfter(offset) {
|
|
12941
|
-
return { start: offset, end: this._ceilStart(offset) };
|
|
12942
|
-
}
|
|
12943
|
-
/** Least slot start `>= offset`, else `docEnd`. */
|
|
12944
|
-
_ceilStart(offset) {
|
|
12945
|
-
let lo = 0;
|
|
12946
|
-
let hi = this.count - 1;
|
|
12947
|
-
let ans = this.docEnd;
|
|
12948
|
-
while (lo <= hi) {
|
|
12949
|
-
const mid = lo + hi >>> 1;
|
|
12950
|
-
if (this._starts[mid] >= offset) {
|
|
12951
|
-
ans = this._starts[mid];
|
|
12952
|
-
hi = mid - 1;
|
|
12953
|
-
} else {
|
|
12954
|
-
lo = mid + 1;
|
|
12955
|
-
}
|
|
12956
|
-
}
|
|
12957
|
-
return ans;
|
|
12958
|
-
}
|
|
12959
|
-
/** Is this gap empty (adjacent slots, no trivia)? */
|
|
12960
|
-
isEmpty(gap) {
|
|
12961
|
-
return gap.end <= gap.start;
|
|
12962
|
-
}
|
|
12963
|
-
};
|
|
12964
|
-
var NL = 10;
|
|
12965
|
-
var CR = 13;
|
|
12966
|
-
var SP = 32;
|
|
12967
|
-
var TAB = 9;
|
|
12968
|
-
function gapText(source, gap) {
|
|
12969
|
-
return gap.end > gap.start ? source.slice(gap.start, gap.end) : "";
|
|
12970
|
-
}
|
|
12971
|
-
function lineBreaksIn(source, gap) {
|
|
12972
|
-
let n = 0;
|
|
12973
|
-
for (let i = gap.start; i < gap.end; i++) {
|
|
12974
|
-
const c = source.charCodeAt(i);
|
|
12975
|
-
if (c === NL) n++;
|
|
12976
|
-
else if (c === CR && source.charCodeAt(i + 1) !== NL) n++;
|
|
12977
|
-
}
|
|
12978
|
-
return n;
|
|
12979
|
-
}
|
|
12980
|
-
function blankLinesIn(source, gap) {
|
|
12981
|
-
return Math.max(0, lineBreaksIn(source, gap) - 1);
|
|
12982
|
-
}
|
|
12983
|
-
function lineStartWithin(source, gap) {
|
|
12984
|
-
for (let i = gap.end - 1; i >= gap.start; i--) {
|
|
12985
|
-
const c = source.charCodeAt(i);
|
|
12986
|
-
if (c === NL || c === CR) return i + 1;
|
|
12987
|
-
}
|
|
12988
|
-
return gap.start;
|
|
12989
|
-
}
|
|
12990
|
-
function indentWidth(source, gap) {
|
|
12991
|
-
const ls = lineStartWithin(source, gap);
|
|
12992
|
-
if (ls === gap.start) return 0;
|
|
12993
|
-
return gap.end - ls;
|
|
12994
|
-
}
|
|
12995
|
-
function indentMixed(source, gap) {
|
|
12996
|
-
const ls = lineStartWithin(source, gap);
|
|
12997
|
-
let sawSpace = false;
|
|
12998
|
-
let sawTab = false;
|
|
12999
|
-
for (let i = ls; i < gap.end; i++) {
|
|
13000
|
-
const c = source.charCodeAt(i);
|
|
13001
|
-
if (c === SP) sawSpace = true;
|
|
13002
|
-
else if (c === TAB) sawTab = true;
|
|
13003
|
-
}
|
|
13004
|
-
return sawSpace && sawTab;
|
|
13005
|
-
}
|
|
13006
|
-
function commentsIn(source, gap, comment) {
|
|
13007
|
-
const re = new RegExp(comment.source, comment.flags.replace(/[gy]/g, "") + "g");
|
|
13008
|
-
re.lastIndex = gap.start;
|
|
13009
|
-
const out = [];
|
|
13010
|
-
let m;
|
|
13011
|
-
while ((m = re.exec(source)) && m.index < gap.end) {
|
|
13012
|
-
if (m[0].length === 0) {
|
|
13013
|
-
re.lastIndex++;
|
|
13014
|
-
continue;
|
|
13015
|
-
}
|
|
13016
|
-
if (m.index + m[0].length > gap.end) break;
|
|
13017
|
-
out.push({ start: m.index, end: m.index + m[0].length });
|
|
13018
|
-
}
|
|
13019
|
-
return out;
|
|
13020
|
-
}
|
|
13021
|
-
function gapIsSignificant(source, gap, comment) {
|
|
13022
|
-
if (gap.end <= gap.start) return false;
|
|
13023
|
-
if (lineBreaksIn(source, gap) > 0) return true;
|
|
13024
|
-
if (comment && commentsIn(source, gap, comment).length > 0) return true;
|
|
13025
|
-
return false;
|
|
13026
|
-
}
|
|
13027
|
-
function collectLeafSlots(root) {
|
|
13028
|
-
const slots = [];
|
|
13029
|
-
const visit = (n) => {
|
|
13030
|
-
const kids = n.children;
|
|
13031
|
-
if (kids && kids.length) {
|
|
13032
|
-
for (const c of kids) visit(c);
|
|
13033
|
-
} else if (n.span) {
|
|
13034
|
-
slots.push({ start: n.span.start, end: n.span.end });
|
|
13035
|
-
}
|
|
13036
|
-
};
|
|
13037
|
-
if (root) visit(root);
|
|
13038
|
-
return slots;
|
|
13039
|
-
}
|
|
13040
|
-
function buildOffsetIndex(root, input = "") {
|
|
13041
|
-
return new OffsetIndex(collectLeafSlots(root), 0, input.length);
|
|
13042
|
-
}
|
|
13043
|
-
|
|
13044
13280
|
// src/index.ts
|
|
13045
13281
|
registerRegexAnalyzer(firstSetFromRegex);
|
|
13046
13282
|
//# sourceMappingURL=index.cjs.map
|