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/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
- if (child.span.start <= pos && pos < child.span.end) {
6494
- const inner = findContaining(child, pos, [...path, i]);
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 shiftSpans(child, delta) {
6666
+ function shiftRelStart(child, delta) {
6522
6667
  const c = child;
6523
- const span = { start: c.span.start + delta, end: c.span.end + delta };
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 graftAndShift(root, path, newNode, delta) {
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 : graftAndShift(child, rest, newNode, delta);
6677
+ return rest.length === 0 ? newNode : graftRelative(child, rest, newNode, delta);
6537
6678
  }
6538
- return shiftSpans(child, delta);
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
- tree;
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, tree, errors, input) {
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.tree = tree;
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
- if (!this.tree) return reparse();
6877
+ const root = this.tree;
6878
+ if (!root) return reparse();
6606
6879
  const delta = replacement.length - (to - from);
6607
- const found = findContaining(this.tree, from);
6608
- if (!found) return reparse();
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
- if (node2.span.end - node2.span.start > this.input.length * REENTRY_MAX_SPAN_FRACTION) break;
6619
- const ruleFn = this._registry[node2.type];
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 (!(node2.span.start <= from && to <= node2.span.end)) continue;
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, node2.span.start, ctx);
6896
+ const r = ruleFn(newInput, absStart, ctx);
6624
6897
  if (!r.ok) continue;
6625
- if (r.span.end !== node2.span.end + delta) continue;
6626
- if (!boundaryIsSafe(ruleFn, newInput, node2.span.start, node2.span.end + delta, node2.state, this._opts.build, r)) {
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, this.tree, path, r.value);
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 = graftAndShift(this.tree, path, r.value, delta);
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 ruleFn = registry[rootRule];
6642
- if (!ruleFn) throw new Error(`No rule '${rootRule}' in registry`);
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 = ruleFn(input, 0, ctx);
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