parseman 0.24.0 → 0.25.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/README.md +1 -1
- package/dist/cst/relative-spans.d.ts +32 -0
- package/dist/cst/relative-spans.d.ts.map +1 -1
- package/dist/functional/doc.d.ts +53 -3
- package/dist/functional/doc.d.ts.map +1 -1
- package/dist/index.cjs +319 -100
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +319 -100
- package/dist/index.js.map +4 -4
- package/dist/plugin/index.cjs.map +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/spec/index.cjs +67 -6
- package/dist/spec/index.cjs.map +3 -3
- package/dist/spec/index.d.ts +10 -2
- package/dist/spec/index.d.ts.map +1 -1
- package/dist/spec/index.js +67 -6
- package/dist/spec/index.js.map +3 -3
- package/dist/spec/model.d.ts.map +1 -1
- package/dist/spec/railroad.d.ts +12 -0
- package/dist/spec/railroad.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,9 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
OffsetIndex: () => OffsetIndex,
|
|
24
24
|
absoluteSpanAt: () => absoluteSpanAt,
|
|
25
|
+
absoluteSpanCST: () => absoluteSpanCST,
|
|
25
26
|
absolutize: () => absolutize,
|
|
27
|
+
absolutizeCST: () => absolutizeCST,
|
|
26
28
|
annotateSpan: () => annotateSpan,
|
|
27
29
|
applyEdit: () => applyEdit,
|
|
28
30
|
balanced: () => balanced,
|
|
@@ -67,6 +69,7 @@ __export(index_exports, {
|
|
|
67
69
|
ref: () => ref,
|
|
68
70
|
regex: () => regex,
|
|
69
71
|
relativize: () => relativize,
|
|
72
|
+
relativizeCST: () => relativizeCST,
|
|
70
73
|
rules: () => rules,
|
|
71
74
|
run: () => run,
|
|
72
75
|
scanTo: () => scanTo,
|
|
@@ -6481,17 +6484,159 @@ function manyRecover(item, until) {
|
|
|
6481
6484
|
return many(tolerantElement(item, until, until));
|
|
6482
6485
|
}
|
|
6483
6486
|
|
|
6487
|
+
// src/cst/relative-spans.ts
|
|
6488
|
+
function relativize(node2, parentBase = 0) {
|
|
6489
|
+
return {
|
|
6490
|
+
start: node2.start - parentBase,
|
|
6491
|
+
end: node2.end - parentBase,
|
|
6492
|
+
children: node2.children.map((c) => relativize(c, node2.start))
|
|
6493
|
+
};
|
|
6494
|
+
}
|
|
6495
|
+
function absolutize(node2, parentBase = 0) {
|
|
6496
|
+
const start = parentBase + node2.start;
|
|
6497
|
+
return {
|
|
6498
|
+
start,
|
|
6499
|
+
end: parentBase + node2.end,
|
|
6500
|
+
children: node2.children.map((c) => absolutize(c, start))
|
|
6501
|
+
};
|
|
6502
|
+
}
|
|
6503
|
+
function absoluteSpanAt(root, path) {
|
|
6504
|
+
let base = 0;
|
|
6505
|
+
let node2 = root;
|
|
6506
|
+
for (const idx of path) {
|
|
6507
|
+
base += node2.start;
|
|
6508
|
+
const child = node2.children[idx];
|
|
6509
|
+
if (!child) throw new RangeError(`absoluteSpanAt: no child ${idx} on path ${path.join(".")}`);
|
|
6510
|
+
node2 = child;
|
|
6511
|
+
}
|
|
6512
|
+
return { start: base + node2.start, end: base + node2.end };
|
|
6513
|
+
}
|
|
6514
|
+
function relativizeCST(node2, parentBase = 0) {
|
|
6515
|
+
const span = { start: node2.span.start - parentBase, end: node2.span.end - parentBase };
|
|
6516
|
+
if (node2.children) {
|
|
6517
|
+
const base = node2.span.start;
|
|
6518
|
+
return { ...node2, span, children: node2.children.map((c) => relativizeCST(c, base)) };
|
|
6519
|
+
}
|
|
6520
|
+
return { ...node2, span };
|
|
6521
|
+
}
|
|
6522
|
+
function absolutizeCST(node2, parentBase = 0) {
|
|
6523
|
+
const start = parentBase + node2.span.start;
|
|
6524
|
+
const span = { start, end: parentBase + node2.span.end };
|
|
6525
|
+
if (node2.children) {
|
|
6526
|
+
return { ...node2, span, children: node2.children.map((c) => absolutizeCST(c, start)) };
|
|
6527
|
+
}
|
|
6528
|
+
return { ...node2, span };
|
|
6529
|
+
}
|
|
6530
|
+
function absoluteSpanCST(root, path) {
|
|
6531
|
+
let base = 0;
|
|
6532
|
+
let node2 = root;
|
|
6533
|
+
for (const idx of path) {
|
|
6534
|
+
base += node2.span.start;
|
|
6535
|
+
const child = node2.children?.[idx];
|
|
6536
|
+
if (!child) throw new RangeError(`absoluteSpanCST: no child ${idx} on path ${path.join(".")}`);
|
|
6537
|
+
node2 = child;
|
|
6538
|
+
}
|
|
6539
|
+
return { start: base + node2.span.start, end: base + node2.span.end };
|
|
6540
|
+
}
|
|
6541
|
+
function shiftAbsolute(node2, at, delta) {
|
|
6542
|
+
const s = node2.start >= at ? node2.start + delta : node2.start;
|
|
6543
|
+
const e = node2.end >= at ? node2.end + delta : node2.end;
|
|
6544
|
+
return {
|
|
6545
|
+
start: s,
|
|
6546
|
+
end: e,
|
|
6547
|
+
children: node2.children.map((c) => shiftAbsolute(c, at, delta))
|
|
6548
|
+
};
|
|
6549
|
+
}
|
|
6550
|
+
function applyEdit(root, at, delta, stats) {
|
|
6551
|
+
return editNode(root, at, delta, 0, 0, stats);
|
|
6552
|
+
}
|
|
6553
|
+
function editNode(node2, at, delta, parentBase, parentShift, stats) {
|
|
6554
|
+
const absStart = parentBase + node2.start;
|
|
6555
|
+
const absEnd = parentBase + node2.end;
|
|
6556
|
+
if (absEnd < at) return node2;
|
|
6557
|
+
const startShifts = absStart >= at;
|
|
6558
|
+
if (startShifts && parentShift === delta) return node2;
|
|
6559
|
+
if (stats) stats.allocated++;
|
|
6560
|
+
const newAbsStart = startShifts ? absStart + delta : absStart;
|
|
6561
|
+
const newAbsEnd = absEnd + delta;
|
|
6562
|
+
const newParentBase = parentBase + parentShift;
|
|
6563
|
+
const newStart = newAbsStart - newParentBase;
|
|
6564
|
+
const newEnd = newAbsEnd - newParentBase;
|
|
6565
|
+
const ownShift = newAbsStart - absStart;
|
|
6566
|
+
let changed = false;
|
|
6567
|
+
const newChildren = [];
|
|
6568
|
+
for (const c of node2.children) {
|
|
6569
|
+
const nc = editNode(c, at, delta, absStart, ownShift, stats);
|
|
6570
|
+
if (nc !== c) changed = true;
|
|
6571
|
+
newChildren.push(nc);
|
|
6572
|
+
}
|
|
6573
|
+
return {
|
|
6574
|
+
start: newStart,
|
|
6575
|
+
end: newEnd,
|
|
6576
|
+
children: changed ? newChildren : node2.children
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6579
|
+
|
|
6484
6580
|
// src/functional/doc.ts
|
|
6581
|
+
function asRuleFn(entry) {
|
|
6582
|
+
return typeof entry === "function" ? entry : (input, pos, ctx) => entry.parse(input, pos, ctx);
|
|
6583
|
+
}
|
|
6584
|
+
function defOf(entry) {
|
|
6585
|
+
return typeof entry === "object" && entry !== null && "_def" in entry ? entry._def : void 0;
|
|
6586
|
+
}
|
|
6587
|
+
function producesRepetition(def, depth = 0) {
|
|
6588
|
+
if (!def || depth > 24) return false;
|
|
6589
|
+
const d = def;
|
|
6590
|
+
switch (d.tag) {
|
|
6591
|
+
case "sepBy":
|
|
6592
|
+
case "many":
|
|
6593
|
+
case "oneOrMore":
|
|
6594
|
+
return true;
|
|
6595
|
+
// Rule entries and `ref`s wrap their body in a `lazy` thunk — resolve it. The
|
|
6596
|
+
// `depth` cap bounds any self-referential cycle (a repetition, if present, is
|
|
6597
|
+
// found shallowly before recursion goes deep).
|
|
6598
|
+
case "lazy": {
|
|
6599
|
+
const thunk = d.thunk;
|
|
6600
|
+
let inner;
|
|
6601
|
+
try {
|
|
6602
|
+
inner = typeof thunk === "function" ? thunk() : void 0;
|
|
6603
|
+
} catch {
|
|
6604
|
+
return false;
|
|
6605
|
+
}
|
|
6606
|
+
return producesRepetition(inner?._def, depth + 1);
|
|
6607
|
+
}
|
|
6608
|
+
// Transparent wrappers — look through to the inner parser.
|
|
6609
|
+
case "node":
|
|
6610
|
+
case "transform":
|
|
6611
|
+
case "token":
|
|
6612
|
+
case "label":
|
|
6613
|
+
case "field":
|
|
6614
|
+
case "expect":
|
|
6615
|
+
case "withCtx":
|
|
6616
|
+
case "grammar":
|
|
6617
|
+
case "optional":
|
|
6618
|
+
return producesRepetition(defOf(d.parser), depth + 1);
|
|
6619
|
+
case "skip":
|
|
6620
|
+
return producesRepetition(defOf(d.main), depth + 1);
|
|
6621
|
+
// A bracketed/anchored list is a sequence whose element run is a repetition.
|
|
6622
|
+
case "sequence":
|
|
6623
|
+
return d.parsers.some((p) => producesRepetition(defOf(p), depth + 1));
|
|
6624
|
+
default:
|
|
6625
|
+
return false;
|
|
6626
|
+
}
|
|
6627
|
+
}
|
|
6485
6628
|
var REENTRY_MAX_SPAN_FRACTION = 0.5;
|
|
6486
6629
|
function isNode(x) {
|
|
6487
6630
|
return typeof x === "object" && x !== null && x._tag === "node";
|
|
6488
6631
|
}
|
|
6489
|
-
function findContaining(node2, pos, path = []) {
|
|
6632
|
+
function findContaining(node2, nodeAbsStart, pos, path = []) {
|
|
6490
6633
|
for (let i = 0; i < node2.children.length; i++) {
|
|
6491
6634
|
const child = node2.children[i];
|
|
6492
6635
|
if (!isNode(child)) continue;
|
|
6493
|
-
|
|
6494
|
-
|
|
6636
|
+
const childAbsStart = nodeAbsStart + child.span.start;
|
|
6637
|
+
const childAbsEnd = nodeAbsStart + child.span.end;
|
|
6638
|
+
if (childAbsStart <= pos && pos < childAbsEnd) {
|
|
6639
|
+
const inner = findContaining(child, childAbsStart, pos, [...path, i]);
|
|
6495
6640
|
return inner ?? { node: child, path: [...path, i] };
|
|
6496
6641
|
}
|
|
6497
6642
|
}
|
|
@@ -6518,24 +6663,20 @@ function replaceAtPath(rebuild, root, path, newNode) {
|
|
|
6518
6663
|
function defaultRebuild(node2, children) {
|
|
6519
6664
|
return { ...node2, children };
|
|
6520
6665
|
}
|
|
6521
|
-
function
|
|
6666
|
+
function shiftRelStart(child, delta) {
|
|
6522
6667
|
const c = child;
|
|
6523
|
-
|
|
6524
|
-
if (Array.isArray(c.children)) {
|
|
6525
|
-
return { ...c, span, children: c.children.map((g) => shiftSpans(g, delta)) };
|
|
6526
|
-
}
|
|
6527
|
-
return { ...c, span };
|
|
6668
|
+
return { ...c, span: { start: c.span.start + delta, end: c.span.end + delta } };
|
|
6528
6669
|
}
|
|
6529
|
-
function
|
|
6670
|
+
function graftRelative(root, path, newNode, delta) {
|
|
6530
6671
|
if (path.length === 0) return newNode;
|
|
6531
6672
|
const [idx, ...rest] = path;
|
|
6532
6673
|
const oldChildren = root.children;
|
|
6533
6674
|
const newChildren = oldChildren.map((child, i) => {
|
|
6534
6675
|
if (i < idx) return child;
|
|
6535
6676
|
if (i === idx) {
|
|
6536
|
-
return rest.length === 0 ? newNode :
|
|
6677
|
+
return rest.length === 0 ? newNode : graftRelative(child, rest, newNode, delta);
|
|
6537
6678
|
}
|
|
6538
|
-
return
|
|
6679
|
+
return shiftRelStart(child, delta);
|
|
6539
6680
|
});
|
|
6540
6681
|
return {
|
|
6541
6682
|
...root,
|
|
@@ -6543,6 +6684,96 @@ function graftAndShift(root, path, newNode, delta) {
|
|
|
6543
6684
|
children: newChildren
|
|
6544
6685
|
};
|
|
6545
6686
|
}
|
|
6687
|
+
function parseMiddle(input, reStart, reEnd, cStart, ruleFn, separator, build) {
|
|
6688
|
+
const ctx = { trackLines: false, state: null, build };
|
|
6689
|
+
const out = [];
|
|
6690
|
+
let pos = reStart;
|
|
6691
|
+
let guard2 = 0;
|
|
6692
|
+
while (pos < reEnd) {
|
|
6693
|
+
if (++guard2 > reEnd - reStart + 2) return null;
|
|
6694
|
+
if (separator && out.length > 0 && out[out.length - 1]._tag === "node") {
|
|
6695
|
+
if (pos + separator.length > reEnd || !input.startsWith(separator, pos)) return null;
|
|
6696
|
+
out.push({ _tag: "leaf", value: separator, span: { start: pos - cStart, end: pos + separator.length - cStart } });
|
|
6697
|
+
pos += separator.length;
|
|
6698
|
+
continue;
|
|
6699
|
+
}
|
|
6700
|
+
let r;
|
|
6701
|
+
try {
|
|
6702
|
+
r = ruleFn(input, pos, ctx);
|
|
6703
|
+
} catch {
|
|
6704
|
+
return null;
|
|
6705
|
+
}
|
|
6706
|
+
if (!r.ok || r.span.end <= pos || r.span.end > reEnd) return null;
|
|
6707
|
+
out.push(relativizeCST(r.value, cStart));
|
|
6708
|
+
pos = r.span.end;
|
|
6709
|
+
}
|
|
6710
|
+
return pos === reEnd ? out : null;
|
|
6711
|
+
}
|
|
6712
|
+
function tryListSplice(root, path, C, cStart, newInput, from, to, delta, registry, build) {
|
|
6713
|
+
const kids = C.children;
|
|
6714
|
+
if (kids.length === 0) return null;
|
|
6715
|
+
let h = 0;
|
|
6716
|
+
while (h < kids.length && cStart + kids[h].span.end <= from) h++;
|
|
6717
|
+
while (h > 0 && kids[h - 1]._tag === "node") h--;
|
|
6718
|
+
let t = kids.length;
|
|
6719
|
+
while (t > h && cStart + kids[t - 1].span.start >= to) t--;
|
|
6720
|
+
while (t < kids.length && kids[t]._tag !== "node") t++;
|
|
6721
|
+
if (t >= kids.length) return null;
|
|
6722
|
+
for (let i = t; i < kids.length; i++) {
|
|
6723
|
+
if (kids[i]._tag === "node" && kids[i].state != null) return null;
|
|
6724
|
+
}
|
|
6725
|
+
let elemType;
|
|
6726
|
+
let elemCount = 0;
|
|
6727
|
+
for (const k of kids) {
|
|
6728
|
+
if (k._tag !== "node") continue;
|
|
6729
|
+
elemCount++;
|
|
6730
|
+
if (elemType === void 0) elemType = k.type;
|
|
6731
|
+
else if (k.type !== elemType) return null;
|
|
6732
|
+
}
|
|
6733
|
+
if (elemType === void 0 || elemCount < 2) return null;
|
|
6734
|
+
const ruleFn = registry[elemType];
|
|
6735
|
+
if (!ruleFn) return null;
|
|
6736
|
+
let separator = null;
|
|
6737
|
+
for (let i = 1; i < kids.length - 1; i++) {
|
|
6738
|
+
if (kids[i - 1]._tag === "node" && kids[i + 1]._tag === "node") {
|
|
6739
|
+
if (kids[i]._tag !== "leaf") return null;
|
|
6740
|
+
const sep = kids[i].value ?? null;
|
|
6741
|
+
if (separator === null) separator = sep;
|
|
6742
|
+
else if (sep !== separator) return null;
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
if (separator === null) return null;
|
|
6746
|
+
const first = kids[0];
|
|
6747
|
+
const last = kids[kids.length - 1];
|
|
6748
|
+
if (first._tag === "leaf" && first.value !== separator && from < cStart + first.span.end) return null;
|
|
6749
|
+
if (last._tag === "leaf" && last.value !== separator && to > cStart + last.span.start) return null;
|
|
6750
|
+
const reStart = h > 0 ? cStart + kids[h - 1].span.end : cStart;
|
|
6751
|
+
const reEnd = cStart + kids[t].span.start + delta;
|
|
6752
|
+
if (reEnd < reStart) return null;
|
|
6753
|
+
const middle = parseMiddle(newInput, reStart, reEnd, cStart, ruleFn, separator, build);
|
|
6754
|
+
if (!middle) return null;
|
|
6755
|
+
if (middle.length > 0) {
|
|
6756
|
+
const last2 = middle[middle.length - 1];
|
|
6757
|
+
if (!(last2._tag === "leaf" && last2.value === separator)) return null;
|
|
6758
|
+
}
|
|
6759
|
+
if (reEnd < newInput.length) {
|
|
6760
|
+
for (const sentinel of [" ", "\uFFFF"]) {
|
|
6761
|
+
if (newInput[reEnd] === sentinel) continue;
|
|
6762
|
+
const probed = newInput.slice(0, reEnd) + sentinel.repeat(newInput.length - reEnd);
|
|
6763
|
+
const probe = parseMiddle(probed, reStart, reEnd, cStart, ruleFn, separator, build);
|
|
6764
|
+
if (!probe || probe.length !== middle.length) return null;
|
|
6765
|
+
for (let i = 0; i < middle.length; i++) if (!structurallyEqual(probe[i], middle[i])) return null;
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
const head = kids.slice(0, h);
|
|
6769
|
+
const tail = kids.slice(t).map((k) => shiftRelStart(k, delta));
|
|
6770
|
+
const newC = {
|
|
6771
|
+
...C,
|
|
6772
|
+
span: { start: C.span.start, end: C.span.end + delta },
|
|
6773
|
+
children: [...head, ...middle, ...tail]
|
|
6774
|
+
};
|
|
6775
|
+
return graftRelative(root, path, newC, delta);
|
|
6776
|
+
}
|
|
6546
6777
|
function structurallyEqual(a, b) {
|
|
6547
6778
|
if (a === b) return true;
|
|
6548
6779
|
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
@@ -6586,27 +6817,68 @@ function boundaryIsSafe(ruleFn, newInput, start, boundary, state, build, produce
|
|
|
6586
6817
|
}
|
|
6587
6818
|
var ParseDocImpl = class _ParseDocImpl {
|
|
6588
6819
|
_registry;
|
|
6820
|
+
/** Registry entries normalized to callable parse functions (memoized once). */
|
|
6821
|
+
_fns;
|
|
6822
|
+
/** Rule names the grammar proves are genuine repetitions — the ONLY splice-safe types. */
|
|
6823
|
+
_reps;
|
|
6589
6824
|
_rootRule;
|
|
6590
6825
|
_opts;
|
|
6591
|
-
|
|
6826
|
+
/**
|
|
6827
|
+
* The tree, held in whichever coordinate system it arrived in. A fresh parse
|
|
6828
|
+
* arrives ABSOLUTE (`_abs` set); an incremental graft arrives PARENT-RELATIVE
|
|
6829
|
+
* (`_rel` set). The public `tree` is always the RELATIVE form (so untouched
|
|
6830
|
+
* subtrees stay shared by identity across edits and reads are O(1)); it's
|
|
6831
|
+
* materialized from `_abs` once, on demand, and memoized. `undefined` = not yet
|
|
6832
|
+
* computed; `null` = failed parse. A fresh parse that's never edited nor
|
|
6833
|
+
* tree-read pays no conversion — important for the full-reparse fallback path.
|
|
6834
|
+
*/
|
|
6835
|
+
_abs;
|
|
6836
|
+
_rel;
|
|
6592
6837
|
errors;
|
|
6593
6838
|
input;
|
|
6594
|
-
constructor(registry, rootRule, opts,
|
|
6839
|
+
constructor(registry, rootRule, opts, trees, errors, input) {
|
|
6595
6840
|
this._registry = registry;
|
|
6841
|
+
this._fns = {};
|
|
6842
|
+
this._reps = /* @__PURE__ */ new Set();
|
|
6843
|
+
for (const [name, entry] of Object.entries(registry)) {
|
|
6844
|
+
this._fns[name] = asRuleFn(entry);
|
|
6845
|
+
if (producesRepetition(defOf(entry))) this._reps.add(name);
|
|
6846
|
+
}
|
|
6596
6847
|
this._rootRule = rootRule;
|
|
6597
6848
|
this._opts = opts;
|
|
6598
|
-
this.
|
|
6849
|
+
this._abs = trees.abs;
|
|
6850
|
+
this._rel = trees.rel;
|
|
6599
6851
|
this.errors = errors;
|
|
6600
6852
|
this.input = input;
|
|
6601
6853
|
}
|
|
6854
|
+
/**
|
|
6855
|
+
* The parse tree with PARENT-RELATIVE spans — a node's `span` is relative to
|
|
6856
|
+
* its parent's start (root base 0). This is the shareable representation:
|
|
6857
|
+
* untouched subtrees keep the same identity across `.edit()`s, and reading the
|
|
6858
|
+
* tree after a length-changing edit is O(1) (no offset rewrite). For absolute
|
|
6859
|
+
* positions use the O(depth) cursor `spanAt(path)`, or `absolutizeCST(tree)` to
|
|
6860
|
+
* materialize the whole absolute tree. (A fresh non-incremental `node().parse()`
|
|
6861
|
+
* result is unchanged — still absolute.)
|
|
6862
|
+
*/
|
|
6863
|
+
get tree() {
|
|
6864
|
+
if (this._rel === void 0) {
|
|
6865
|
+
this._rel = this._abs ? relativizeCST(this._abs, 0) : null;
|
|
6866
|
+
}
|
|
6867
|
+
return this._rel;
|
|
6868
|
+
}
|
|
6869
|
+
spanAt(path) {
|
|
6870
|
+
const rel = this.tree;
|
|
6871
|
+
if (!rel) throw new Error("spanAt on a failed parse (tree is null)");
|
|
6872
|
+
return absoluteSpanCST(rel, path);
|
|
6873
|
+
}
|
|
6602
6874
|
edit(from, to, replacement) {
|
|
6603
6875
|
const newInput = this.input.slice(0, from) + replacement + this.input.slice(to);
|
|
6604
6876
|
const reparse = () => parseDoc(this._registry, this._rootRule, newInput, this._opts);
|
|
6605
|
-
|
|
6877
|
+
const root = this.tree;
|
|
6878
|
+
if (!root) return reparse();
|
|
6606
6879
|
const delta = replacement.length - (to - from);
|
|
6607
|
-
const found = findContaining(
|
|
6608
|
-
|
|
6609
|
-
const ancestors = ancestorsAt(this.tree, found.path);
|
|
6880
|
+
const found = findContaining(root, 0, from) ?? { node: root, path: [] };
|
|
6881
|
+
const ancestors = ancestorsAt(root, found.path);
|
|
6610
6882
|
const candidates = [found];
|
|
6611
6883
|
const pathCopy = [...found.path];
|
|
6612
6884
|
for (let i = ancestors.length - 2; i >= 0; i--) {
|
|
@@ -6615,37 +6887,50 @@ var ParseDocImpl = class _ParseDocImpl {
|
|
|
6615
6887
|
}
|
|
6616
6888
|
const rebuild = this._opts.rebuild ?? defaultRebuild;
|
|
6617
6889
|
for (const { node: node2, path } of candidates) {
|
|
6618
|
-
|
|
6619
|
-
|
|
6890
|
+
const { start: absStart, end: absEnd } = absoluteSpanCST(root, path);
|
|
6891
|
+
if (absEnd - absStart > this.input.length * REENTRY_MAX_SPAN_FRACTION) break;
|
|
6892
|
+
const ruleFn = this._fns[node2.type];
|
|
6620
6893
|
if (!ruleFn) continue;
|
|
6621
|
-
if (!(
|
|
6894
|
+
if (!(absStart <= from && to <= absEnd)) continue;
|
|
6622
6895
|
const ctx = { trackLines: false, state: node2.state, build: this._opts.build };
|
|
6623
|
-
const r = ruleFn(newInput,
|
|
6896
|
+
const r = ruleFn(newInput, absStart, ctx);
|
|
6624
6897
|
if (!r.ok) continue;
|
|
6625
|
-
if (r.span.end !==
|
|
6626
|
-
if (!boundaryIsSafe(ruleFn, newInput,
|
|
6898
|
+
if (r.span.end !== absEnd + delta) continue;
|
|
6899
|
+
if (!boundaryIsSafe(ruleFn, newInput, absStart, absEnd + delta, node2.state, this._opts.build, r)) {
|
|
6627
6900
|
continue;
|
|
6628
6901
|
}
|
|
6902
|
+
const parentBase = absStart - node2.span.start;
|
|
6903
|
+
const newRel = relativizeCST(r.value, parentBase);
|
|
6629
6904
|
if (delta === 0) {
|
|
6630
|
-
const newTree2 = replaceAtPath(rebuild,
|
|
6631
|
-
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, newTree2, [], newInput);
|
|
6905
|
+
const newTree2 = replaceAtPath(rebuild, root, path, newRel);
|
|
6906
|
+
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, { rel: newTree2 }, [], newInput);
|
|
6632
6907
|
}
|
|
6633
6908
|
if (this._opts.rebuild) return reparse();
|
|
6634
|
-
const newTree =
|
|
6635
|
-
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, newTree, [], newInput);
|
|
6909
|
+
const newTree = graftRelative(root, path, newRel, delta);
|
|
6910
|
+
return new _ParseDocImpl(this._registry, this._rootRule, this._opts, { rel: newTree }, [], newInput);
|
|
6911
|
+
}
|
|
6912
|
+
if (this._opts.structuralReuse && delta !== 0 && !this._opts.rebuild) {
|
|
6913
|
+
const spliceCandidates = [...candidates, { node: root, path: [] }];
|
|
6914
|
+
for (const { node: node2, path } of spliceCandidates) {
|
|
6915
|
+
if (!this._reps.has(node2.type)) continue;
|
|
6916
|
+
const { start: cStart, end: cEnd } = absoluteSpanCST(root, path);
|
|
6917
|
+
if (!(cStart <= from && to <= cEnd)) continue;
|
|
6918
|
+
const spliced = tryListSplice(root, path, node2, cStart, newInput, from, to, delta, this._fns, this._opts.build);
|
|
6919
|
+
if (spliced) return new _ParseDocImpl(this._registry, this._rootRule, this._opts, { rel: spliced }, [], newInput);
|
|
6920
|
+
}
|
|
6636
6921
|
}
|
|
6637
6922
|
return reparse();
|
|
6638
6923
|
}
|
|
6639
6924
|
};
|
|
6640
6925
|
function parseDoc(registry, rootRule, input, opts = {}) {
|
|
6641
|
-
const
|
|
6642
|
-
if (!
|
|
6926
|
+
const entry = registry[rootRule];
|
|
6927
|
+
if (!entry) throw new Error(`No rule '${rootRule}' in registry`);
|
|
6643
6928
|
const ctx = { trackLines: false, state: opts.state, build: opts.build };
|
|
6644
|
-
const r =
|
|
6929
|
+
const r = asRuleFn(entry)(input, 0, ctx);
|
|
6645
6930
|
if (r.ok) {
|
|
6646
|
-
return new ParseDocImpl(registry, rootRule, opts, r.value, [], input);
|
|
6931
|
+
return new ParseDocImpl(registry, rootRule, opts, { abs: r.value }, [], input);
|
|
6647
6932
|
}
|
|
6648
|
-
return new ParseDocImpl(registry, rootRule, opts, null, [{ ok: false, expected: r.expected, span: r.span }], input);
|
|
6933
|
+
return new ParseDocImpl(registry, rootRule, opts, { abs: null }, [{ ok: false, expected: r.expected, span: r.span }], input);
|
|
6649
6934
|
}
|
|
6650
6935
|
|
|
6651
6936
|
// src/functional/run.ts
|
|
@@ -7014,72 +7299,6 @@ function buildOffsetIndex(root, input = "") {
|
|
|
7014
7299
|
return new OffsetIndex(collectLeafSlots(root), 0, input.length);
|
|
7015
7300
|
}
|
|
7016
7301
|
|
|
7017
|
-
// src/cst/relative-spans.ts
|
|
7018
|
-
function relativize(node2, parentBase = 0) {
|
|
7019
|
-
return {
|
|
7020
|
-
start: node2.start - parentBase,
|
|
7021
|
-
end: node2.end - parentBase,
|
|
7022
|
-
children: node2.children.map((c) => relativize(c, node2.start))
|
|
7023
|
-
};
|
|
7024
|
-
}
|
|
7025
|
-
function absolutize(node2, parentBase = 0) {
|
|
7026
|
-
const start = parentBase + node2.start;
|
|
7027
|
-
return {
|
|
7028
|
-
start,
|
|
7029
|
-
end: parentBase + node2.end,
|
|
7030
|
-
children: node2.children.map((c) => absolutize(c, start))
|
|
7031
|
-
};
|
|
7032
|
-
}
|
|
7033
|
-
function absoluteSpanAt(root, path) {
|
|
7034
|
-
let base = 0;
|
|
7035
|
-
let node2 = root;
|
|
7036
|
-
for (const idx of path) {
|
|
7037
|
-
base += node2.start;
|
|
7038
|
-
const child = node2.children[idx];
|
|
7039
|
-
if (!child) throw new RangeError(`absoluteSpanAt: no child ${idx} on path ${path.join(".")}`);
|
|
7040
|
-
node2 = child;
|
|
7041
|
-
}
|
|
7042
|
-
return { start: base + node2.start, end: base + node2.end };
|
|
7043
|
-
}
|
|
7044
|
-
function shiftAbsolute(node2, at, delta) {
|
|
7045
|
-
const s = node2.start >= at ? node2.start + delta : node2.start;
|
|
7046
|
-
const e = node2.end >= at ? node2.end + delta : node2.end;
|
|
7047
|
-
return {
|
|
7048
|
-
start: s,
|
|
7049
|
-
end: e,
|
|
7050
|
-
children: node2.children.map((c) => shiftAbsolute(c, at, delta))
|
|
7051
|
-
};
|
|
7052
|
-
}
|
|
7053
|
-
function applyEdit(root, at, delta, stats) {
|
|
7054
|
-
return editNode(root, at, delta, 0, 0, stats);
|
|
7055
|
-
}
|
|
7056
|
-
function editNode(node2, at, delta, parentBase, parentShift, stats) {
|
|
7057
|
-
const absStart = parentBase + node2.start;
|
|
7058
|
-
const absEnd = parentBase + node2.end;
|
|
7059
|
-
if (absEnd < at) return node2;
|
|
7060
|
-
const startShifts = absStart >= at;
|
|
7061
|
-
if (startShifts && parentShift === delta) return node2;
|
|
7062
|
-
if (stats) stats.allocated++;
|
|
7063
|
-
const newAbsStart = startShifts ? absStart + delta : absStart;
|
|
7064
|
-
const newAbsEnd = absEnd + delta;
|
|
7065
|
-
const newParentBase = parentBase + parentShift;
|
|
7066
|
-
const newStart = newAbsStart - newParentBase;
|
|
7067
|
-
const newEnd = newAbsEnd - newParentBase;
|
|
7068
|
-
const ownShift = newAbsStart - absStart;
|
|
7069
|
-
let changed = false;
|
|
7070
|
-
const newChildren = [];
|
|
7071
|
-
for (const c of node2.children) {
|
|
7072
|
-
const nc = editNode(c, at, delta, absStart, ownShift, stats);
|
|
7073
|
-
if (nc !== c) changed = true;
|
|
7074
|
-
newChildren.push(nc);
|
|
7075
|
-
}
|
|
7076
|
-
return {
|
|
7077
|
-
start: newStart,
|
|
7078
|
-
end: newEnd,
|
|
7079
|
-
children: changed ? newChildren : node2.children
|
|
7080
|
-
};
|
|
7081
|
-
}
|
|
7082
|
-
|
|
7083
7302
|
// src/index.ts
|
|
7084
7303
|
registerRegexAnalyzer(firstSetFromRegex);
|
|
7085
7304
|
//# sourceMappingURL=index.cjs.map
|