@lezer/common 1.0.4 → 1.1.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/index.cjs CHANGED
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- // FIXME profile adding a per-Tree TreeNode cache, validating it by
4
- // parent pointer
5
3
  /**
6
4
  The default maximum length of a `TreeBuffer` node.
7
5
  */
@@ -116,6 +114,12 @@ class MountedTree {
116
114
  this.overlay = overlay;
117
115
  this.parser = parser;
118
116
  }
117
+ /**
118
+ @internal
119
+ */
120
+ static get(tree) {
121
+ return tree && tree.props && tree.props[NodeProp.mounted.id];
122
+ }
119
123
  }
120
124
  const noProps = Object.create(null);
121
125
  /**
@@ -371,7 +375,7 @@ class Tree {
371
375
  @internal
372
376
  */
373
377
  toString() {
374
- let mounted = this.prop(NodeProp.mounted);
378
+ let mounted = MountedTree.get(this);
375
379
  if (mounted && !mounted.overlay)
376
380
  return mounted.tree.toString();
377
381
  let children = "";
@@ -443,6 +447,16 @@ class Tree {
443
447
  return node;
444
448
  }
445
449
  /**
450
+ In some situations, it can be useful to iterate through all
451
+ nodes around a position, including those in overlays that don't
452
+ directly cover the position. This method gives you an iterator
453
+ that will produce all nodes, from small to big, around the given
454
+ position.
455
+ */
456
+ resolveStack(pos, side = 0) {
457
+ return stackIterator(this, pos, side);
458
+ }
459
+ /**
446
460
  Iterate over the tree and its children, calling `enter` for any
447
461
  node that touches the `from`/`to` region (if given) before
448
462
  running over such a node's children, and `leave` (if given) when
@@ -621,22 +635,6 @@ function checkSide(side, pos, from, to) {
621
635
  case 4 /* Side.DontCare */: return true;
622
636
  }
623
637
  }
624
- function enterUnfinishedNodesBefore(node, pos) {
625
- let scan = node.childBefore(pos);
626
- while (scan) {
627
- let last = scan.lastChild;
628
- if (!last || last.to != scan.to)
629
- break;
630
- if (last.type.isError && last.from == last.to) {
631
- node = scan;
632
- scan = last.prevSibling;
633
- }
634
- else {
635
- scan = last;
636
- }
637
- }
638
- return node;
639
- }
640
638
  function resolveNode(node, pos, side, overlays) {
641
639
  var _a;
642
640
  // Move up to a node that actually holds the position, if possible
@@ -662,10 +660,48 @@ function resolveNode(node, pos, side, overlays) {
662
660
  node = inner;
663
661
  }
664
662
  }
665
- class TreeNode {
663
+ class BaseNode {
664
+ cursor(mode = 0) { return new TreeCursor(this, mode); }
665
+ getChild(type, before = null, after = null) {
666
+ let r = getChildren(this, type, before, after);
667
+ return r.length ? r[0] : null;
668
+ }
669
+ getChildren(type, before = null, after = null) {
670
+ return getChildren(this, type, before, after);
671
+ }
672
+ resolve(pos, side = 0) {
673
+ return resolveNode(this, pos, side, false);
674
+ }
675
+ resolveInner(pos, side = 0) {
676
+ return resolveNode(this, pos, side, true);
677
+ }
678
+ matchContext(context) {
679
+ return matchNodeContext(this, context);
680
+ }
681
+ enterUnfinishedNodesBefore(pos) {
682
+ let scan = this.childBefore(pos), node = this;
683
+ while (scan) {
684
+ let last = scan.lastChild;
685
+ if (!last || last.to != scan.to)
686
+ break;
687
+ if (last.type.isError && last.from == last.to) {
688
+ node = scan;
689
+ scan = last.prevSibling;
690
+ }
691
+ else {
692
+ scan = last;
693
+ }
694
+ }
695
+ return node;
696
+ }
697
+ get node() { return this; }
698
+ get next() { return this.parent; }
699
+ }
700
+ class TreeNode extends BaseNode {
666
701
  constructor(_tree, from,
667
702
  // Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
668
703
  index, _parent) {
704
+ super();
669
705
  this._tree = _tree;
670
706
  this.from = from;
671
707
  this.index = index;
@@ -689,8 +725,7 @@ class TreeNode {
689
725
  }
690
726
  else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
691
727
  let mounted;
692
- if (!(mode & exports.IterMode.IgnoreMounts) &&
693
- next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
728
+ if (!(mode & exports.IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
694
729
  return new TreeNode(mounted.tree, start, i, parent);
695
730
  let inner = new TreeNode(next, start, i, parent);
696
731
  return (mode & exports.IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
@@ -714,7 +749,7 @@ class TreeNode {
714
749
  childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
715
750
  enter(pos, side, mode = 0) {
716
751
  let mounted;
717
- if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
752
+ if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
718
753
  let rPos = pos - this.from;
719
754
  for (let { from, to } of mounted.overlay) {
720
755
  if ((side > 0 ? from <= rPos : from < rPos) &&
@@ -739,29 +774,12 @@ class TreeNode {
739
774
  get prevSibling() {
740
775
  return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
741
776
  }
742
- cursor(mode = 0) { return new TreeCursor(this, mode); }
743
777
  get tree() { return this._tree; }
744
778
  toTree() { return this._tree; }
745
- resolve(pos, side = 0) {
746
- return resolveNode(this, pos, side, false);
747
- }
748
- resolveInner(pos, side = 0) {
749
- return resolveNode(this, pos, side, true);
750
- }
751
- enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
752
- getChild(type, before = null, after = null) {
753
- let r = getChildren(this, type, before, after);
754
- return r.length ? r[0] : null;
755
- }
756
- getChildren(type, before = null, after = null) {
757
- return getChildren(this, type, before, after);
758
- }
759
779
  /**
760
780
  @internal
761
781
  */
762
782
  toString() { return this._tree.toString(); }
763
- get node() { return this; }
764
- matchContext(context) { return matchNodeContext(this, context); }
765
783
  }
766
784
  function getChildren(node, type, before, after) {
767
785
  let cur = node.cursor(), result = [];
@@ -800,11 +818,12 @@ class BufferContext {
800
818
  this.start = start;
801
819
  }
802
820
  }
803
- class BufferNode {
821
+ class BufferNode extends BaseNode {
804
822
  get name() { return this.type.name; }
805
823
  get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
806
824
  get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
807
825
  constructor(context, _parent, index) {
826
+ super();
808
827
  this.context = context;
809
828
  this._parent = _parent;
810
829
  this.index = index;
@@ -846,7 +865,6 @@ class BufferNode {
846
865
  return this.externalSibling(-1);
847
866
  return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
848
867
  }
849
- cursor(mode = 0) { return new TreeCursor(this, mode); }
850
868
  get tree() { return null; }
851
869
  toTree() {
852
870
  let children = [], positions = [];
@@ -859,26 +877,55 @@ class BufferNode {
859
877
  }
860
878
  return new Tree(this.type, children, positions, this.to - this.from);
861
879
  }
862
- resolve(pos, side = 0) {
863
- return resolveNode(this, pos, side, false);
864
- }
865
- resolveInner(pos, side = 0) {
866
- return resolveNode(this, pos, side, true);
867
- }
868
- enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
869
880
  /**
870
881
  @internal
871
882
  */
872
883
  toString() { return this.context.buffer.childString(this.index); }
873
- getChild(type, before = null, after = null) {
874
- let r = getChildren(this, type, before, after);
875
- return r.length ? r[0] : null;
884
+ }
885
+ function iterStack(heads) {
886
+ if (!heads.length)
887
+ return null;
888
+ let pick = 0, picked = heads[0];
889
+ for (let i = 1; i < heads.length; i++) {
890
+ let node = heads[i];
891
+ if (node.from > picked.from || node.to < picked.to) {
892
+ picked = node;
893
+ pick = i;
894
+ }
876
895
  }
877
- getChildren(type, before = null, after = null) {
878
- return getChildren(this, type, before, after);
896
+ let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
897
+ let newHeads = heads.slice();
898
+ if (next)
899
+ newHeads[pick] = next;
900
+ else
901
+ newHeads.splice(pick, 1);
902
+ return new StackIterator(newHeads, picked);
903
+ }
904
+ class StackIterator {
905
+ constructor(heads, node) {
906
+ this.heads = heads;
907
+ this.node = node;
879
908
  }
880
- get node() { return this; }
881
- matchContext(context) { return matchNodeContext(this, context); }
909
+ get next() { return iterStack(this.heads); }
910
+ }
911
+ function stackIterator(tree, pos, side) {
912
+ let inner = tree.resolveInner(pos, side), layers = null;
913
+ for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
914
+ if (scan.index < 0) { // This is an overlay root
915
+ let parent = scan.parent;
916
+ (layers || (layers = [inner])).push(parent.resolve(pos, side));
917
+ scan = parent;
918
+ }
919
+ else {
920
+ let mount = MountedTree.get(scan.tree);
921
+ // Relevant overlay branching off
922
+ if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
923
+ let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
924
+ (layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
925
+ }
926
+ }
927
+ }
928
+ return layers ? iterStack(layers) : inner;
882
929
  }
883
930
  /**
884
931
  A tree cursor object focuses on a given node in a syntax tree, and
@@ -937,6 +984,9 @@ class TreeCursor {
937
984
  this.to = start + buffer.buffer[index + 2];
938
985
  return true;
939
986
  }
987
+ /**
988
+ @internal
989
+ */
940
990
  yield(node) {
941
991
  if (!node)
942
992
  return false;
@@ -1202,7 +1252,7 @@ function buildTree(data) {
1202
1252
  let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
1203
1253
  let types = nodeSet.types;
1204
1254
  let contextHash = 0, lookAhead = 0;
1205
- function takeNode(parentStart, minPos, children, positions, inRepeat) {
1255
+ function takeNode(parentStart, minPos, children, positions, inRepeat, depth) {
1206
1256
  let { id, start, end, size } = cursor;
1207
1257
  let lookAheadAtStart = lookAhead;
1208
1258
  while (size < 0) {
@@ -1251,8 +1301,11 @@ function buildTree(data) {
1251
1301
  }
1252
1302
  cursor.next();
1253
1303
  }
1304
+ else if (depth > 2500 /* CutOff.Depth */) {
1305
+ takeFlatNode(start, endPos, localChildren, localPositions);
1306
+ }
1254
1307
  else {
1255
- takeNode(start, endPos, localChildren, localPositions, localInRepeat);
1308
+ takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
1256
1309
  }
1257
1310
  }
1258
1311
  if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
@@ -1270,6 +1323,38 @@ function buildTree(data) {
1270
1323
  children.push(node);
1271
1324
  positions.push(startPos);
1272
1325
  }
1326
+ function takeFlatNode(parentStart, minPos, children, positions) {
1327
+ let nodes = []; // Temporary, inverted array of leaf nodes found, with absolute positions
1328
+ let nodeCount = 0, stopAt = -1;
1329
+ while (cursor.pos > minPos) {
1330
+ let { id, start, end, size } = cursor;
1331
+ if (size > 4) { // Not a leaf
1332
+ cursor.next();
1333
+ }
1334
+ else if (stopAt > -1 && start < stopAt) {
1335
+ break;
1336
+ }
1337
+ else {
1338
+ if (stopAt < 0)
1339
+ stopAt = end - maxBufferLength;
1340
+ nodes.push(id, start, end);
1341
+ nodeCount++;
1342
+ cursor.next();
1343
+ }
1344
+ }
1345
+ if (nodeCount) {
1346
+ let buffer = new Uint16Array(nodeCount * 4);
1347
+ let start = nodes[nodes.length - 2];
1348
+ for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
1349
+ buffer[j++] = nodes[i];
1350
+ buffer[j++] = nodes[i + 1] - start;
1351
+ buffer[j++] = nodes[i + 2] - start;
1352
+ buffer[j++] = j;
1353
+ }
1354
+ children.push(new TreeBuffer(buffer, nodes[2] - start, nodeSet));
1355
+ positions.push(start - parentStart);
1356
+ }
1357
+ }
1273
1358
  function makeBalanced(type) {
1274
1359
  return (children, positions, length) => {
1275
1360
  let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
@@ -1380,7 +1465,7 @@ function buildTree(data) {
1380
1465
  }
1381
1466
  let children = [], positions = [];
1382
1467
  while (cursor.pos > 0)
1383
- takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
1468
+ takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
1384
1469
  let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
1385
1470
  return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
1386
1471
  }
@@ -1661,16 +1746,18 @@ function parseMixed(nest) {
1661
1746
  return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
1662
1747
  }
1663
1748
  class InnerParse {
1664
- constructor(parser, parse, overlay, target, ranges) {
1749
+ constructor(parser, parse, overlay, target, from) {
1665
1750
  this.parser = parser;
1666
1751
  this.parse = parse;
1667
1752
  this.overlay = overlay;
1668
1753
  this.target = target;
1669
- this.ranges = ranges;
1670
- if (!ranges.length || ranges.some(r => r.from >= r.to))
1671
- throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
1754
+ this.from = from;
1672
1755
  }
1673
1756
  }
1757
+ function checkRanges(ranges) {
1758
+ if (!ranges.length || ranges.some(r => r.from >= r.to))
1759
+ throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
1760
+ }
1674
1761
  class ActiveOverlay {
1675
1762
  constructor(parser, predicate, mounts, index, start, target, prev) {
1676
1763
  this.parser = parser;
@@ -1733,7 +1820,7 @@ class MixedParse {
1733
1820
  return 0;
1734
1821
  let pos = this.input.length;
1735
1822
  for (let i = this.innerDone; i < this.inner.length; i++) {
1736
- if (this.inner[i].ranges[0].from < pos)
1823
+ if (this.inner[i].from < pos)
1737
1824
  pos = Math.min(pos, this.inner[i].parse.parsedPos);
1738
1825
  }
1739
1826
  return pos;
@@ -1751,9 +1838,12 @@ class MixedParse {
1751
1838
  let overlay = null;
1752
1839
  let covered = null;
1753
1840
  let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), exports.IterMode.IncludeAnonymous | exports.IterMode.IgnoreMounts);
1754
- scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
1841
+ scan: for (let nest, isCovered;;) {
1755
1842
  let enter = true, range;
1756
- if (fragmentCursor.hasNode(cursor)) {
1843
+ if (this.stoppedAt != null && cursor.from >= this.stoppedAt) {
1844
+ enter = false;
1845
+ }
1846
+ else if (fragmentCursor.hasNode(cursor)) {
1757
1847
  if (overlay) {
1758
1848
  let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay);
1759
1849
  if (match)
@@ -1768,7 +1858,8 @@ class MixedParse {
1768
1858
  else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) {
1769
1859
  enter = isCovered != 2 /* Cover.Full */;
1770
1860
  }
1771
- else if (!cursor.type.isAnonymous && cursor.from < cursor.to && (nest = this.nest(cursor, this.input))) {
1861
+ else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) &&
1862
+ (cursor.from < cursor.to || !nest.overlay)) {
1772
1863
  if (!cursor.tree)
1773
1864
  materialize(cursor);
1774
1865
  let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser);
@@ -1776,9 +1867,13 @@ class MixedParse {
1776
1867
  overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay);
1777
1868
  }
1778
1869
  else {
1779
- let ranges = punchRanges(this.ranges, nest.overlay || [new Range(cursor.from, cursor.to)]);
1870
+ let ranges = punchRanges(this.ranges, nest.overlay ||
1871
+ (cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : []));
1780
1872
  if (ranges.length)
1781
- this.inner.push(new InnerParse(nest.parser, nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges));
1873
+ checkRanges(ranges);
1874
+ if (ranges.length || !nest.overlay)
1875
+ this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges)
1876
+ : nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from));
1782
1877
  if (!nest.overlay)
1783
1878
  enter = false;
1784
1879
  else if (ranges.length)
@@ -1805,8 +1900,10 @@ class MixedParse {
1805
1900
  break scan;
1806
1901
  if (overlay && !--overlay.depth) {
1807
1902
  let ranges = punchRanges(this.ranges, overlay.ranges);
1808
- if (ranges.length)
1809
- this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges));
1903
+ if (ranges.length) {
1904
+ checkRanges(ranges);
1905
+ this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from));
1906
+ }
1810
1907
  overlay = overlay.prev;
1811
1908
  }
1812
1909
  if (covered && !--covered.depth)
@@ -1840,11 +1937,11 @@ function sliceBuf(buf, startI, endI, nodes, positions, off) {
1840
1937
  // parse that was ran via the mix parser, and thus aren't shared with
1841
1938
  // any other code, making violations of the immutability safe.
1842
1939
  function materialize(cursor) {
1843
- let { node } = cursor, depth = 0;
1940
+ let { node } = cursor, stack = [];
1844
1941
  // Scan up to the nearest tree
1845
1942
  do {
1943
+ stack.push(cursor.index);
1846
1944
  cursor.parent();
1847
- depth++;
1848
1945
  } while (!cursor.tree);
1849
1946
  // Find the index of the buffer in that tree
1850
1947
  let i = 0, base = cursor.tree, off = 0;
@@ -1853,26 +1950,29 @@ function materialize(cursor) {
1853
1950
  if (off <= node.from && off + base.children[i].length >= node.to)
1854
1951
  break;
1855
1952
  }
1856
- let buf = base.children[i], b = buf.buffer;
1953
+ let buf = base.children[i], b = buf.buffer, newStack = [i];
1857
1954
  // Split a level in the buffer, putting the nodes before and after
1858
1955
  // the child that contains `node` into new buffers.
1859
- function split(startI, endI, type, innerOffset, length) {
1860
- let i = startI;
1861
- while (b[i + 2] + off <= node.from)
1862
- i = b[i + 3];
1956
+ function split(startI, endI, type, innerOffset, length, stackPos) {
1957
+ let targetI = stack[stackPos];
1863
1958
  let children = [], positions = [];
1864
- sliceBuf(buf, startI, i, children, positions, innerOffset);
1865
- let from = b[i + 1], to = b[i + 2];
1866
- let isTarget = from + off == node.from && to + off == node.to && b[i] == node.type.id;
1867
- children.push(isTarget ? node.toTree() : split(i + 4, b[i + 3], buf.set.types[b[i]], from, to - from));
1959
+ sliceBuf(buf, startI, targetI, children, positions, innerOffset);
1960
+ let from = b[targetI + 1], to = b[targetI + 2];
1961
+ newStack.push(children.length);
1962
+ let child = stackPos
1963
+ ? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1)
1964
+ : node.toTree();
1965
+ children.push(child);
1868
1966
  positions.push(from - innerOffset);
1869
- sliceBuf(buf, b[i + 3], endI, children, positions, innerOffset);
1967
+ sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset);
1870
1968
  return new Tree(type, children, positions, length);
1871
1969
  }
1872
- base.children[i] = split(0, b.length, NodeType.none, 0, buf.length);
1970
+ base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1);
1873
1971
  // Move the cursor back to the target node
1874
- for (let d = 0; d <= depth; d++)
1875
- cursor.childAfter(node.from);
1972
+ for (let index of newStack) {
1973
+ let tree = cursor.tree.children[index], pos = cursor.tree.positions[index];
1974
+ cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree));
1975
+ }
1876
1976
  }
1877
1977
  class StructureCursor {
1878
1978
  constructor(root, offset) {
package/dist/index.d.cts CHANGED
@@ -615,6 +615,14 @@ declare class Tree {
615
615
  */
616
616
  resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
617
617
  /**
618
+ In some situations, it can be useful to iterate through all
619
+ nodes around a position, including those in overlays that don't
620
+ directly cover the position. This method gives you an iterator
621
+ that will produce all nodes, from small to big, around the given
622
+ position.
623
+ */
624
+ resolveStack(pos: number, side?: -1 | 0 | 1): NodeIterator;
625
+ /**
618
626
  Iterate over the tree and its children, calling `enter` for any
619
627
  node that touches the `from`/`to` region (if given) before
620
628
  running over such a node's children, and `leave` (if given) when
@@ -656,6 +664,13 @@ declare class Tree {
656
664
  */
657
665
  static build(data: BuildData): Tree;
658
666
  }
667
+ /**
668
+ Represents a sequence of nodes.
669
+ */
670
+ type NodeIterator = {
671
+ node: SyntaxNode;
672
+ next: NodeIterator | null;
673
+ };
659
674
  type BuildData = {
660
675
  /**
661
676
  The buffer or buffer cursor to read the node data from.
@@ -827,7 +842,9 @@ interface SyntaxNodeRef {
827
842
  */
828
843
  readonly node: SyntaxNode;
829
844
  /**
830
- Test whether the node matches a given context.
845
+ Test whether the node matches a given context—a sequence of
846
+ direct parent nodes. Empty strings in the context array act as
847
+ wildcards, other strings must match the ancestor node's name.
831
848
  */
832
849
  matchContext(context: readonly string[]): boolean;
833
850
  }
@@ -921,12 +938,6 @@ interface SyntaxNode extends SyntaxNodeRef {
921
938
  matching children, not just the first.
922
939
  */
923
940
  getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
924
- /**
925
- Test whether the node matches a given context—a sequence of
926
- direct parent nodes. Empty strings in the context array act as
927
- wildcards, other strings must match the ancestor node's name.
928
- */
929
- matchContext(context: readonly string[]): boolean;
930
941
  }
931
942
  /**
932
943
  A tree cursor object focuses on a given node in a syntax tree, and
@@ -953,7 +964,6 @@ declare class TreeCursor implements SyntaxNodeRef {
953
964
  private bufferNode;
954
965
  private yieldNode;
955
966
  private yieldBuf;
956
- private yield;
957
967
  /**
958
968
  Move the cursor to this node's first child. When this returns
959
969
  false, the node has no child, and the cursor has not been moved.
@@ -1112,4 +1122,4 @@ tree.
1112
1122
  */
1113
1123
  declare function parseMixed(nest: (node: SyntaxNodeRef, input: Input) => NestedParse | null): ParseWrapper;
1114
1124
 
1115
- export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
1125
+ export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeIterator, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
package/dist/index.d.ts CHANGED
@@ -615,6 +615,14 @@ declare class Tree {
615
615
  */
616
616
  resolveInner(pos: number, side?: -1 | 0 | 1): SyntaxNode;
617
617
  /**
618
+ In some situations, it can be useful to iterate through all
619
+ nodes around a position, including those in overlays that don't
620
+ directly cover the position. This method gives you an iterator
621
+ that will produce all nodes, from small to big, around the given
622
+ position.
623
+ */
624
+ resolveStack(pos: number, side?: -1 | 0 | 1): NodeIterator;
625
+ /**
618
626
  Iterate over the tree and its children, calling `enter` for any
619
627
  node that touches the `from`/`to` region (if given) before
620
628
  running over such a node's children, and `leave` (if given) when
@@ -656,6 +664,13 @@ declare class Tree {
656
664
  */
657
665
  static build(data: BuildData): Tree;
658
666
  }
667
+ /**
668
+ Represents a sequence of nodes.
669
+ */
670
+ type NodeIterator = {
671
+ node: SyntaxNode;
672
+ next: NodeIterator | null;
673
+ };
659
674
  type BuildData = {
660
675
  /**
661
676
  The buffer or buffer cursor to read the node data from.
@@ -827,7 +842,9 @@ interface SyntaxNodeRef {
827
842
  */
828
843
  readonly node: SyntaxNode;
829
844
  /**
830
- Test whether the node matches a given context.
845
+ Test whether the node matches a given context—a sequence of
846
+ direct parent nodes. Empty strings in the context array act as
847
+ wildcards, other strings must match the ancestor node's name.
831
848
  */
832
849
  matchContext(context: readonly string[]): boolean;
833
850
  }
@@ -921,12 +938,6 @@ interface SyntaxNode extends SyntaxNodeRef {
921
938
  matching children, not just the first.
922
939
  */
923
940
  getChildren(type: string | number, before?: string | number | null, after?: string | number | null): SyntaxNode[];
924
- /**
925
- Test whether the node matches a given context—a sequence of
926
- direct parent nodes. Empty strings in the context array act as
927
- wildcards, other strings must match the ancestor node's name.
928
- */
929
- matchContext(context: readonly string[]): boolean;
930
941
  }
931
942
  /**
932
943
  A tree cursor object focuses on a given node in a syntax tree, and
@@ -953,7 +964,6 @@ declare class TreeCursor implements SyntaxNodeRef {
953
964
  private bufferNode;
954
965
  private yieldNode;
955
966
  private yieldBuf;
956
- private yield;
957
967
  /**
958
968
  Move the cursor to this node's first child. When this returns
959
969
  false, the node has no child, and the cursor has not been moved.
@@ -1112,4 +1122,4 @@ tree.
1112
1122
  */
1113
1123
  declare function parseMixed(nest: (node: SyntaxNodeRef, input: Input) => NestedParse | null): ParseWrapper;
1114
1124
 
1115
- export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
1125
+ export { BufferCursor, ChangedRange, DefaultBufferLength, Input, IterMode, MountedTree, NestedParse, NodeIterator, NodeProp, NodePropSource, NodeSet, NodeType, NodeWeakMap, ParseWrapper, Parser, PartialParse, SyntaxNode, SyntaxNodeRef, Tree, TreeBuffer, TreeCursor, TreeFragment, parseMixed };
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- // FIXME profile adding a per-Tree TreeNode cache, validating it by
2
- // parent pointer
3
1
  /**
4
2
  The default maximum length of a `TreeBuffer` node.
5
3
  */
@@ -114,6 +112,12 @@ class MountedTree {
114
112
  this.overlay = overlay;
115
113
  this.parser = parser;
116
114
  }
115
+ /**
116
+ @internal
117
+ */
118
+ static get(tree) {
119
+ return tree && tree.props && tree.props[NodeProp.mounted.id];
120
+ }
117
121
  }
118
122
  const noProps = Object.create(null);
119
123
  /**
@@ -369,7 +373,7 @@ class Tree {
369
373
  @internal
370
374
  */
371
375
  toString() {
372
- let mounted = this.prop(NodeProp.mounted);
376
+ let mounted = MountedTree.get(this);
373
377
  if (mounted && !mounted.overlay)
374
378
  return mounted.tree.toString();
375
379
  let children = "";
@@ -441,6 +445,16 @@ class Tree {
441
445
  return node;
442
446
  }
443
447
  /**
448
+ In some situations, it can be useful to iterate through all
449
+ nodes around a position, including those in overlays that don't
450
+ directly cover the position. This method gives you an iterator
451
+ that will produce all nodes, from small to big, around the given
452
+ position.
453
+ */
454
+ resolveStack(pos, side = 0) {
455
+ return stackIterator(this, pos, side);
456
+ }
457
+ /**
444
458
  Iterate over the tree and its children, calling `enter` for any
445
459
  node that touches the `from`/`to` region (if given) before
446
460
  running over such a node's children, and `leave` (if given) when
@@ -619,22 +633,6 @@ function checkSide(side, pos, from, to) {
619
633
  case 4 /* Side.DontCare */: return true;
620
634
  }
621
635
  }
622
- function enterUnfinishedNodesBefore(node, pos) {
623
- let scan = node.childBefore(pos);
624
- while (scan) {
625
- let last = scan.lastChild;
626
- if (!last || last.to != scan.to)
627
- break;
628
- if (last.type.isError && last.from == last.to) {
629
- node = scan;
630
- scan = last.prevSibling;
631
- }
632
- else {
633
- scan = last;
634
- }
635
- }
636
- return node;
637
- }
638
636
  function resolveNode(node, pos, side, overlays) {
639
637
  var _a;
640
638
  // Move up to a node that actually holds the position, if possible
@@ -660,10 +658,48 @@ function resolveNode(node, pos, side, overlays) {
660
658
  node = inner;
661
659
  }
662
660
  }
663
- class TreeNode {
661
+ class BaseNode {
662
+ cursor(mode = 0) { return new TreeCursor(this, mode); }
663
+ getChild(type, before = null, after = null) {
664
+ let r = getChildren(this, type, before, after);
665
+ return r.length ? r[0] : null;
666
+ }
667
+ getChildren(type, before = null, after = null) {
668
+ return getChildren(this, type, before, after);
669
+ }
670
+ resolve(pos, side = 0) {
671
+ return resolveNode(this, pos, side, false);
672
+ }
673
+ resolveInner(pos, side = 0) {
674
+ return resolveNode(this, pos, side, true);
675
+ }
676
+ matchContext(context) {
677
+ return matchNodeContext(this, context);
678
+ }
679
+ enterUnfinishedNodesBefore(pos) {
680
+ let scan = this.childBefore(pos), node = this;
681
+ while (scan) {
682
+ let last = scan.lastChild;
683
+ if (!last || last.to != scan.to)
684
+ break;
685
+ if (last.type.isError && last.from == last.to) {
686
+ node = scan;
687
+ scan = last.prevSibling;
688
+ }
689
+ else {
690
+ scan = last;
691
+ }
692
+ }
693
+ return node;
694
+ }
695
+ get node() { return this; }
696
+ get next() { return this.parent; }
697
+ }
698
+ class TreeNode extends BaseNode {
664
699
  constructor(_tree, from,
665
700
  // Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
666
701
  index, _parent) {
702
+ super();
667
703
  this._tree = _tree;
668
704
  this.from = from;
669
705
  this.index = index;
@@ -687,8 +723,7 @@ class TreeNode {
687
723
  }
688
724
  else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
689
725
  let mounted;
690
- if (!(mode & IterMode.IgnoreMounts) &&
691
- next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
726
+ if (!(mode & IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
692
727
  return new TreeNode(mounted.tree, start, i, parent);
693
728
  let inner = new TreeNode(next, start, i, parent);
694
729
  return (mode & IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
@@ -712,7 +747,7 @@ class TreeNode {
712
747
  childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
713
748
  enter(pos, side, mode = 0) {
714
749
  let mounted;
715
- if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
750
+ if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
716
751
  let rPos = pos - this.from;
717
752
  for (let { from, to } of mounted.overlay) {
718
753
  if ((side > 0 ? from <= rPos : from < rPos) &&
@@ -737,29 +772,12 @@ class TreeNode {
737
772
  get prevSibling() {
738
773
  return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
739
774
  }
740
- cursor(mode = 0) { return new TreeCursor(this, mode); }
741
775
  get tree() { return this._tree; }
742
776
  toTree() { return this._tree; }
743
- resolve(pos, side = 0) {
744
- return resolveNode(this, pos, side, false);
745
- }
746
- resolveInner(pos, side = 0) {
747
- return resolveNode(this, pos, side, true);
748
- }
749
- enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
750
- getChild(type, before = null, after = null) {
751
- let r = getChildren(this, type, before, after);
752
- return r.length ? r[0] : null;
753
- }
754
- getChildren(type, before = null, after = null) {
755
- return getChildren(this, type, before, after);
756
- }
757
777
  /**
758
778
  @internal
759
779
  */
760
780
  toString() { return this._tree.toString(); }
761
- get node() { return this; }
762
- matchContext(context) { return matchNodeContext(this, context); }
763
781
  }
764
782
  function getChildren(node, type, before, after) {
765
783
  let cur = node.cursor(), result = [];
@@ -798,11 +816,12 @@ class BufferContext {
798
816
  this.start = start;
799
817
  }
800
818
  }
801
- class BufferNode {
819
+ class BufferNode extends BaseNode {
802
820
  get name() { return this.type.name; }
803
821
  get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
804
822
  get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
805
823
  constructor(context, _parent, index) {
824
+ super();
806
825
  this.context = context;
807
826
  this._parent = _parent;
808
827
  this.index = index;
@@ -844,7 +863,6 @@ class BufferNode {
844
863
  return this.externalSibling(-1);
845
864
  return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
846
865
  }
847
- cursor(mode = 0) { return new TreeCursor(this, mode); }
848
866
  get tree() { return null; }
849
867
  toTree() {
850
868
  let children = [], positions = [];
@@ -857,26 +875,55 @@ class BufferNode {
857
875
  }
858
876
  return new Tree(this.type, children, positions, this.to - this.from);
859
877
  }
860
- resolve(pos, side = 0) {
861
- return resolveNode(this, pos, side, false);
862
- }
863
- resolveInner(pos, side = 0) {
864
- return resolveNode(this, pos, side, true);
865
- }
866
- enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
867
878
  /**
868
879
  @internal
869
880
  */
870
881
  toString() { return this.context.buffer.childString(this.index); }
871
- getChild(type, before = null, after = null) {
872
- let r = getChildren(this, type, before, after);
873
- return r.length ? r[0] : null;
882
+ }
883
+ function iterStack(heads) {
884
+ if (!heads.length)
885
+ return null;
886
+ let pick = 0, picked = heads[0];
887
+ for (let i = 1; i < heads.length; i++) {
888
+ let node = heads[i];
889
+ if (node.from > picked.from || node.to < picked.to) {
890
+ picked = node;
891
+ pick = i;
892
+ }
874
893
  }
875
- getChildren(type, before = null, after = null) {
876
- return getChildren(this, type, before, after);
894
+ let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
895
+ let newHeads = heads.slice();
896
+ if (next)
897
+ newHeads[pick] = next;
898
+ else
899
+ newHeads.splice(pick, 1);
900
+ return new StackIterator(newHeads, picked);
901
+ }
902
+ class StackIterator {
903
+ constructor(heads, node) {
904
+ this.heads = heads;
905
+ this.node = node;
877
906
  }
878
- get node() { return this; }
879
- matchContext(context) { return matchNodeContext(this, context); }
907
+ get next() { return iterStack(this.heads); }
908
+ }
909
+ function stackIterator(tree, pos, side) {
910
+ let inner = tree.resolveInner(pos, side), layers = null;
911
+ for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
912
+ if (scan.index < 0) { // This is an overlay root
913
+ let parent = scan.parent;
914
+ (layers || (layers = [inner])).push(parent.resolve(pos, side));
915
+ scan = parent;
916
+ }
917
+ else {
918
+ let mount = MountedTree.get(scan.tree);
919
+ // Relevant overlay branching off
920
+ if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
921
+ let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
922
+ (layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
923
+ }
924
+ }
925
+ }
926
+ return layers ? iterStack(layers) : inner;
880
927
  }
881
928
  /**
882
929
  A tree cursor object focuses on a given node in a syntax tree, and
@@ -935,6 +982,9 @@ class TreeCursor {
935
982
  this.to = start + buffer.buffer[index + 2];
936
983
  return true;
937
984
  }
985
+ /**
986
+ @internal
987
+ */
938
988
  yield(node) {
939
989
  if (!node)
940
990
  return false;
@@ -1200,7 +1250,7 @@ function buildTree(data) {
1200
1250
  let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
1201
1251
  let types = nodeSet.types;
1202
1252
  let contextHash = 0, lookAhead = 0;
1203
- function takeNode(parentStart, minPos, children, positions, inRepeat) {
1253
+ function takeNode(parentStart, minPos, children, positions, inRepeat, depth) {
1204
1254
  let { id, start, end, size } = cursor;
1205
1255
  let lookAheadAtStart = lookAhead;
1206
1256
  while (size < 0) {
@@ -1249,8 +1299,11 @@ function buildTree(data) {
1249
1299
  }
1250
1300
  cursor.next();
1251
1301
  }
1302
+ else if (depth > 2500 /* CutOff.Depth */) {
1303
+ takeFlatNode(start, endPos, localChildren, localPositions);
1304
+ }
1252
1305
  else {
1253
- takeNode(start, endPos, localChildren, localPositions, localInRepeat);
1306
+ takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
1254
1307
  }
1255
1308
  }
1256
1309
  if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
@@ -1268,6 +1321,38 @@ function buildTree(data) {
1268
1321
  children.push(node);
1269
1322
  positions.push(startPos);
1270
1323
  }
1324
+ function takeFlatNode(parentStart, minPos, children, positions) {
1325
+ let nodes = []; // Temporary, inverted array of leaf nodes found, with absolute positions
1326
+ let nodeCount = 0, stopAt = -1;
1327
+ while (cursor.pos > minPos) {
1328
+ let { id, start, end, size } = cursor;
1329
+ if (size > 4) { // Not a leaf
1330
+ cursor.next();
1331
+ }
1332
+ else if (stopAt > -1 && start < stopAt) {
1333
+ break;
1334
+ }
1335
+ else {
1336
+ if (stopAt < 0)
1337
+ stopAt = end - maxBufferLength;
1338
+ nodes.push(id, start, end);
1339
+ nodeCount++;
1340
+ cursor.next();
1341
+ }
1342
+ }
1343
+ if (nodeCount) {
1344
+ let buffer = new Uint16Array(nodeCount * 4);
1345
+ let start = nodes[nodes.length - 2];
1346
+ for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
1347
+ buffer[j++] = nodes[i];
1348
+ buffer[j++] = nodes[i + 1] - start;
1349
+ buffer[j++] = nodes[i + 2] - start;
1350
+ buffer[j++] = j;
1351
+ }
1352
+ children.push(new TreeBuffer(buffer, nodes[2] - start, nodeSet));
1353
+ positions.push(start - parentStart);
1354
+ }
1355
+ }
1271
1356
  function makeBalanced(type) {
1272
1357
  return (children, positions, length) => {
1273
1358
  let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
@@ -1378,7 +1463,7 @@ function buildTree(data) {
1378
1463
  }
1379
1464
  let children = [], positions = [];
1380
1465
  while (cursor.pos > 0)
1381
- takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
1466
+ takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
1382
1467
  let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
1383
1468
  return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
1384
1469
  }
@@ -1659,16 +1744,18 @@ function parseMixed(nest) {
1659
1744
  return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
1660
1745
  }
1661
1746
  class InnerParse {
1662
- constructor(parser, parse, overlay, target, ranges) {
1747
+ constructor(parser, parse, overlay, target, from) {
1663
1748
  this.parser = parser;
1664
1749
  this.parse = parse;
1665
1750
  this.overlay = overlay;
1666
1751
  this.target = target;
1667
- this.ranges = ranges;
1668
- if (!ranges.length || ranges.some(r => r.from >= r.to))
1669
- throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
1752
+ this.from = from;
1670
1753
  }
1671
1754
  }
1755
+ function checkRanges(ranges) {
1756
+ if (!ranges.length || ranges.some(r => r.from >= r.to))
1757
+ throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
1758
+ }
1672
1759
  class ActiveOverlay {
1673
1760
  constructor(parser, predicate, mounts, index, start, target, prev) {
1674
1761
  this.parser = parser;
@@ -1731,7 +1818,7 @@ class MixedParse {
1731
1818
  return 0;
1732
1819
  let pos = this.input.length;
1733
1820
  for (let i = this.innerDone; i < this.inner.length; i++) {
1734
- if (this.inner[i].ranges[0].from < pos)
1821
+ if (this.inner[i].from < pos)
1735
1822
  pos = Math.min(pos, this.inner[i].parse.parsedPos);
1736
1823
  }
1737
1824
  return pos;
@@ -1749,9 +1836,12 @@ class MixedParse {
1749
1836
  let overlay = null;
1750
1837
  let covered = null;
1751
1838
  let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
1752
- scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
1839
+ scan: for (let nest, isCovered;;) {
1753
1840
  let enter = true, range;
1754
- if (fragmentCursor.hasNode(cursor)) {
1841
+ if (this.stoppedAt != null && cursor.from >= this.stoppedAt) {
1842
+ enter = false;
1843
+ }
1844
+ else if (fragmentCursor.hasNode(cursor)) {
1755
1845
  if (overlay) {
1756
1846
  let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay);
1757
1847
  if (match)
@@ -1766,7 +1856,8 @@ class MixedParse {
1766
1856
  else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) {
1767
1857
  enter = isCovered != 2 /* Cover.Full */;
1768
1858
  }
1769
- else if (!cursor.type.isAnonymous && cursor.from < cursor.to && (nest = this.nest(cursor, this.input))) {
1859
+ else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) &&
1860
+ (cursor.from < cursor.to || !nest.overlay)) {
1770
1861
  if (!cursor.tree)
1771
1862
  materialize(cursor);
1772
1863
  let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser);
@@ -1774,9 +1865,13 @@ class MixedParse {
1774
1865
  overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay);
1775
1866
  }
1776
1867
  else {
1777
- let ranges = punchRanges(this.ranges, nest.overlay || [new Range(cursor.from, cursor.to)]);
1868
+ let ranges = punchRanges(this.ranges, nest.overlay ||
1869
+ (cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : []));
1778
1870
  if (ranges.length)
1779
- this.inner.push(new InnerParse(nest.parser, nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges));
1871
+ checkRanges(ranges);
1872
+ if (ranges.length || !nest.overlay)
1873
+ this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges)
1874
+ : nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from));
1780
1875
  if (!nest.overlay)
1781
1876
  enter = false;
1782
1877
  else if (ranges.length)
@@ -1803,8 +1898,10 @@ class MixedParse {
1803
1898
  break scan;
1804
1899
  if (overlay && !--overlay.depth) {
1805
1900
  let ranges = punchRanges(this.ranges, overlay.ranges);
1806
- if (ranges.length)
1807
- this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges));
1901
+ if (ranges.length) {
1902
+ checkRanges(ranges);
1903
+ this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from));
1904
+ }
1808
1905
  overlay = overlay.prev;
1809
1906
  }
1810
1907
  if (covered && !--covered.depth)
@@ -1838,11 +1935,11 @@ function sliceBuf(buf, startI, endI, nodes, positions, off) {
1838
1935
  // parse that was ran via the mix parser, and thus aren't shared with
1839
1936
  // any other code, making violations of the immutability safe.
1840
1937
  function materialize(cursor) {
1841
- let { node } = cursor, depth = 0;
1938
+ let { node } = cursor, stack = [];
1842
1939
  // Scan up to the nearest tree
1843
1940
  do {
1941
+ stack.push(cursor.index);
1844
1942
  cursor.parent();
1845
- depth++;
1846
1943
  } while (!cursor.tree);
1847
1944
  // Find the index of the buffer in that tree
1848
1945
  let i = 0, base = cursor.tree, off = 0;
@@ -1851,26 +1948,29 @@ function materialize(cursor) {
1851
1948
  if (off <= node.from && off + base.children[i].length >= node.to)
1852
1949
  break;
1853
1950
  }
1854
- let buf = base.children[i], b = buf.buffer;
1951
+ let buf = base.children[i], b = buf.buffer, newStack = [i];
1855
1952
  // Split a level in the buffer, putting the nodes before and after
1856
1953
  // the child that contains `node` into new buffers.
1857
- function split(startI, endI, type, innerOffset, length) {
1858
- let i = startI;
1859
- while (b[i + 2] + off <= node.from)
1860
- i = b[i + 3];
1954
+ function split(startI, endI, type, innerOffset, length, stackPos) {
1955
+ let targetI = stack[stackPos];
1861
1956
  let children = [], positions = [];
1862
- sliceBuf(buf, startI, i, children, positions, innerOffset);
1863
- let from = b[i + 1], to = b[i + 2];
1864
- let isTarget = from + off == node.from && to + off == node.to && b[i] == node.type.id;
1865
- children.push(isTarget ? node.toTree() : split(i + 4, b[i + 3], buf.set.types[b[i]], from, to - from));
1957
+ sliceBuf(buf, startI, targetI, children, positions, innerOffset);
1958
+ let from = b[targetI + 1], to = b[targetI + 2];
1959
+ newStack.push(children.length);
1960
+ let child = stackPos
1961
+ ? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1)
1962
+ : node.toTree();
1963
+ children.push(child);
1866
1964
  positions.push(from - innerOffset);
1867
- sliceBuf(buf, b[i + 3], endI, children, positions, innerOffset);
1965
+ sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset);
1868
1966
  return new Tree(type, children, positions, length);
1869
1967
  }
1870
- base.children[i] = split(0, b.length, NodeType.none, 0, buf.length);
1968
+ base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1);
1871
1969
  // Move the cursor back to the target node
1872
- for (let d = 0; d <= depth; d++)
1873
- cursor.childAfter(node.from);
1970
+ for (let index of newStack) {
1971
+ let tree = cursor.tree.children[index], pos = cursor.tree.positions[index];
1972
+ cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree));
1973
+ }
1874
1974
  }
1875
1975
  class StructureCursor {
1876
1976
  constructor(root, offset) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lezer/common",
3
- "version": "1.0.4",
3
+ "version": "1.1.1",
4
4
  "description": "Syntax tree data structure and parser interfaces for the lezer parser",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "module",