parseman 0.41.0 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combinators/expect.d.ts.map +1 -1
- package/dist/combinators/grammar.d.ts.map +1 -1
- package/dist/combinators/literal.d.ts.map +1 -1
- package/dist/combinators/node.d.ts.map +1 -1
- package/dist/combinators/parser.d.ts +6 -0
- package/dist/combinators/parser.d.ts.map +1 -1
- package/dist/combinators/regex.d.ts.map +1 -1
- package/dist/combinators/scanTo.d.ts.map +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/codegen.d.ts +5 -0
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/inline-build.d.ts +1 -1
- package/dist/compiler/inline-build.d.ts.map +1 -1
- package/dist/compiler/line-index.d.ts +1 -15
- package/dist/compiler/line-index.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts +1 -0
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.cjs +483 -181
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +483 -181
- package/dist/index.js.map +4 -4
- package/dist/language-service/index.cjs +48 -2
- package/dist/language-service/index.cjs.map +3 -3
- package/dist/language-service/index.js +48 -2
- package/dist/language-service/index.js.map +3 -3
- package/dist/line-index.d.ts +41 -0
- package/dist/line-index.d.ts.map +1 -0
- package/dist/plugin/index.cjs +646 -169
- package/dist/plugin/index.cjs.map +4 -4
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +646 -169
- package/dist/plugin/index.js.map +4 -4
- package/dist/recovery/scan.d.ts.map +1 -1
- package/dist/regex/first-set.d.ts.map +1 -1
- package/dist/run/index.cjs +47 -1
- package/dist/run/index.cjs.map +3 -3
- package/dist/run/index.d.ts +3 -2
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +47 -1
- package/dist/run/index.js.map +3 -3
- package/dist/spec/index.cjs +462 -327
- package/dist/spec/index.cjs.map +4 -4
- package/dist/spec/index.js +462 -327
- package/dist/spec/index.js.map +4 -4
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/spec/index.js
CHANGED
|
@@ -357,90 +357,63 @@ function markUnusedValues(root) {
|
|
|
357
357
|
visit(resolveRoot(root), true);
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
-
// src/
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
;
|
|
364
|
-
r._ruleName = key;
|
|
365
|
-
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
366
|
-
}
|
|
367
|
-
function isDefinableRef(v) {
|
|
368
|
-
return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
|
|
369
|
-
}
|
|
370
|
-
function ruleNameOf(r) {
|
|
371
|
-
return r._ruleName;
|
|
360
|
+
// src/line-index.ts
|
|
361
|
+
function createLineIndex() {
|
|
362
|
+
return { lineStarts: [0] };
|
|
372
363
|
}
|
|
373
|
-
function
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
function rules(a, b) {
|
|
378
|
-
const factory = typeof a === "function" ? a : b;
|
|
379
|
-
const options = typeof a === "function" ? b : a;
|
|
380
|
-
const cache = {};
|
|
381
|
-
const proxy = new Proxy(cache, {
|
|
382
|
-
get(target, key) {
|
|
383
|
-
if (typeof key !== "string") return void 0;
|
|
384
|
-
const record = target;
|
|
385
|
-
if (!(key in record)) {
|
|
386
|
-
const r = ref();
|
|
387
|
-
tagRule(r, key);
|
|
388
|
-
record[key] = r;
|
|
389
|
-
}
|
|
390
|
-
return record[key];
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
const definitions = factory(proxy);
|
|
394
|
-
for (const key of Object.keys(definitions)) {
|
|
395
|
-
const placeholder = cache[key];
|
|
396
|
-
const parser2 = definitions[key];
|
|
397
|
-
if (placeholder === parser2) {
|
|
398
|
-
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
399
|
-
}
|
|
400
|
-
if (isDefinableRef(placeholder)) {
|
|
401
|
-
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
402
|
-
placeholder.define(parser2);
|
|
403
|
-
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
404
|
-
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
405
|
-
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
406
|
-
const alias = ref();
|
|
407
|
-
tagRule(alias, key);
|
|
408
|
-
alias.define(parser2);
|
|
409
|
-
alias._meta.firstSet = parser2._meta.firstSet;
|
|
410
|
-
alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
411
|
-
cache[key] = alias;
|
|
412
|
-
} else {
|
|
413
|
-
tagRule(parser2, key);
|
|
414
|
-
cache[key] = parser2;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
if (options?.trivia != null) {
|
|
418
|
-
for (const key of Object.keys(definitions)) {
|
|
419
|
-
const rule = cache[key];
|
|
420
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if (options?.scanSkip != null) {
|
|
424
|
-
for (const key of Object.keys(definitions)) {
|
|
425
|
-
const rule = cache[key];
|
|
426
|
-
if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
|
|
427
|
-
}
|
|
364
|
+
function recordLineRange(index, input, start, end) {
|
|
365
|
+
const lineStarts = index.lineStarts;
|
|
366
|
+
for (let i = start; i < end; i++) {
|
|
367
|
+
if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
|
|
428
368
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
369
|
+
}
|
|
370
|
+
function recordLineRangeFromContext(ctx, input, _startHint, end) {
|
|
371
|
+
if (!ctx.trackLines) return;
|
|
372
|
+
const from = ctx._lineScannedTo ?? 0;
|
|
373
|
+
if (end <= from) return;
|
|
374
|
+
const index = ctx._lineIndex ?? (ctx._lineStarts ? { lineStarts: ctx._lineStarts } : void 0);
|
|
375
|
+
if (!index) return;
|
|
376
|
+
recordLineRange(index, input, from, end);
|
|
377
|
+
ctx._lineScannedTo = end;
|
|
378
|
+
}
|
|
379
|
+
function normalizeLineIndex(index) {
|
|
380
|
+
const starts = index.lineStarts;
|
|
381
|
+
starts.sort((a, b) => a - b);
|
|
382
|
+
let write = 0;
|
|
383
|
+
for (let read = 0; read < starts.length; read++) {
|
|
384
|
+
const value = starts[read];
|
|
385
|
+
if (write === 0 || starts[write - 1] !== value) starts[write++] = value;
|
|
434
386
|
}
|
|
435
|
-
|
|
436
|
-
|
|
387
|
+
starts.length = write;
|
|
388
|
+
if (starts.length === 0 || starts[0] !== 0) starts.unshift(0);
|
|
389
|
+
return index;
|
|
390
|
+
}
|
|
391
|
+
function offsetToLineCol(index, offset) {
|
|
392
|
+
const { lineStarts } = index;
|
|
393
|
+
let lo = 0;
|
|
394
|
+
let hi = lineStarts.length - 1;
|
|
395
|
+
while (lo < hi) {
|
|
396
|
+
const mid = lo + hi + 1 >> 1;
|
|
397
|
+
if (lineStarts[mid] <= offset) lo = mid;
|
|
398
|
+
else hi = mid - 1;
|
|
437
399
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
return
|
|
400
|
+
return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
|
|
401
|
+
}
|
|
402
|
+
function annotateSpan(span, index) {
|
|
403
|
+
const s = offsetToLineCol(index, span.start);
|
|
404
|
+
const e = offsetToLineCol(index, span.end);
|
|
405
|
+
return {
|
|
406
|
+
...span,
|
|
407
|
+
startLine: s.line,
|
|
408
|
+
startColumn: s.col,
|
|
409
|
+
endLine: e.line,
|
|
410
|
+
endColumn: e.col
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function annotateSpanFromLineContext(span, ctx) {
|
|
414
|
+
if (!ctx.trackLines) return span;
|
|
415
|
+
const index = ctx._lineIndex ?? (ctx._lineStarts ? { lineStarts: ctx._lineStarts } : void 0);
|
|
416
|
+
return index ? annotateSpan(span, index) : span;
|
|
444
417
|
}
|
|
445
418
|
|
|
446
419
|
// src/cst/capture-buffer.ts
|
|
@@ -484,7 +457,12 @@ function endCstNodeCapture(ctx, saved) {
|
|
|
484
457
|
return materialized;
|
|
485
458
|
}
|
|
486
459
|
function pushCstLeaf(ctx, leaf2) {
|
|
487
|
-
|
|
460
|
+
if (!ctx.trackLines) {
|
|
461
|
+
pushCstChild(ctx, leaf2, leaf2);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const annotated = leaf2 && typeof leaf2 === "object" && leaf2.span ? { ...leaf2, span: annotateSpanFromLineContext(leaf2.span, ctx) } : leaf2;
|
|
465
|
+
pushCstChild(ctx, annotated, annotated);
|
|
488
466
|
}
|
|
489
467
|
function pushCstChild(ctx, built, rawEntry) {
|
|
490
468
|
const b = ctx._cstBuf;
|
|
@@ -674,7 +652,9 @@ function firstSetSentinel(fs) {
|
|
|
674
652
|
function recoverScan(input, from, ctx, sync, expected) {
|
|
675
653
|
let scanPos = from;
|
|
676
654
|
while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
|
|
677
|
-
const
|
|
655
|
+
const span = { start: from, end: scanPos };
|
|
656
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, from, scanPos);
|
|
657
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
678
658
|
ctx._errors?.push(error);
|
|
679
659
|
return { error, end: scanPos };
|
|
680
660
|
}
|
|
@@ -776,7 +756,8 @@ function expect(combinator, label2) {
|
|
|
776
756
|
parse(input, pos, ctx) {
|
|
777
757
|
const result = combinator.parse(input, pos, ctx);
|
|
778
758
|
if (result.ok) return result;
|
|
779
|
-
const
|
|
759
|
+
const span = { start: pos, end: pos };
|
|
760
|
+
const error = { _tag: "parseError", span: ctx.trackLines ? annotateSpanFromLineContext(span, ctx) : span, expected };
|
|
780
761
|
ctx._errors?.push(error);
|
|
781
762
|
if (ctx._tolerant) captureError(ctx, error);
|
|
782
763
|
return { ok: true, value: error, span: { start: pos, end: pos } };
|
|
@@ -1047,34 +1028,329 @@ function codesToFirstSet(codes) {
|
|
|
1047
1028
|
lo = hi = codes[i];
|
|
1048
1029
|
}
|
|
1049
1030
|
}
|
|
1050
|
-
ranges.push({ lo, hi });
|
|
1051
|
-
return { kind: "ranges", ranges };
|
|
1052
|
-
}
|
|
1053
|
-
function inFirstSet(code, fs) {
|
|
1054
|
-
if (fs.kind === "any") return true;
|
|
1055
|
-
if (fs.kind === "empty") return false;
|
|
1056
|
-
for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1057
|
-
return false;
|
|
1058
|
-
}
|
|
1059
|
-
function areDisjoint(sets) {
|
|
1060
|
-
if (sets.some((s) => s.kind === "any")) return false;
|
|
1061
|
-
for (let i = 0; i < sets.length; i++)
|
|
1062
|
-
for (let j2 = i + 1; j2 < sets.length; j2++)
|
|
1063
|
-
if (intersects(sets[i], sets[j2])) return false;
|
|
1064
|
-
return true;
|
|
1065
|
-
}
|
|
1066
|
-
function buildAsciiDispatch(parsers) {
|
|
1067
|
-
const table = Array(128).fill(-1);
|
|
1068
|
-
for (let i = 0; i < parsers.length; i++) {
|
|
1069
|
-
const fs = parsers[i]._meta.firstSet;
|
|
1070
|
-
if (fs.kind !== "ranges") continue;
|
|
1071
|
-
for (const { lo, hi } of fs.ranges) {
|
|
1072
|
-
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
1073
|
-
table[code] = i;
|
|
1031
|
+
ranges.push({ lo, hi });
|
|
1032
|
+
return { kind: "ranges", ranges };
|
|
1033
|
+
}
|
|
1034
|
+
function inFirstSet(code, fs) {
|
|
1035
|
+
if (fs.kind === "any") return true;
|
|
1036
|
+
if (fs.kind === "empty") return false;
|
|
1037
|
+
for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
|
|
1038
|
+
return false;
|
|
1039
|
+
}
|
|
1040
|
+
function areDisjoint(sets) {
|
|
1041
|
+
if (sets.some((s) => s.kind === "any")) return false;
|
|
1042
|
+
for (let i = 0; i < sets.length; i++)
|
|
1043
|
+
for (let j2 = i + 1; j2 < sets.length; j2++)
|
|
1044
|
+
if (intersects(sets[i], sets[j2])) return false;
|
|
1045
|
+
return true;
|
|
1046
|
+
}
|
|
1047
|
+
function buildAsciiDispatch(parsers) {
|
|
1048
|
+
const table = Array(128).fill(-1);
|
|
1049
|
+
for (let i = 0; i < parsers.length; i++) {
|
|
1050
|
+
const fs = parsers[i]._meta.firstSet;
|
|
1051
|
+
if (fs.kind !== "ranges") continue;
|
|
1052
|
+
for (const { lo, hi } of fs.ranges) {
|
|
1053
|
+
for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
|
|
1054
|
+
table[code] = i;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return table;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// src/cst/trivia-kinds.ts
|
|
1062
|
+
function unwrapTrivia(p) {
|
|
1063
|
+
let cur = p;
|
|
1064
|
+
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
1065
|
+
return cur;
|
|
1066
|
+
}
|
|
1067
|
+
function peelLabel(p) {
|
|
1068
|
+
if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
function analyzeLabeledTrivia(trivia2) {
|
|
1072
|
+
let core = unwrapTrivia(trivia2);
|
|
1073
|
+
let minRepeats = 1;
|
|
1074
|
+
if (core._def.tag === "oneOrMore") {
|
|
1075
|
+
core = core._def.parser;
|
|
1076
|
+
minRepeats = 1;
|
|
1077
|
+
} else if (core._def.tag === "many") {
|
|
1078
|
+
core = core._def.parser;
|
|
1079
|
+
minRepeats = 0;
|
|
1080
|
+
}
|
|
1081
|
+
const arms = [];
|
|
1082
|
+
if (core._def.tag === "choice") {
|
|
1083
|
+
for (let i = 0; i < core._def.parsers.length; i++) {
|
|
1084
|
+
const peeled = peelLabel(core._def.parsers[i]);
|
|
1085
|
+
if (!peeled) return null;
|
|
1086
|
+
arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
|
|
1087
|
+
}
|
|
1088
|
+
} else {
|
|
1089
|
+
const peeled = peelLabel(core);
|
|
1090
|
+
if (!peeled) return null;
|
|
1091
|
+
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
1092
|
+
}
|
|
1093
|
+
return { labels: arms.map((a) => a.label), arms, minRepeats };
|
|
1094
|
+
}
|
|
1095
|
+
function matchArmAt(input, pos, arm) {
|
|
1096
|
+
const r = arm.parse(input, pos, { trackLines: false });
|
|
1097
|
+
if (!r.ok || r.span.end <= pos) return null;
|
|
1098
|
+
return { end: r.span.end };
|
|
1099
|
+
}
|
|
1100
|
+
function scanLabeledTriviaChunks(input, cur, spec) {
|
|
1101
|
+
const chunks = [];
|
|
1102
|
+
let pos = cur;
|
|
1103
|
+
while (pos < input.length) {
|
|
1104
|
+
let matched = null;
|
|
1105
|
+
for (const arm of spec.arms) {
|
|
1106
|
+
const m = matchArmAt(input, pos, arm.parser);
|
|
1107
|
+
if (m) {
|
|
1108
|
+
matched = { end: m.end, kindIndex: arm.kindIndex };
|
|
1109
|
+
break;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
if (!matched) break;
|
|
1113
|
+
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
1114
|
+
pos = matched.end;
|
|
1115
|
+
}
|
|
1116
|
+
if (chunks.length < spec.minRepeats) {
|
|
1117
|
+
return { end: cur, chunks: [] };
|
|
1118
|
+
}
|
|
1119
|
+
return { end: pos, chunks };
|
|
1120
|
+
}
|
|
1121
|
+
function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
|
|
1122
|
+
const chunks = [];
|
|
1123
|
+
let pos = cur;
|
|
1124
|
+
while (pos < input.length) {
|
|
1125
|
+
const c = input.charCodeAt(pos);
|
|
1126
|
+
if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
|
|
1127
|
+
const start = pos;
|
|
1128
|
+
pos++;
|
|
1129
|
+
while (pos < input.length) {
|
|
1130
|
+
const c2 = input.charCodeAt(pos);
|
|
1131
|
+
if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
|
|
1132
|
+
else break;
|
|
1133
|
+
}
|
|
1134
|
+
chunks.push({ start, end: pos, kindIndex: wsKind });
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
if (c === 47 && input.charCodeAt(pos + 1) === 42) {
|
|
1138
|
+
let j2 = pos + 2;
|
|
1139
|
+
while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
|
|
1140
|
+
if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
|
|
1141
|
+
const start = pos;
|
|
1142
|
+
pos = j2 + 2;
|
|
1143
|
+
chunks.push({ start, end: pos, kindIndex: commentKind });
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
return { end: pos, chunks };
|
|
1151
|
+
}
|
|
1152
|
+
function tryFastLabeledScan(input, cur, trivia2) {
|
|
1153
|
+
const spec = analyzeLabeledTrivia(trivia2);
|
|
1154
|
+
if (!spec || spec.arms.length !== 2) return null;
|
|
1155
|
+
const wsArm = spec.arms.find((a) => {
|
|
1156
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
1157
|
+
return src != null && !src.includes("\\*");
|
|
1158
|
+
});
|
|
1159
|
+
const commentArm = spec.arms.find((a) => {
|
|
1160
|
+
const src = getCoreRegexDef(a.parser)?.source;
|
|
1161
|
+
return src != null && src.includes("\\*");
|
|
1162
|
+
});
|
|
1163
|
+
if (!wsArm || !commentArm) return null;
|
|
1164
|
+
const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1165
|
+
if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
|
|
1166
|
+
return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1167
|
+
}
|
|
1168
|
+
function recordTriviaChunks(ctx, chunks) {
|
|
1169
|
+
const kinds = ctx.triviaKindLabels;
|
|
1170
|
+
const mask = ctx._triviaCaptureMask;
|
|
1171
|
+
for (const ch of chunks) {
|
|
1172
|
+
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1173
|
+
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
1174
|
+
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
1175
|
+
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
function triviaKindMask(labels, keep) {
|
|
1181
|
+
if (!labels) return void 0;
|
|
1182
|
+
let mask = 0;
|
|
1183
|
+
for (const name of keep) {
|
|
1184
|
+
const idx = labels.indexOf(name);
|
|
1185
|
+
if (idx >= 0) mask |= 1 << idx;
|
|
1186
|
+
}
|
|
1187
|
+
return mask;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
// src/combinators/grammar.ts
|
|
1191
|
+
function annotateResultLines(result, index) {
|
|
1192
|
+
const annotated = { ...result, span: annotateSpan(result.span, index) };
|
|
1193
|
+
const errors = annotated.errors;
|
|
1194
|
+
if (errors) {
|
|
1195
|
+
;
|
|
1196
|
+
annotated.errors = errors.map((error) => ({
|
|
1197
|
+
...error,
|
|
1198
|
+
span: annotateSpan(error.span, index)
|
|
1199
|
+
}));
|
|
1200
|
+
}
|
|
1201
|
+
return annotated;
|
|
1202
|
+
}
|
|
1203
|
+
function createParseLineContext(input, pos) {
|
|
1204
|
+
const lineIndex = createLineIndex();
|
|
1205
|
+
if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
|
|
1206
|
+
return { lineIndex, lineScannedTo: pos };
|
|
1207
|
+
}
|
|
1208
|
+
function parser(opts, root) {
|
|
1209
|
+
const clearTrivia = opts.trivia === null;
|
|
1210
|
+
return {
|
|
1211
|
+
_tag: "grammar",
|
|
1212
|
+
_meta: root._meta,
|
|
1213
|
+
_def: {
|
|
1214
|
+
tag: "grammar",
|
|
1215
|
+
parser: root,
|
|
1216
|
+
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
1217
|
+
clearTrivia,
|
|
1218
|
+
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
1219
|
+
trackLines: opts.trackLines ?? false
|
|
1220
|
+
},
|
|
1221
|
+
parse(input, pos, _ctx) {
|
|
1222
|
+
const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
|
|
1223
|
+
const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
|
|
1224
|
+
const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
|
|
1225
|
+
const ctx = {
|
|
1226
|
+
..._ctx,
|
|
1227
|
+
trackLines,
|
|
1228
|
+
...lineIndex ? { _lineIndex: lineIndex } : {},
|
|
1229
|
+
...lineContext ? { _lineScannedTo: lineContext.lineScannedTo } : {},
|
|
1230
|
+
// trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
|
|
1231
|
+
...clearTrivia ? {
|
|
1232
|
+
trivia: void 0,
|
|
1233
|
+
triviaKindLabels: void 0
|
|
1234
|
+
} : opts.trivia != null ? {
|
|
1235
|
+
trivia: opts.trivia,
|
|
1236
|
+
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
1237
|
+
} : {},
|
|
1238
|
+
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
1239
|
+
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
1240
|
+
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
1241
|
+
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
1242
|
+
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
1243
|
+
// (capture all).
|
|
1244
|
+
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
|
|
1245
|
+
};
|
|
1246
|
+
const result = root.parse(input, pos ?? 0, ctx);
|
|
1247
|
+
if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
|
|
1248
|
+
_ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
|
|
1249
|
+
}
|
|
1250
|
+
return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// src/combinators/parser.ts
|
|
1256
|
+
var RULE_ORDER = "__parsemanRuleOrder";
|
|
1257
|
+
function tagRule(r, key) {
|
|
1258
|
+
;
|
|
1259
|
+
r._ruleName = key;
|
|
1260
|
+
if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
|
|
1261
|
+
}
|
|
1262
|
+
function isDefinableRef(v) {
|
|
1263
|
+
return !!v && typeof v === "object" && "_def" in v && v._def.tag === "lazy" && typeof v.define === "function";
|
|
1264
|
+
}
|
|
1265
|
+
function ruleNameOf(r) {
|
|
1266
|
+
return r._ruleName;
|
|
1267
|
+
}
|
|
1268
|
+
function isNamedRuleRefForAnotherRule(r, key) {
|
|
1269
|
+
const name = r._def.tag === "lazy" ? ruleNameOf(r) : void 0;
|
|
1270
|
+
return name !== void 0 && name !== key;
|
|
1271
|
+
}
|
|
1272
|
+
function rules(a, b) {
|
|
1273
|
+
const factory = typeof a === "function" ? a : b;
|
|
1274
|
+
const options = typeof a === "function" ? b : a;
|
|
1275
|
+
const cache = {};
|
|
1276
|
+
const proxy = new Proxy(cache, {
|
|
1277
|
+
get(target, key) {
|
|
1278
|
+
if (typeof key !== "string") return void 0;
|
|
1279
|
+
const record = target;
|
|
1280
|
+
if (!(key in record)) {
|
|
1281
|
+
const r = ref();
|
|
1282
|
+
tagRule(r, key);
|
|
1283
|
+
record[key] = r;
|
|
1284
|
+
}
|
|
1285
|
+
return record[key];
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
const definitions = factory(proxy);
|
|
1289
|
+
for (const key of Object.keys(definitions)) {
|
|
1290
|
+
const placeholder = cache[key];
|
|
1291
|
+
const parser2 = definitions[key];
|
|
1292
|
+
if (placeholder === parser2) {
|
|
1293
|
+
throw new Error(`rules(): rule "${key}" cannot be a direct alias to itself`);
|
|
1294
|
+
}
|
|
1295
|
+
if (isDefinableRef(placeholder)) {
|
|
1296
|
+
if (!isNamedRuleRefForAnotherRule(parser2, key)) tagRule(parser2, key);
|
|
1297
|
+
placeholder.define(parser2);
|
|
1298
|
+
placeholder._meta.firstSet = parser2._meta.firstSet;
|
|
1299
|
+
placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1300
|
+
} else if (isNamedRuleRefForAnotherRule(parser2, key)) {
|
|
1301
|
+
const alias = ref();
|
|
1302
|
+
tagRule(alias, key);
|
|
1303
|
+
alias.define(parser2);
|
|
1304
|
+
alias._meta.firstSet = parser2._meta.firstSet;
|
|
1305
|
+
alias._meta.canMatchNewline = parser2._meta.canMatchNewline;
|
|
1306
|
+
cache[key] = alias;
|
|
1307
|
+
} else {
|
|
1308
|
+
tagRule(parser2, key);
|
|
1309
|
+
cache[key] = parser2;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
if (options?.trivia != null) {
|
|
1313
|
+
for (const key of Object.keys(definitions)) {
|
|
1314
|
+
const rule = cache[key];
|
|
1315
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
if (options?.scanSkip != null) {
|
|
1319
|
+
for (const key of Object.keys(definitions)) {
|
|
1320
|
+
const rule = cache[key];
|
|
1321
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
if (options?.hostMode === "cst") {
|
|
1325
|
+
for (const key of Object.keys(definitions)) {
|
|
1326
|
+
const rule = cache[key];
|
|
1327
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
if (options?.trackLines === true) {
|
|
1331
|
+
for (const key of Object.keys(definitions)) {
|
|
1332
|
+
const rule = cache[key];
|
|
1333
|
+
if (rule && !rule._meta.isTrivia) rule._meta.grammarTrackLines = true;
|
|
1334
|
+
}
|
|
1335
|
+
for (const key of Object.keys(definitions)) {
|
|
1336
|
+
const rule = cache[key];
|
|
1337
|
+
if (rule && !rule._meta.isTrivia && rule._def.tag !== "grammar") {
|
|
1338
|
+
const wrapped = parser({ trackLines: true }, rule);
|
|
1339
|
+
tagRule(wrapped, key);
|
|
1340
|
+
wrapped._meta.grammarTrackLines = true;
|
|
1341
|
+
cache[key] = wrapped;
|
|
1074
1342
|
}
|
|
1075
1343
|
}
|
|
1076
1344
|
}
|
|
1077
|
-
|
|
1345
|
+
for (const key of Object.keys(definitions)) {
|
|
1346
|
+
markUnusedValues(cache[key]);
|
|
1347
|
+
}
|
|
1348
|
+
Object.defineProperty(cache, RULE_ORDER, {
|
|
1349
|
+
value: Object.keys(definitions),
|
|
1350
|
+
enumerable: false,
|
|
1351
|
+
configurable: true
|
|
1352
|
+
});
|
|
1353
|
+
return cache;
|
|
1078
1354
|
}
|
|
1079
1355
|
|
|
1080
1356
|
// src/analysis/duplication.ts
|
|
@@ -1116,6 +1392,7 @@ function literal(value, opts = {}) {
|
|
|
1116
1392
|
canMatchNewline: value.includes("\n"),
|
|
1117
1393
|
isTrivia: false
|
|
1118
1394
|
};
|
|
1395
|
+
const canMatchNewline = meta.canMatchNewline;
|
|
1119
1396
|
if (caseInsensitive) {
|
|
1120
1397
|
const upper = value.toUpperCase();
|
|
1121
1398
|
const lower = value.toLowerCase();
|
|
@@ -1132,6 +1409,7 @@ function literal(value, opts = {}) {
|
|
|
1132
1409
|
return function parse2(input, pos, ctx) {
|
|
1133
1410
|
if (input.charCodeAt(pos) === code) {
|
|
1134
1411
|
const span = { start: pos, end: pos + 1 };
|
|
1412
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
1135
1413
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
|
|
1136
1414
|
return { ok: true, value, span };
|
|
1137
1415
|
}
|
|
@@ -1145,6 +1423,7 @@ function literal(value, opts = {}) {
|
|
|
1145
1423
|
const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
|
|
1146
1424
|
if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
|
|
1147
1425
|
const span = { start: pos, end };
|
|
1426
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, end);
|
|
1148
1427
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
|
|
1149
1428
|
return { ok: true, value: matchedValue, span };
|
|
1150
1429
|
}
|
|
@@ -1309,6 +1588,7 @@ function regex(pattern, flags = "") {
|
|
|
1309
1588
|
if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
|
|
1310
1589
|
const value = input.slice(pos, scanEnd);
|
|
1311
1590
|
const span2 = { start: pos, end: scanEnd };
|
|
1591
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
|
|
1312
1592
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
|
|
1313
1593
|
return { ok: true, value, span: span2 };
|
|
1314
1594
|
}
|
|
@@ -1318,141 +1598,13 @@ function regex(pattern, flags = "") {
|
|
|
1318
1598
|
return failAt(ctx, [`/${source}/`], pos);
|
|
1319
1599
|
}
|
|
1320
1600
|
const span = { start: pos, end: pos + m[0].length };
|
|
1601
|
+
if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
|
|
1321
1602
|
if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
|
|
1322
1603
|
return { ok: true, value: m[0], span };
|
|
1323
1604
|
}
|
|
1324
1605
|
};
|
|
1325
1606
|
}
|
|
1326
1607
|
|
|
1327
|
-
// src/cst/trivia-kinds.ts
|
|
1328
|
-
function unwrapTrivia(p) {
|
|
1329
|
-
let cur = p;
|
|
1330
|
-
while (cur._def.tag === "trivia") cur = cur._def.parser;
|
|
1331
|
-
return cur;
|
|
1332
|
-
}
|
|
1333
|
-
function peelLabel(p) {
|
|
1334
|
-
if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
|
|
1335
|
-
return null;
|
|
1336
|
-
}
|
|
1337
|
-
function analyzeLabeledTrivia(trivia2) {
|
|
1338
|
-
let core = unwrapTrivia(trivia2);
|
|
1339
|
-
let minRepeats = 1;
|
|
1340
|
-
if (core._def.tag === "oneOrMore") {
|
|
1341
|
-
core = core._def.parser;
|
|
1342
|
-
minRepeats = 1;
|
|
1343
|
-
} else if (core._def.tag === "many") {
|
|
1344
|
-
core = core._def.parser;
|
|
1345
|
-
minRepeats = 0;
|
|
1346
|
-
}
|
|
1347
|
-
const arms = [];
|
|
1348
|
-
if (core._def.tag === "choice") {
|
|
1349
|
-
for (let i = 0; i < core._def.parsers.length; i++) {
|
|
1350
|
-
const peeled = peelLabel(core._def.parsers[i]);
|
|
1351
|
-
if (!peeled) return null;
|
|
1352
|
-
arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
|
|
1353
|
-
}
|
|
1354
|
-
} else {
|
|
1355
|
-
const peeled = peelLabel(core);
|
|
1356
|
-
if (!peeled) return null;
|
|
1357
|
-
arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
|
|
1358
|
-
}
|
|
1359
|
-
return { labels: arms.map((a) => a.label), arms, minRepeats };
|
|
1360
|
-
}
|
|
1361
|
-
function matchArmAt(input, pos, arm) {
|
|
1362
|
-
const r = arm.parse(input, pos, { trackLines: false });
|
|
1363
|
-
if (!r.ok || r.span.end <= pos) return null;
|
|
1364
|
-
return { end: r.span.end };
|
|
1365
|
-
}
|
|
1366
|
-
function scanLabeledTriviaChunks(input, cur, spec) {
|
|
1367
|
-
const chunks = [];
|
|
1368
|
-
let pos = cur;
|
|
1369
|
-
while (pos < input.length) {
|
|
1370
|
-
let matched = null;
|
|
1371
|
-
for (const arm of spec.arms) {
|
|
1372
|
-
const m = matchArmAt(input, pos, arm.parser);
|
|
1373
|
-
if (m) {
|
|
1374
|
-
matched = { end: m.end, kindIndex: arm.kindIndex };
|
|
1375
|
-
break;
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
if (!matched) break;
|
|
1379
|
-
chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
|
|
1380
|
-
pos = matched.end;
|
|
1381
|
-
}
|
|
1382
|
-
if (chunks.length < spec.minRepeats) {
|
|
1383
|
-
return { end: cur, chunks: [] };
|
|
1384
|
-
}
|
|
1385
|
-
return { end: pos, chunks };
|
|
1386
|
-
}
|
|
1387
|
-
function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
|
|
1388
|
-
const chunks = [];
|
|
1389
|
-
let pos = cur;
|
|
1390
|
-
while (pos < input.length) {
|
|
1391
|
-
const c = input.charCodeAt(pos);
|
|
1392
|
-
if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
|
|
1393
|
-
const start = pos;
|
|
1394
|
-
pos++;
|
|
1395
|
-
while (pos < input.length) {
|
|
1396
|
-
const c2 = input.charCodeAt(pos);
|
|
1397
|
-
if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
|
|
1398
|
-
else break;
|
|
1399
|
-
}
|
|
1400
|
-
chunks.push({ start, end: pos, kindIndex: wsKind });
|
|
1401
|
-
continue;
|
|
1402
|
-
}
|
|
1403
|
-
if (c === 47 && input.charCodeAt(pos + 1) === 42) {
|
|
1404
|
-
let j2 = pos + 2;
|
|
1405
|
-
while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
|
|
1406
|
-
if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
|
|
1407
|
-
const start = pos;
|
|
1408
|
-
pos = j2 + 2;
|
|
1409
|
-
chunks.push({ start, end: pos, kindIndex: commentKind });
|
|
1410
|
-
continue;
|
|
1411
|
-
}
|
|
1412
|
-
break;
|
|
1413
|
-
}
|
|
1414
|
-
break;
|
|
1415
|
-
}
|
|
1416
|
-
return { end: pos, chunks };
|
|
1417
|
-
}
|
|
1418
|
-
function tryFastLabeledScan(input, cur, trivia2) {
|
|
1419
|
-
const spec = analyzeLabeledTrivia(trivia2);
|
|
1420
|
-
if (!spec || spec.arms.length !== 2) return null;
|
|
1421
|
-
const wsArm = spec.arms.find((a) => {
|
|
1422
|
-
const src = getCoreRegexDef(a.parser)?.source;
|
|
1423
|
-
return src != null && !src.includes("\\*");
|
|
1424
|
-
});
|
|
1425
|
-
const commentArm = spec.arms.find((a) => {
|
|
1426
|
-
const src = getCoreRegexDef(a.parser)?.source;
|
|
1427
|
-
return src != null && src.includes("\\*");
|
|
1428
|
-
});
|
|
1429
|
-
if (!wsArm || !commentArm) return null;
|
|
1430
|
-
const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1431
|
-
if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
|
|
1432
|
-
return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
|
|
1433
|
-
}
|
|
1434
|
-
function recordTriviaChunks(ctx, chunks) {
|
|
1435
|
-
const kinds = ctx.triviaKindLabels;
|
|
1436
|
-
const mask = ctx._triviaCaptureMask;
|
|
1437
|
-
for (const ch of chunks) {
|
|
1438
|
-
pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1439
|
-
if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
|
|
1440
|
-
if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
|
|
1441
|
-
pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
function triviaKindMask(labels, keep) {
|
|
1447
|
-
if (!labels) return void 0;
|
|
1448
|
-
let mask = 0;
|
|
1449
|
-
for (const name of keep) {
|
|
1450
|
-
const idx = labels.indexOf(name);
|
|
1451
|
-
if (idx >= 0) mask |= 1 << idx;
|
|
1452
|
-
}
|
|
1453
|
-
return mask;
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1608
|
// src/combinators/trivia-skip.ts
|
|
1457
1609
|
var NOOP_COMMIT = () => {
|
|
1458
1610
|
};
|
|
@@ -1468,6 +1620,18 @@ function rollbackTrivia(ctx, mark) {
|
|
|
1468
1620
|
rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
|
|
1469
1621
|
if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
|
|
1470
1622
|
}
|
|
1623
|
+
function parseTriviaNoCapture(triviaP, input, cur, ctx) {
|
|
1624
|
+
const probeCtx = {
|
|
1625
|
+
trackLines: ctx.trackLines,
|
|
1626
|
+
state: ctx.state,
|
|
1627
|
+
...ctx._lineIndex ? { _lineIndex: ctx._lineIndex } : {},
|
|
1628
|
+
...ctx._lineStarts ? { _lineStarts: ctx._lineStarts } : {},
|
|
1629
|
+
...ctx._lineScannedTo !== void 0 ? { _lineScannedTo: ctx._lineScannedTo } : {}
|
|
1630
|
+
};
|
|
1631
|
+
const result = triviaP.parse(input, cur, probeCtx);
|
|
1632
|
+
ctx._lineScannedTo = probeCtx._lineScannedTo;
|
|
1633
|
+
return result;
|
|
1634
|
+
}
|
|
1471
1635
|
function saveLookaheadMark(ctx) {
|
|
1472
1636
|
return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
|
|
1473
1637
|
}
|
|
@@ -1490,13 +1654,29 @@ function scanWithLabels(input, cur, ctx) {
|
|
|
1490
1654
|
function advanceTrivia(input, cur, ctx) {
|
|
1491
1655
|
const triviaP = ctx.trivia;
|
|
1492
1656
|
if (!triviaP) return cur;
|
|
1657
|
+
if (!ctx.trackLines) {
|
|
1658
|
+
const fast2 = fastTriviaScanner(triviaP);
|
|
1659
|
+
if (fast2) return fast2(input, cur);
|
|
1660
|
+
if (ctx.triviaKindLabels) {
|
|
1661
|
+
const scan = scanWithLabels(input, cur, ctx);
|
|
1662
|
+
return scan.end;
|
|
1663
|
+
}
|
|
1664
|
+
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1665
|
+
return tr2.ok && tr2.span.end > cur ? tr2.span.end : cur;
|
|
1666
|
+
}
|
|
1667
|
+
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1493
1668
|
const fast = fastTriviaScanner(triviaP);
|
|
1494
|
-
if (fast)
|
|
1669
|
+
if (fast) {
|
|
1670
|
+
const end = fast(input, cur);
|
|
1671
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1672
|
+
return end;
|
|
1673
|
+
}
|
|
1495
1674
|
if (ctx.triviaKindLabels) {
|
|
1496
1675
|
const scan = scanWithLabels(input, cur, ctx);
|
|
1676
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
|
|
1497
1677
|
return scan.end;
|
|
1498
1678
|
}
|
|
1499
|
-
const tr = triviaP
|
|
1679
|
+
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1500
1680
|
return tr.ok && tr.span.end > cur ? tr.span.end : cur;
|
|
1501
1681
|
}
|
|
1502
1682
|
function scanTrivia(input, cur, ctx) {
|
|
@@ -1504,18 +1684,46 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1504
1684
|
if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
|
|
1505
1685
|
const log = ctx._triviaLog;
|
|
1506
1686
|
const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
|
|
1687
|
+
if (!ctx.trackLines) {
|
|
1688
|
+
const fast2 = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1689
|
+
if (fast2 && log === void 0 && !captureTl) {
|
|
1690
|
+
return { end: fast2(input, cur), commit: NOOP_COMMIT };
|
|
1691
|
+
}
|
|
1692
|
+
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
1693
|
+
return scanWithLabels(input, cur, ctx);
|
|
1694
|
+
}
|
|
1695
|
+
if (log !== void 0 || captureTl) {
|
|
1696
|
+
const tr3 = triviaP.parse(input, cur, {
|
|
1697
|
+
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
1698
|
+
state: ctx.state
|
|
1699
|
+
});
|
|
1700
|
+
if (!tr3.ok || tr3.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1701
|
+
const end = tr3.span.end;
|
|
1702
|
+
return {
|
|
1703
|
+
end,
|
|
1704
|
+
commit: () => {
|
|
1705
|
+
pushTriviaLogEntry(ctx, cur, end);
|
|
1706
|
+
if (captureTl) pushCstTriviaEntry(ctx, cur, end);
|
|
1707
|
+
}
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
const tr2 = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
|
|
1711
|
+
return { end: tr2.ok ? tr2.span.end : cur, commit: NOOP_COMMIT };
|
|
1712
|
+
}
|
|
1713
|
+
const trackTriviaLines = ctx.trackLines && triviaP._meta.canMatchNewline;
|
|
1507
1714
|
const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
|
|
1508
1715
|
if (fast && log === void 0 && !captureTl) {
|
|
1509
|
-
|
|
1716
|
+
const end = fast(input, cur);
|
|
1717
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, end);
|
|
1718
|
+
return { end, commit: NOOP_COMMIT };
|
|
1510
1719
|
}
|
|
1511
1720
|
if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
|
|
1512
|
-
|
|
1721
|
+
const scan = scanWithLabels(input, cur, ctx);
|
|
1722
|
+
if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
|
|
1723
|
+
return scan;
|
|
1513
1724
|
}
|
|
1514
1725
|
if (log !== void 0 || captureTl) {
|
|
1515
|
-
const tr2 = triviaP
|
|
1516
|
-
trackLines: log !== void 0 ? false : ctx.trackLines,
|
|
1517
|
-
state: ctx.state
|
|
1518
|
-
});
|
|
1726
|
+
const tr2 = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1519
1727
|
if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
|
|
1520
1728
|
const end = tr2.span.end;
|
|
1521
1729
|
return {
|
|
@@ -1526,7 +1734,7 @@ function scanTrivia(input, cur, ctx) {
|
|
|
1526
1734
|
}
|
|
1527
1735
|
};
|
|
1528
1736
|
}
|
|
1529
|
-
const tr = triviaP
|
|
1737
|
+
const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
|
|
1530
1738
|
return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
|
|
1531
1739
|
}
|
|
1532
1740
|
function consumeTrivia(input, cur, ctx) {
|
|
@@ -2179,7 +2387,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2179
2387
|
let cur = pos;
|
|
2180
2388
|
const skip3 = resolveScanSkip(explicitSkip, raw, ctx);
|
|
2181
2389
|
const probeCtx = {
|
|
2182
|
-
trackLines:
|
|
2390
|
+
trackLines: false,
|
|
2183
2391
|
state: ctx.state,
|
|
2184
2392
|
...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
|
|
2185
2393
|
};
|
|
@@ -2192,6 +2400,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2192
2400
|
while (cur < input.length) {
|
|
2193
2401
|
const s = sentinel.parse(input, cur, probeCtx);
|
|
2194
2402
|
if (s.ok) {
|
|
2403
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
|
|
2195
2404
|
emit(cur);
|
|
2196
2405
|
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
2197
2406
|
}
|
|
@@ -2207,6 +2416,7 @@ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
|
|
|
2207
2416
|
if (!advanced) cur++;
|
|
2208
2417
|
}
|
|
2209
2418
|
if (orEOF) {
|
|
2419
|
+
if (ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, cur);
|
|
2210
2420
|
emit(cur);
|
|
2211
2421
|
return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
|
|
2212
2422
|
}
|
|
@@ -2816,89 +3026,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
|
|
|
2816
3026
|
const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
2817
3027
|
const nodeType = def.type ?? missingInferredType();
|
|
2818
3028
|
const cstOutput = cstOutputHost(ctx.build);
|
|
3029
|
+
const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
|
|
2819
3030
|
const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
|
|
2820
|
-
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields,
|
|
2821
|
-
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
|
|
3031
|
+
const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
|
|
3032
|
+
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 };
|
|
2822
3033
|
if (saved.buf !== void 0 || saved.ch !== void 0) {
|
|
2823
3034
|
pushCstChild(ctx, built, rawEntry);
|
|
2824
3035
|
}
|
|
2825
|
-
return { ok: true, value: built, span
|
|
2826
|
-
}
|
|
2827
|
-
};
|
|
2828
|
-
}
|
|
2829
|
-
|
|
2830
|
-
// src/compiler/line-index.ts
|
|
2831
|
-
function buildLineIndex(input) {
|
|
2832
|
-
const lineStarts = [0];
|
|
2833
|
-
for (let i = 0; i < input.length; i++) {
|
|
2834
|
-
if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
|
|
2835
|
-
}
|
|
2836
|
-
return { lineStarts };
|
|
2837
|
-
}
|
|
2838
|
-
function offsetToLineCol(index, offset) {
|
|
2839
|
-
const { lineStarts } = index;
|
|
2840
|
-
let lo = 0;
|
|
2841
|
-
let hi = lineStarts.length - 1;
|
|
2842
|
-
while (lo < hi) {
|
|
2843
|
-
const mid = lo + hi + 1 >> 1;
|
|
2844
|
-
if (lineStarts[mid] <= offset) lo = mid;
|
|
2845
|
-
else hi = mid - 1;
|
|
2846
|
-
}
|
|
2847
|
-
return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
|
|
2848
|
-
}
|
|
2849
|
-
function annotateSpan(span, index) {
|
|
2850
|
-
const s = offsetToLineCol(index, span.start);
|
|
2851
|
-
const e = offsetToLineCol(index, span.end);
|
|
2852
|
-
return {
|
|
2853
|
-
...span,
|
|
2854
|
-
startLine: s.line,
|
|
2855
|
-
startColumn: s.col,
|
|
2856
|
-
endLine: e.line,
|
|
2857
|
-
endColumn: e.col
|
|
2858
|
-
};
|
|
2859
|
-
}
|
|
2860
|
-
|
|
2861
|
-
// src/combinators/grammar.ts
|
|
2862
|
-
function parser(opts, root) {
|
|
2863
|
-
const clearTrivia = opts.trivia === null;
|
|
2864
|
-
return {
|
|
2865
|
-
_tag: "grammar",
|
|
2866
|
-
_meta: root._meta,
|
|
2867
|
-
_def: {
|
|
2868
|
-
tag: "grammar",
|
|
2869
|
-
parser: root,
|
|
2870
|
-
triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
|
|
2871
|
-
clearTrivia,
|
|
2872
|
-
...opts.captureTrivia ? { captureTrivia: true } : {},
|
|
2873
|
-
trackLines: opts.trackLines ?? false
|
|
2874
|
-
},
|
|
2875
|
-
parse(input, pos, _ctx) {
|
|
2876
|
-
const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
|
|
2877
|
-
const ctx = {
|
|
2878
|
-
..._ctx,
|
|
2879
|
-
trackLines,
|
|
2880
|
-
// trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
|
|
2881
|
-
...clearTrivia ? {
|
|
2882
|
-
trivia: void 0,
|
|
2883
|
-
triviaKindLabels: void 0
|
|
2884
|
-
} : opts.trivia != null ? {
|
|
2885
|
-
trivia: opts.trivia,
|
|
2886
|
-
...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
|
|
2887
|
-
} : {},
|
|
2888
|
-
...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
|
|
2889
|
-
// Kind-filter for per-node capture. Resolve against this scope's trivia
|
|
2890
|
-
// labels — this parser's own trivia if it declares one, else the INHERITED
|
|
2891
|
-
// labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
|
|
2892
|
-
// trivia is inherited rather than re-declared here. No labels → undefined
|
|
2893
|
-
// (capture all).
|
|
2894
|
-
...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
|
|
2895
|
-
};
|
|
2896
|
-
const result = root.parse(input, pos ?? 0, ctx);
|
|
2897
|
-
if (trackLines) {
|
|
2898
|
-
const idx = buildLineIndex(input);
|
|
2899
|
-
return { ...result, span: annotateSpan(result.span, idx) };
|
|
2900
|
-
}
|
|
2901
|
-
return result;
|
|
3036
|
+
return { ok: true, value: built, span };
|
|
2902
3037
|
}
|
|
2903
3038
|
};
|
|
2904
3039
|
}
|
|
@@ -3186,7 +3321,7 @@ function normalizeCstCollapse(collapse) {
|
|
|
3186
3321
|
return typeof collapse === "function" ? collapse : void 0;
|
|
3187
3322
|
}
|
|
3188
3323
|
function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
|
|
3189
|
-
return { _tag: "node", type, span: {
|
|
3324
|
+
return { _tag: "node", type, span: { ...span }, state: state ?? null, children: [...children] };
|
|
3190
3325
|
}
|
|
3191
3326
|
function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
|
|
3192
3327
|
if (typeof typeOrOptions === "string") {
|