@lezer/common 0.15.9 → 0.15.10

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/tree.cjs CHANGED
@@ -2,46 +2,39 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /// The default maximum length of a `TreeBuffer` node.
5
+ // FIXME profile adding a per-Tree TreeNode cache, validating it by
6
+ // parent pointer
7
+ /// The default maximum length of a `TreeBuffer` node (1024).
6
8
  const DefaultBufferLength = 1024;
7
9
  let nextPropID = 0;
8
- const CachedNode = new WeakMap();
9
- /// Each [node type](#tree.NodeType) can have metadata associated with
10
- /// it in props. Instances of this class represent prop names.
10
+ class Range {
11
+ constructor(from, to) {
12
+ this.from = from;
13
+ this.to = to;
14
+ }
15
+ }
16
+ /// Each [node type](#common.NodeType) or [individual tree](#common.Tree)
17
+ /// can have metadata associated with it in props. Instances of this
18
+ /// class represent prop names.
11
19
  class NodeProp {
12
- /// Create a new node prop type. You can optionally pass a
13
- /// `deserialize` function.
14
- constructor({ deserialize } = {}) {
20
+ /// Create a new node prop type.
21
+ constructor(config = {}) {
15
22
  this.id = nextPropID++;
16
- this.deserialize = deserialize || (() => {
23
+ this.perNode = !!config.perNode;
24
+ this.deserialize = config.deserialize || (() => {
17
25
  throw new Error("This node type doesn't define a deserialize function");
18
26
  });
19
27
  }
20
- /// Create a string-valued node prop whose deserialize function is
21
- /// the identity function.
22
- static string() { return new NodeProp({ deserialize: str => str }); }
23
- /// Create a number-valued node prop whose deserialize function is
24
- /// just `Number`.
25
- static number() { return new NodeProp({ deserialize: Number }); }
26
- /// Creates a boolean-valued node prop whose deserialize function
27
- /// returns true for any input.
28
- static flag() { return new NodeProp({ deserialize: () => true }); }
29
- /// Store a value for this prop in the given object. This can be
30
- /// useful when building up a prop object to pass to the
31
- /// [`NodeType`](#tree.NodeType) constructor. Returns its first
32
- /// argument.
33
- set(propObj, value) {
34
- propObj[this.id] = value;
35
- return propObj;
36
- }
37
28
  /// This is meant to be used with
38
- /// [`NodeSet.extend`](#tree.NodeSet.extend) or
39
- /// [`Parser.withProps`](#lezer.Parser.withProps) to compute prop
40
- /// values for each node type in the set. Takes a [match
41
- /// object](#tree.NodeType^match) or function that returns undefined
29
+ /// [`NodeSet.extend`](#common.NodeSet.extend) or
30
+ /// [`LRParser.configure`](#lr.ParserConfig.props) to compute
31
+ /// prop values for each node type in the set. Takes a [match
32
+ /// object](#common.NodeType^match) or function that returns undefined
42
33
  /// if the node type doesn't get this prop, and the prop's value if
43
34
  /// it does.
44
35
  add(match) {
36
+ if (this.perNode)
37
+ throw new RangeError("Can't add per-node props to node types");
45
38
  if (typeof match != "function")
46
39
  match = NodeType.match(match);
47
40
  return (type) => {
@@ -55,7 +48,7 @@ class NodeProp {
55
48
  /// space-separated string when declaring this prop in a grammar)
56
49
  /// for the node types of closing delimiters that match it.
57
50
  NodeProp.closedBy = new NodeProp({ deserialize: str => str.split(" ") });
58
- /// The inverse of [`closedBy`](#tree.NodeProp^closedBy). This is
51
+ /// The inverse of [`closedBy`](#common.NodeProp^closedBy). This is
59
52
  /// attached to closing delimiters, holding an array of node names
60
53
  /// of types of matching opening delimiters.
61
54
  NodeProp.openedBy = new NodeProp({ deserialize: str => str.split(" ") });
@@ -63,6 +56,41 @@ NodeProp.openedBy = new NodeProp({ deserialize: str => str.split(" ") });
63
56
  /// types that represent an expression could be tagged with an
64
57
  /// `"Expression"` group).
65
58
  NodeProp.group = new NodeProp({ deserialize: str => str.split(" ") });
59
+ /// The hash of the [context](#lr.ContextTracker.constructor)
60
+ /// that the node was parsed in, if any. Used to limit reuse of
61
+ /// contextual nodes.
62
+ NodeProp.contextHash = new NodeProp({ perNode: true });
63
+ /// The distance beyond the end of the node that the tokenizer
64
+ /// looked ahead for any of the tokens inside the node. (The LR
65
+ /// parser only stores this when it is larger than 25, for
66
+ /// efficiency reasons.)
67
+ NodeProp.lookAhead = new NodeProp({ perNode: true });
68
+ /// This per-node prop is used to replace a given node, or part of a
69
+ /// node, with another tree. This is useful to include trees from
70
+ /// different languages.
71
+ NodeProp.mounted = new NodeProp({ perNode: true });
72
+ /// A mounted tree, which can be [stored](#common.NodeProp^mounted) on
73
+ /// a tree node to indicate that parts of its content are
74
+ /// represented by another tree.
75
+ class MountedTree {
76
+ constructor(
77
+ /// The inner tree.
78
+ tree,
79
+ /// If this is null, this tree replaces the entire node (it will
80
+ /// be included in the regular iteration instead of its host
81
+ /// node). If not, only the given ranges are considered to be
82
+ /// covered by this tree. This is used for trees that are mixed in
83
+ /// a way that isn't strictly hierarchical. Such mounted trees are
84
+ /// only entered by [`resolveInner`](#common.Tree.resolveInner)
85
+ /// and [`enter`](#common.SyntaxNode.enter).
86
+ overlay,
87
+ /// The parser used to create this subtree.
88
+ parser) {
89
+ this.tree = tree;
90
+ this.overlay = overlay;
91
+ this.parser = parser;
92
+ }
93
+ }
66
94
  const noProps = Object.create(null);
67
95
  /// Each node in a syntax tree has a node type associated with it.
68
96
  class NodeType {
@@ -94,8 +122,11 @@ class NodeType {
94
122
  for (let src of spec.props) {
95
123
  if (!Array.isArray(src))
96
124
  src = src(type);
97
- if (src)
98
- src[0].set(props, src[1]);
125
+ if (src) {
126
+ if (src[0].perNode)
127
+ throw new RangeError("Can't store a per-node prop on a node type");
128
+ props[src[0].id] = src[1];
129
+ }
99
130
  }
100
131
  return type;
101
132
  }
@@ -112,7 +143,7 @@ class NodeType {
112
143
  /// named node, for example because it is used to cache repetition.
113
144
  get isAnonymous() { return (this.flags & 8 /* Anonymous */) > 0; }
114
145
  /// Returns true when this node's name or one of its
115
- /// [groups](#tree.NodeProp^group) matches the given string.
146
+ /// [groups](#common.NodeProp^group) matches the given string.
116
147
  is(name) {
117
148
  if (typeof name == 'string') {
118
149
  if (this.name == name)
@@ -124,8 +155,8 @@ class NodeType {
124
155
  }
125
156
  /// Create a function from node types to arbitrary values by
126
157
  /// specifying an object whose property names are node or
127
- /// [group](#tree.NodeProp^group) names. Often useful with
128
- /// [`NodeProp.add`](#tree.NodeProp.add). You can put multiple
158
+ /// [group](#common.NodeProp^group) names. Often useful with
159
+ /// [`NodeProp.add`](#common.NodeProp.add). You can put multiple
129
160
  /// names, separated by spaces, in a single property name to map
130
161
  /// multiple node names to a single value.
131
162
  static match(map) {
@@ -146,12 +177,11 @@ class NodeType {
146
177
  NodeType.none = new NodeType("", Object.create(null), 0, 8 /* Anonymous */);
147
178
  /// A node set holds a collection of node types. It is used to
148
179
  /// compactly represent trees by storing their type ids, rather than a
149
- /// full pointer to the type object, in a number array. Each parser
150
- /// [has](#lezer.Parser.nodeSet) a node set, and [tree
151
- /// buffers](#tree.TreeBuffer) can only store collections of nodes
152
- /// from the same set. A set can have a maximum of 2**16 (65536)
153
- /// node types in it, so that the ids fit into 16-bit typed array
154
- /// slots.
180
+ /// full pointer to the type object, in a numeric array. Each parser
181
+ /// [has](#lr.LRParser.nodeSet) a node set, and [tree
182
+ /// buffers](#common.TreeBuffer) can only store collections of nodes
183
+ /// from the same set. A set can have a maximum of 2**16 (65536) node
184
+ /// types in it, so that the ids fit into 16-bit typed array slots.
155
185
  class NodeSet {
156
186
  /// Create a set with the given types. The `id` property of each
157
187
  /// type should correspond to its position within the array.
@@ -165,7 +195,7 @@ class NodeSet {
165
195
  }
166
196
  /// Create a copy of this set with some node properties added. The
167
197
  /// arguments to this method should be created with
168
- /// [`NodeProp.add`](#tree.NodeProp.add).
198
+ /// [`NodeProp.add`](#common.NodeProp.add).
169
199
  extend(...props) {
170
200
  let newTypes = [];
171
201
  for (let type of this.types) {
@@ -175,7 +205,7 @@ class NodeSet {
175
205
  if (add) {
176
206
  if (!newProps)
177
207
  newProps = Object.assign({}, type.props);
178
- add[0].set(newProps, add[1]);
208
+ newProps[add[0].id] = add[1];
179
209
  }
180
210
  }
181
211
  newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type);
@@ -183,6 +213,7 @@ class NodeSet {
183
213
  return new NodeSet(newTypes);
184
214
  }
185
215
  }
216
+ const CachedNode = new WeakMap();
186
217
  /// A piece of syntax tree. There are two ways to approach these
187
218
  /// trees: the way they are actually stored in memory, and the
188
219
  /// convenient way.
@@ -193,36 +224,56 @@ class NodeSet {
193
224
  ///
194
225
  /// However, when you want to actually work with tree nodes, this
195
226
  /// representation is very awkward, so most client code will want to
196
- /// use the `TreeCursor` interface instead, which provides a view on
197
- /// some part of this data structure, and can be used to move around
198
- /// to adjacent nodes.
227
+ /// use the [`TreeCursor`](#common.TreeCursor) or
228
+ /// [`SyntaxNode`](#common.SyntaxNode) interface instead, which provides
229
+ /// a view on some part of this data structure, and can be used to
230
+ /// move around to adjacent nodes.
199
231
  class Tree {
200
- /// Construct a new tree. You usually want to go through
201
- /// [`Tree.build`](#tree.Tree^build) instead.
202
- constructor(type,
203
- /// The tree's child nodes. Children small enough to fit in a
204
- /// `TreeBuffer will be represented as such, other children can be
205
- /// further `Tree` instances with their own internal structure.
232
+ /// Construct a new tree. See also [`Tree.build`](#common.Tree^build).
233
+ constructor(
234
+ /// The type of the top node.
235
+ type,
236
+ /// This node's child nodes.
206
237
  children,
207
238
  /// The positions (offsets relative to the start of this tree) of
208
239
  /// the children.
209
240
  positions,
210
241
  /// The total length of this tree
211
- length) {
242
+ length,
243
+ /// Per-node [node props](#common.NodeProp) to associate with this node.
244
+ props) {
212
245
  this.type = type;
213
246
  this.children = children;
214
247
  this.positions = positions;
215
248
  this.length = length;
249
+ /// @internal
250
+ this.props = null;
251
+ if (props && props.length) {
252
+ this.props = Object.create(null);
253
+ for (let [prop, value] of props)
254
+ this.props[typeof prop == "number" ? prop : prop.id] = value;
255
+ }
216
256
  }
217
257
  /// @internal
218
258
  toString() {
219
- let children = this.children.map(c => c.toString()).join();
259
+ let mounted = this.prop(NodeProp.mounted);
260
+ if (mounted && !mounted.overlay)
261
+ return mounted.tree.toString();
262
+ let children = "";
263
+ for (let ch of this.children) {
264
+ let str = ch.toString();
265
+ if (str) {
266
+ if (children)
267
+ children += ",";
268
+ children += str;
269
+ }
270
+ }
220
271
  return !this.type.name ? children :
221
272
  (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
222
273
  (children.length ? "(" + children + ")" : "");
223
274
  }
224
- /// Get a [tree cursor](#tree.TreeCursor) rooted at this tree. When
225
- /// `pos` is given, the cursor is [moved](#tree.TreeCursor.moveTo)
275
+ /// Get a [tree cursor](#common.TreeCursor) rooted at this tree. When
276
+ /// `pos` is given, the cursor is [moved](#common.TreeCursor.moveTo)
226
277
  /// to the given position and side.
227
278
  cursor(pos, side = 0) {
228
279
  let scope = (pos != null && CachedNode.get(this)) || this.topNode;
@@ -233,18 +284,19 @@ class Tree {
233
284
  }
234
285
  return cursor;
235
286
  }
236
- /// Get a [tree cursor](#tree.TreeCursor) that, unlike regular
237
- /// cursors, doesn't skip [anonymous](#tree.NodeType.isAnonymous)
238
- /// nodes.
287
+ /// Get a [tree cursor](#common.TreeCursor) that, unlike regular
288
+ /// cursors, doesn't skip through
289
+ /// [anonymous](#common.NodeType.isAnonymous) nodes and doesn't
290
+ /// automatically enter mounted nodes.
239
291
  fullCursor() {
240
- return new TreeCursor(this.topNode, true);
292
+ return new TreeCursor(this.topNode, 1 /* Full */);
241
293
  }
242
- /// Get a [syntax node](#tree.SyntaxNode) object for the top of the
294
+ /// Get a [syntax node](#common.SyntaxNode) object for the top of the
243
295
  /// tree.
244
296
  get topNode() {
245
297
  return new TreeNode(this, 0, 0, null);
246
298
  }
247
- /// Get the [syntax node](#tree.SyntaxNode) at the given position.
299
+ /// Get the [syntax node](#common.SyntaxNode) at the given position.
248
300
  /// If `side` is -1, this will move into nodes that end at the
249
301
  /// position. If 1, it'll move into nodes that start at the
250
302
  /// position. With 0, it'll only enter nodes that cover the position
@@ -252,16 +304,30 @@ class Tree {
252
304
  resolve(pos, side = 0) {
253
305
  return this.cursor(pos, side).node;
254
306
  }
307
+ /// Like [`resolve`](#common.Tree.resolve), but will enter
308
+ /// [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
309
+ /// pointing into the innermost overlaid tree at the given position
310
+ /// (with parent links going through all parent structure, including
311
+ /// the host trees).
312
+ resolveInner(pos, side = 0) {
313
+ let result = this.topNode;
314
+ for (;;) {
315
+ let inner = result.enter(pos, side);
316
+ if (!inner)
317
+ return result;
318
+ result = inner;
319
+ }
320
+ }
255
321
  /// Iterate over the tree and its children, calling `enter` for any
256
322
  /// node that touches the `from`/`to` region (if given) before
257
323
  /// running over such a node's children, and `leave` (if given) when
258
- /// leaving the node. When `enter` returns `false`, the given node
259
- /// will not have its children iterated over (or `leave` called).
324
+ /// leaving the node. When `enter` returns `false`, that node will
325
+ /// not have its children iterated over (or `leave` called).
260
326
  iterate(spec) {
261
327
  let { enter, leave, from = 0, to = this.length } = spec;
262
- for (let c = this.cursor();;) {
328
+ for (let c = this.cursor(), get = () => c.node;;) {
263
329
  let mustLeave = false;
264
- if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c.type, c.from, c.to) !== false)) {
330
+ if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c.type, c.from, c.to, get) !== false)) {
265
331
  if (c.firstChild())
266
332
  continue;
267
333
  if (!c.type.isAnonymous)
@@ -269,7 +335,7 @@ class Tree {
269
335
  }
270
336
  for (;;) {
271
337
  if (mustLeave && leave)
272
- leave(c.type, c.from, c.to);
338
+ leave(c.type, c.from, c.to, get);
273
339
  mustLeave = c.type.isAnonymous;
274
340
  if (c.nextSibling())
275
341
  break;
@@ -279,10 +345,27 @@ class Tree {
279
345
  }
280
346
  }
281
347
  }
282
- /// Balance the direct children of this tree.
283
- balance(maxBufferLength = DefaultBufferLength) {
284
- return this.children.length <= BalanceBranchFactor ? this
285
- : balanceRange(this.type, NodeType.none, this.children, this.positions, 0, this.children.length, 0, maxBufferLength, this.length, 0);
348
+ /// Get the value of the given [node prop](#common.NodeProp) for this
349
+ /// node. Works with both per-node and per-type props.
350
+ prop(prop) {
351
+ return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : undefined;
352
+ }
353
+ /// Returns the node's [per-node props](#common.NodeProp.perNode) in a
354
+ /// format that can be passed to the [`Tree`](#common.Tree)
355
+ /// constructor.
356
+ get propValues() {
357
+ let result = [];
358
+ if (this.props)
359
+ for (let id in this.props)
360
+ result.push([+id, this.props[id]]);
361
+ return result;
362
+ }
363
+ /// Balance the direct children of this tree, producing a copy of
364
+ /// which may have children grouped into subtrees with type
365
+ /// [`NodeType.none`](#common.NodeType^none).
366
+ balance(config = {}) {
367
+ return this.children.length <= 8 /* BranchFactor */ ? this :
368
+ balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new Tree(NodeType.none, children, positions, length)));
286
369
  }
287
370
  /// Build a tree from a postfix-ordered buffer of node information,
288
371
  /// or a cursor over such a buffer.
@@ -290,35 +373,39 @@ class Tree {
290
373
  }
291
374
  /// The empty tree
292
375
  Tree.empty = new Tree(NodeType.none, [], [], 0);
293
- // For trees that need a context hash attached, we're using this
294
- // kludge which assigns an extra property directly after
295
- // initialization (creating a single new object shape).
296
- function withHash(tree, hash) {
297
- if (hash)
298
- tree.contextHash = hash;
299
- return tree;
376
+ class FlatBufferCursor {
377
+ constructor(buffer, index) {
378
+ this.buffer = buffer;
379
+ this.index = index;
380
+ }
381
+ get id() { return this.buffer[this.index - 4]; }
382
+ get start() { return this.buffer[this.index - 3]; }
383
+ get end() { return this.buffer[this.index - 2]; }
384
+ get size() { return this.buffer[this.index - 1]; }
385
+ get pos() { return this.index; }
386
+ next() { this.index -= 4; }
387
+ fork() { return new FlatBufferCursor(this.buffer, this.index); }
300
388
  }
301
389
  /// Tree buffers contain (type, start, end, endIndex) quads for each
302
390
  /// node. In such a buffer, nodes are stored in prefix order (parents
303
391
  /// before children, with the endIndex of the parent indicating which
304
392
  /// children belong to it)
305
393
  class TreeBuffer {
306
- /// Create a tree buffer @internal
394
+ /// Create a tree buffer.
307
395
  constructor(
308
- /// @internal
396
+ /// The buffer's content.
309
397
  buffer,
310
398
  /// The total length of the group of nodes in the buffer.
311
399
  length,
312
- /// @internal
313
- set,
314
- /// An optional repeat node type associated with the buffer.
315
- type = NodeType.none) {
400
+ /// The node set used in this buffer.
401
+ set) {
316
402
  this.buffer = buffer;
317
403
  this.length = length;
318
404
  this.set = set;
319
- this.type = type;
320
405
  }
321
406
  /// @internal
407
+ get type() { return NodeType.none; }
408
+ /// @internal
322
409
  toString() {
323
410
  let result = [];
324
411
  for (let index = 0; index < this.buffer.length;) {
@@ -344,25 +431,10 @@ class TreeBuffer {
344
431
  return result + "(" + children.join(",") + ")";
345
432
  }
346
433
  /// @internal
347
- findChild(startIndex, endIndex, dir, after) {
434
+ findChild(startIndex, endIndex, dir, pos, side) {
348
435
  let { buffer } = this, pick = -1;
349
436
  for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
350
- if (after != -100000000 /* None */) {
351
- let start = buffer[i + 1], end = buffer[i + 2];
352
- if (dir > 0) {
353
- if (end > after)
354
- pick = i;
355
- if (end > after)
356
- break;
357
- }
358
- else {
359
- if (start < after)
360
- pick = i;
361
- if (end >= after)
362
- break;
363
- }
364
- }
365
- else {
437
+ if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) {
366
438
  pick = i;
367
439
  if (dir > 0)
368
440
  break;
@@ -370,45 +442,107 @@ class TreeBuffer {
370
442
  }
371
443
  return pick;
372
444
  }
445
+ /// @internal
446
+ slice(startI, endI, from, to) {
447
+ let b = this.buffer;
448
+ let copy = new Uint16Array(endI - startI);
449
+ for (let i = startI, j = 0; i < endI;) {
450
+ copy[j++] = b[i++];
451
+ copy[j++] = b[i++] - from;
452
+ copy[j++] = b[i++] - from;
453
+ copy[j++] = b[i++] - startI;
454
+ }
455
+ return new TreeBuffer(copy, to - from, this.set);
456
+ }
457
+ }
458
+ function checkSide(side, pos, from, to) {
459
+ switch (side) {
460
+ case -2 /* Before */: return from < pos;
461
+ case -1 /* AtOrBefore */: return to >= pos && from < pos;
462
+ case 0 /* Around */: return from < pos && to > pos;
463
+ case 1 /* AtOrAfter */: return from <= pos && to > pos;
464
+ case 2 /* After */: return to > pos;
465
+ case 4 /* DontCare */: return true;
466
+ }
467
+ }
468
+ function enterUnfinishedNodesBefore(node, pos) {
469
+ let scan = node.childBefore(pos);
470
+ while (scan) {
471
+ let last = scan.lastChild;
472
+ if (!last || last.to != scan.to)
473
+ break;
474
+ if (last.type.isError && last.from == last.to) {
475
+ node = scan;
476
+ scan = last.prevSibling;
477
+ }
478
+ else {
479
+ scan = last;
480
+ }
481
+ }
482
+ return node;
373
483
  }
374
484
  class TreeNode {
375
- constructor(node, from, index, _parent) {
485
+ constructor(node, _from,
486
+ // Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
487
+ index, _parent) {
376
488
  this.node = node;
377
- this.from = from;
489
+ this._from = _from;
378
490
  this.index = index;
379
491
  this._parent = _parent;
380
492
  }
381
493
  get type() { return this.node.type; }
382
494
  get name() { return this.node.type.name; }
383
- get to() { return this.from + this.node.length; }
384
- nextChild(i, dir, after, full = false) {
495
+ get from() { return this._from; }
496
+ get to() { return this._from + this.node.length; }
497
+ nextChild(i, dir, pos, side, mode = 0) {
385
498
  for (let parent = this;;) {
386
499
  for (let { children, positions } = parent.node, e = dir > 0 ? children.length : -1; i != e; i += dir) {
387
- let next = children[i], start = positions[i] + parent.from;
388
- if (after != -100000000 /* None */ && (dir < 0 ? start >= after : start + next.length <= after))
500
+ let next = children[i], start = positions[i] + parent._from;
501
+ if (!checkSide(side, pos, start, start + next.length))
389
502
  continue;
390
503
  if (next instanceof TreeBuffer) {
391
- let index = next.findChild(0, next.buffer.length, dir, after == -100000000 /* None */ ? -100000000 /* None */ : after - start);
504
+ if (mode & 2 /* NoEnterBuffer */)
505
+ continue;
506
+ let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
392
507
  if (index > -1)
393
508
  return new BufferNode(new BufferContext(parent, next, i, start), null, index);
394
509
  }
395
- else if (full || (!next.type.isAnonymous || hasChild(next))) {
510
+ else if ((mode & 1 /* Full */) || (!next.type.isAnonymous || hasChild(next))) {
511
+ let mounted;
512
+ if (!(mode & 1 /* Full */) && next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
513
+ return new TreeNode(mounted.tree, start, i, parent);
396
514
  let inner = new TreeNode(next, start, i, parent);
397
- return full || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, after);
515
+ return (mode & 1 /* Full */) || !inner.type.isAnonymous ? inner
516
+ : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
398
517
  }
399
518
  }
400
- if (full || !parent.type.isAnonymous)
519
+ if ((mode & 1 /* Full */) || !parent.type.isAnonymous)
401
520
  return null;
402
- i = parent.index + dir;
521
+ if (parent.index >= 0)
522
+ i = parent.index + dir;
523
+ else
524
+ i = dir < 0 ? -1 : parent._parent.node.children.length;
403
525
  parent = parent._parent;
404
526
  if (!parent)
405
527
  return null;
406
528
  }
407
529
  }
408
- get firstChild() { return this.nextChild(0, 1, -100000000 /* None */); }
409
- get lastChild() { return this.nextChild(this.node.children.length - 1, -1, -100000000 /* None */); }
410
- childAfter(pos) { return this.nextChild(0, 1, pos); }
411
- childBefore(pos) { return this.nextChild(this.node.children.length - 1, -1, pos); }
530
+ get firstChild() { return this.nextChild(0, 1, 0, 4 /* DontCare */); }
531
+ get lastChild() { return this.nextChild(this.node.children.length - 1, -1, 0, 4 /* DontCare */); }
532
+ childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* After */); }
533
+ childBefore(pos) { return this.nextChild(this.node.children.length - 1, -1, pos, -2 /* Before */); }
534
+ enter(pos, side, overlays = true, buffers = true) {
535
+ let mounted;
536
+ if (overlays && (mounted = this.node.prop(NodeProp.mounted)) && mounted.overlay) {
537
+ let rPos = pos - this.from;
538
+ for (let { from, to } of mounted.overlay) {
539
+ if ((side > 0 ? from <= rPos : from < rPos) &&
540
+ (side < 0 ? to >= rPos : to > rPos))
541
+ return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
542
+ }
543
+ }
544
+ return this.nextChild(0, 1, pos, side, buffers ? 0 : 2 /* NoEnterBuffer */);
545
+ }
412
546
  nextSignificantParent() {
413
547
  let val = this;
414
548
  while (val.type.isAnonymous && val._parent)
@@ -419,15 +553,18 @@ class TreeNode {
419
553
  return this._parent ? this._parent.nextSignificantParent() : null;
420
554
  }
421
555
  get nextSibling() {
422
- return this._parent ? this._parent.nextChild(this.index + 1, 1, -1) : null;
556
+ return this._parent && this.index >= 0 ? this._parent.nextChild(this.index + 1, 1, 0, 4 /* DontCare */) : null;
423
557
  }
424
558
  get prevSibling() {
425
- return this._parent ? this._parent.nextChild(this.index - 1, -1, -1) : null;
559
+ return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* DontCare */) : null;
426
560
  }
427
561
  get cursor() { return new TreeCursor(this); }
562
+ get tree() { return this.node; }
563
+ toTree() { return this.node; }
428
564
  resolve(pos, side = 0) {
429
565
  return this.cursor.moveTo(pos, side).node;
430
566
  }
567
+ enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
431
568
  getChild(type, before = null, after = null) {
432
569
  let r = getChildren(this, type, before, after);
433
570
  return r.length ? r[0] : null;
@@ -473,20 +610,27 @@ class BufferNode {
473
610
  get name() { return this.type.name; }
474
611
  get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
475
612
  get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
476
- child(dir, after) {
613
+ child(dir, pos, side) {
614
+ let { buffer } = this.context;
615
+ let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side);
616
+ return index < 0 ? null : new BufferNode(this.context, this, index);
617
+ }
618
+ get firstChild() { return this.child(1, 0, 4 /* DontCare */); }
619
+ get lastChild() { return this.child(-1, 0, 4 /* DontCare */); }
620
+ childAfter(pos) { return this.child(1, pos, 2 /* After */); }
621
+ childBefore(pos) { return this.child(-1, pos, -2 /* Before */); }
622
+ enter(pos, side, overlays, buffers = true) {
623
+ if (!buffers)
624
+ return null;
477
625
  let { buffer } = this.context;
478
- let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, after == -100000000 /* None */ ? -100000000 /* None */ : after - this.context.start);
626
+ let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
479
627
  return index < 0 ? null : new BufferNode(this.context, this, index);
480
628
  }
481
- get firstChild() { return this.child(1, -100000000 /* None */); }
482
- get lastChild() { return this.child(-1, -100000000 /* None */); }
483
- childAfter(pos) { return this.child(1, pos); }
484
- childBefore(pos) { return this.child(-1, pos); }
485
629
  get parent() {
486
630
  return this._parent || this.context.parent.nextSignificantParent();
487
631
  }
488
632
  externalSibling(dir) {
489
- return this._parent ? null : this.context.parent.nextChild(this.context.index + dir, dir, -1);
633
+ return this._parent ? null : this.context.parent.nextChild(this.context.index + dir, dir, 0, 4 /* DontCare */);
490
634
  }
491
635
  get nextSibling() {
492
636
  let { buffer } = this.context;
@@ -500,12 +644,25 @@ class BufferNode {
500
644
  let parentStart = this._parent ? this._parent.index + 4 : 0;
501
645
  if (this.index == parentStart)
502
646
  return this.externalSibling(-1);
503
- return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, -100000000 /* None */));
647
+ return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
504
648
  }
505
649
  get cursor() { return new TreeCursor(this); }
650
+ get tree() { return null; }
651
+ toTree() {
652
+ let children = [], positions = [];
653
+ let { buffer } = this.context;
654
+ let startI = this.index + 4, endI = buffer.buffer[this.index + 3];
655
+ if (endI > startI) {
656
+ let from = buffer.buffer[this.index + 1], to = buffer.buffer[this.index + 2];
657
+ children.push(buffer.slice(startI, endI, from, to));
658
+ positions.push(0);
659
+ }
660
+ return new Tree(this.type, children, positions, this.to - this.from);
661
+ }
506
662
  resolve(pos, side = 0) {
507
663
  return this.cursor.moveTo(pos, side).node;
508
664
  }
665
+ enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
509
666
  /// @internal
510
667
  toString() { return this.context.buffer.childString(this.index); }
511
668
  getChild(type, before = null, after = null) {
@@ -520,8 +677,10 @@ class BufferNode {
520
677
  /// allows you to move to adjacent nodes.
521
678
  class TreeCursor {
522
679
  /// @internal
523
- constructor(node, full = false) {
524
- this.full = full;
680
+ constructor(node,
681
+ /// @internal
682
+ mode = 0) {
683
+ this.mode = mode;
525
684
  this.buffer = null;
526
685
  this.stack = [];
527
686
  this.index = 0;
@@ -572,11 +731,11 @@ class TreeCursor {
572
731
  return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString();
573
732
  }
574
733
  /// @internal
575
- enter(dir, after) {
734
+ enterChild(dir, pos, side) {
576
735
  if (!this.buffer)
577
- return this.yield(this._tree.nextChild(dir < 0 ? this._tree.node.children.length - 1 : 0, dir, after, this.full));
736
+ return this.yield(this._tree.nextChild(dir < 0 ? this._tree.node.children.length - 1 : 0, dir, pos, side, this.mode));
578
737
  let { buffer } = this.buffer;
579
- let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, after == -100000000 /* None */ ? -100000000 /* None */ : after - this.buffer.start);
738
+ let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
580
739
  if (index < 0)
581
740
  return false;
582
741
  this.stack.push(this.index);
@@ -584,20 +743,30 @@ class TreeCursor {
584
743
  }
585
744
  /// Move the cursor to this node's first child. When this returns
586
745
  /// false, the node has no child, and the cursor has not been moved.
587
- firstChild() { return this.enter(1, -100000000 /* None */); }
746
+ firstChild() { return this.enterChild(1, 0, 4 /* DontCare */); }
588
747
  /// Move the cursor to this node's last child.
589
- lastChild() { return this.enter(-1, -100000000 /* None */); }
590
- /// Move the cursor to the first child that starts at or after `pos`.
591
- childAfter(pos) { return this.enter(1, pos); }
592
- /// Move to the last child that ends at or before `pos`.
593
- childBefore(pos) { return this.enter(-1, pos); }
594
- /// Move the node's parent node, if this isn't the top node.
748
+ lastChild() { return this.enterChild(-1, 0, 4 /* DontCare */); }
749
+ /// Move the cursor to the first child that ends after `pos`.
750
+ childAfter(pos) { return this.enterChild(1, pos, 2 /* After */); }
751
+ /// Move to the last child that starts before `pos`.
752
+ childBefore(pos) { return this.enterChild(-1, pos, -2 /* Before */); }
753
+ /// Move the cursor to the child around `pos`. If side is -1 the
754
+ /// child may end at that position, when 1 it may start there. This
755
+ /// will also enter [overlaid](#common.MountedTree.overlay)
756
+ /// [mounted](#common.NodeProp^mounted) trees unless `overlays` is
757
+ /// set to false.
758
+ enter(pos, side, overlays = true, buffers = true) {
759
+ if (!this.buffer)
760
+ return this.yield(this._tree.enter(pos, side, overlays && !(this.mode & 1 /* Full */), buffers));
761
+ return buffers ? this.enterChild(1, pos, side) : false;
762
+ }
763
+ /// Move to the node's parent node, if this isn't the top node.
595
764
  parent() {
596
765
  if (!this.buffer)
597
- return this.yieldNode(this.full ? this._tree._parent : this._tree.parent);
766
+ return this.yieldNode((this.mode & 1 /* Full */) ? this._tree._parent : this._tree.parent);
598
767
  if (this.stack.length)
599
768
  return this.yieldBuf(this.stack.pop());
600
- let parent = this.full ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
769
+ let parent = (this.mode & 1 /* Full */) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
601
770
  this.buffer = null;
602
771
  return this.yieldNode(parent);
603
772
  }
@@ -605,19 +774,20 @@ class TreeCursor {
605
774
  sibling(dir) {
606
775
  if (!this.buffer)
607
776
  return !this._tree._parent ? false
608
- : this.yield(this._tree._parent.nextChild(this._tree.index + dir, dir, -100000000 /* None */, this.full));
777
+ : this.yield(this._tree.index < 0 ? null
778
+ : this._tree._parent.nextChild(this._tree.index + dir, dir, 0, 4 /* DontCare */, this.mode));
609
779
  let { buffer } = this.buffer, d = this.stack.length - 1;
610
780
  if (dir < 0) {
611
781
  let parentStart = d < 0 ? 0 : this.stack[d] + 4;
612
782
  if (this.index != parentStart)
613
- return this.yieldBuf(buffer.findChild(parentStart, this.index, -1, -100000000 /* None */));
783
+ return this.yieldBuf(buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
614
784
  }
615
785
  else {
616
786
  let after = buffer.buffer[this.index + 3];
617
787
  if (after < (d < 0 ? buffer.buffer.length : buffer.buffer[this.stack[d] + 3]))
618
788
  return this.yieldBuf(after);
619
789
  }
620
- return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, -100000000 /* None */, this.full)) : false;
790
+ return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4 /* DontCare */, this.mode)) : false;
621
791
  }
622
792
  /// Move to this node's next sibling, if any.
623
793
  nextSibling() { return this.sibling(1); }
@@ -641,16 +811,17 @@ class TreeCursor {
641
811
  ({ index, _parent: parent } = this._tree);
642
812
  }
643
813
  for (; parent; { index, _parent: parent } = parent) {
644
- for (let i = index + dir, e = dir < 0 ? -1 : parent.node.children.length; i != e; i += dir) {
645
- let child = parent.node.children[i];
646
- if (this.full || !child.type.isAnonymous || child instanceof TreeBuffer || hasChild(child))
647
- return false;
648
- }
814
+ if (index > -1)
815
+ for (let i = index + dir, e = dir < 0 ? -1 : parent.node.children.length; i != e; i += dir) {
816
+ let child = parent.node.children[i];
817
+ if ((this.mode & 1 /* Full */) || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child))
818
+ return false;
819
+ }
649
820
  }
650
821
  return true;
651
822
  }
652
- move(dir) {
653
- if (this.enter(dir, -100000000 /* None */))
823
+ move(dir, enter) {
824
+ if (enter && this.enterChild(dir, 0, 4 /* DontCare */))
654
825
  return true;
655
826
  for (;;) {
656
827
  if (this.sibling(dir))
@@ -662,14 +833,14 @@ class TreeCursor {
662
833
  /// Move to the next node in a
663
834
  /// [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_(NLR))
664
835
  /// traversal, going from a node to its first child or, if the
665
- /// current node is empty, its next sibling or the next sibling of
666
- /// the first parent node that has one.
667
- next() { return this.move(1); }
836
+ /// current node is empty or `enter` is false, its next sibling or
837
+ /// the next sibling of the first parent node that has one.
838
+ next(enter = true) { return this.move(1, enter); }
668
839
  /// Move to the next node in a last-to-first pre-order traveral. A
669
- /// node is followed by ist last child or, if it has none, its
840
+ /// node is followed by its last child or, if it has none, its
670
841
  /// previous sibling or the previous sibling of the first parent
671
842
  /// node that has one.
672
- prev() { return this.move(-1); }
843
+ prev(enter = true) { return this.move(-1, enter); }
673
844
  /// Move the cursor to the innermost node that covers `pos`. If
674
845
  /// `side` is -1, it will enter nodes that end at `pos`. If it is 1,
675
846
  /// it will enter nodes that start at `pos`.
@@ -681,19 +852,10 @@ class TreeCursor {
681
852
  if (!this.parent())
682
853
  break;
683
854
  // Then scan down into child nodes as far as possible
684
- for (;;) {
685
- if (side < 0 ? !this.childBefore(pos) : !this.childAfter(pos))
686
- break;
687
- if (this.from == this.to ||
688
- (side < 1 ? this.from >= pos : this.from > pos) ||
689
- (side > -1 ? this.to <= pos : this.to < pos)) {
690
- this.parent();
691
- break;
692
- }
693
- }
855
+ while (this.enterChild(1, pos, side)) { }
694
856
  return this;
695
857
  }
696
- /// Get a [syntax node](#tree.SyntaxNode) at the cursor's current
858
+ /// Get a [syntax node](#common.SyntaxNode) at the cursor's current
697
859
  /// position.
698
860
  get node() {
699
861
  if (!this.buffer)
@@ -716,58 +878,54 @@ class TreeCursor {
716
878
  result = new BufferNode(this.buffer, result, this.stack[i]);
717
879
  return this.bufferNode = new BufferNode(this.buffer, result, this.index);
718
880
  }
719
- /// Get the [tree](#tree.Tree) that represents the current node, if
881
+ /// Get the [tree](#common.Tree) that represents the current node, if
720
882
  /// any. Will return null when the node is in a [tree
721
- /// buffer](#tree.TreeBuffer).
883
+ /// buffer](#common.TreeBuffer).
722
884
  get tree() {
723
885
  return this.buffer ? null : this._tree.node;
724
886
  }
725
887
  }
726
888
  function hasChild(tree) {
727
- return tree.children.some(ch => !ch.type.isAnonymous || ch instanceof TreeBuffer || hasChild(ch));
889
+ return tree.children.some(ch => ch instanceof TreeBuffer || !ch.type.isAnonymous || hasChild(ch));
728
890
  }
729
- class FlatBufferCursor {
730
- constructor(buffer, index) {
731
- this.buffer = buffer;
732
- this.index = index;
733
- }
734
- get id() { return this.buffer[this.index - 4]; }
735
- get start() { return this.buffer[this.index - 3]; }
736
- get end() { return this.buffer[this.index - 2]; }
737
- get size() { return this.buffer[this.index - 1]; }
738
- get pos() { return this.index; }
739
- next() { this.index -= 4; }
740
- fork() { return new FlatBufferCursor(this.buffer, this.index); }
741
- }
742
- const BalanceBranchFactor = 8;
743
891
  function buildTree(data) {
744
892
  var _a;
745
- let { buffer, nodeSet, topID = 0, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet.types.length } = data;
893
+ let { buffer, nodeSet, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet.types.length } = data;
746
894
  let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
747
895
  let types = nodeSet.types;
748
- let contextHash = 0;
896
+ let contextHash = 0, lookAhead = 0;
749
897
  function takeNode(parentStart, minPos, children, positions, inRepeat) {
750
898
  let { id, start, end, size } = cursor;
751
- let startPos = start - parentStart;
752
- if (size < 0) {
753
- if (size == -1) { // Reused node
754
- children.push(reused[id]);
755
- positions.push(startPos);
899
+ let lookAheadAtStart = lookAhead;
900
+ while (size < 0) {
901
+ cursor.next();
902
+ if (size == -1 /* Reuse */) {
903
+ let node = reused[id];
904
+ children.push(node);
905
+ positions.push(start - parentStart);
906
+ return;
756
907
  }
757
- else { // Context change
908
+ else if (size == -3 /* ContextChange */) { // Context change
758
909
  contextHash = id;
910
+ return;
911
+ }
912
+ else if (size == -4 /* LookAhead */) {
913
+ lookAhead = id;
914
+ return;
915
+ }
916
+ else {
917
+ throw new RangeError(`Unrecognized record size: ${size}`);
759
918
  }
760
- cursor.next();
761
- return;
762
919
  }
763
920
  let type = types[id], node, buffer;
921
+ let startPos = start - parentStart;
764
922
  if (end - start <= maxBufferLength && (buffer = findBufferSize(cursor.pos - minPos, inRepeat))) {
765
923
  // Small enough for a buffer, and no reused nodes inside
766
924
  let data = new Uint16Array(buffer.size - buffer.skip);
767
925
  let endPos = cursor.pos - buffer.size, index = data.length;
768
926
  while (cursor.pos > endPos)
769
- index = copyToBuffer(buffer.start, data, index, inRepeat);
770
- node = new TreeBuffer(data, end - buffer.start, nodeSet, inRepeat < 0 ? NodeType.none : types[inRepeat]);
927
+ index = copyToBuffer(buffer.start, data, index);
928
+ node = new TreeBuffer(data, end - buffer.start, nodeSet);
771
929
  startPos = buffer.start - parentStart;
772
930
  }
773
931
  else { // Make it a node
@@ -775,22 +933,67 @@ function buildTree(data) {
775
933
  cursor.next();
776
934
  let localChildren = [], localPositions = [];
777
935
  let localInRepeat = id >= minRepeatType ? id : -1;
936
+ let lastGroup = 0, lastEnd = end;
778
937
  while (cursor.pos > endPos) {
779
- if (cursor.id == localInRepeat)
938
+ if (localInRepeat >= 0 && cursor.id == localInRepeat && cursor.size >= 0) {
939
+ if (cursor.end <= lastEnd - maxBufferLength) {
940
+ makeRepeatLeaf(localChildren, localPositions, start, lastGroup, cursor.end, lastEnd, localInRepeat, lookAheadAtStart);
941
+ lastGroup = localChildren.length;
942
+ lastEnd = cursor.end;
943
+ }
780
944
  cursor.next();
781
- else
945
+ }
946
+ else {
782
947
  takeNode(start, endPos, localChildren, localPositions, localInRepeat);
948
+ }
783
949
  }
950
+ if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
951
+ makeRepeatLeaf(localChildren, localPositions, start, lastGroup, start, lastEnd, localInRepeat, lookAheadAtStart);
784
952
  localChildren.reverse();
785
953
  localPositions.reverse();
786
- if (localInRepeat > -1 && localChildren.length > BalanceBranchFactor)
787
- node = balanceRange(type, type, localChildren, localPositions, 0, localChildren.length, 0, maxBufferLength, end - start, contextHash);
788
- else
789
- node = withHash(new Tree(type, localChildren, localPositions, end - start), contextHash);
954
+ if (localInRepeat > -1 && lastGroup > 0) {
955
+ let make = makeBalanced(type);
956
+ node = balanceRange(type, localChildren, localPositions, 0, localChildren.length, 0, end - start, make, make);
957
+ }
958
+ else {
959
+ node = makeTree(type, localChildren, localPositions, end - start, lookAheadAtStart - end);
960
+ }
790
961
  }
791
962
  children.push(node);
792
963
  positions.push(startPos);
793
964
  }
965
+ function makeBalanced(type) {
966
+ return (children, positions, length) => {
967
+ let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
968
+ if (lastI >= 0 && (last = children[lastI]) instanceof Tree) {
969
+ if (!lastI && last.type == type && last.length == length)
970
+ return last;
971
+ if (lookAheadProp = last.prop(NodeProp.lookAhead))
972
+ lookAhead = positions[lastI] + last.length + lookAheadProp;
973
+ }
974
+ return makeTree(type, children, positions, length, lookAhead);
975
+ };
976
+ }
977
+ function makeRepeatLeaf(children, positions, base, i, from, to, type, lookAhead) {
978
+ let localChildren = [], localPositions = [];
979
+ while (children.length > i) {
980
+ localChildren.push(children.pop());
981
+ localPositions.push(positions.pop() + base - from);
982
+ }
983
+ children.push(makeTree(nodeSet.types[type], localChildren, localPositions, to - from, lookAhead - to));
984
+ positions.push(from - base);
985
+ }
986
+ function makeTree(type, children, positions, length, lookAhead = 0, props) {
987
+ if (contextHash) {
988
+ let pair = [NodeProp.contextHash, contextHash];
989
+ props = props ? [pair].concat(props) : [pair];
990
+ }
991
+ if (lookAhead > 25) {
992
+ let pair = [NodeProp.lookAhead, lookAhead];
993
+ props = props ? [pair].concat(props) : [pair];
994
+ }
995
+ return new Tree(type, children, positions, length, props);
996
+ }
794
997
  function findBufferSize(maxSize, inRepeat) {
795
998
  // Scan through the buffer to find previous siblings that fit
796
999
  // together in a TreeBuffer, and don't contain any reused nodes
@@ -802,8 +1005,9 @@ function buildTree(data) {
802
1005
  let size = 0, start = 0, skip = 0, minStart = fork.end - maxBufferLength;
803
1006
  let result = { size: 0, start: 0, skip: 0 };
804
1007
  scan: for (let minPos = fork.pos - maxSize; fork.pos > minPos;) {
1008
+ let nodeSize = fork.size;
805
1009
  // Pretend nested repeat nodes of the same type don't exist
806
- if (fork.id == inRepeat) {
1010
+ if (fork.id == inRepeat && nodeSize >= 0) {
807
1011
  // Except that we store the current state as a valid return
808
1012
  // value.
809
1013
  result.size = size;
@@ -814,17 +1018,22 @@ function buildTree(data) {
814
1018
  fork.next();
815
1019
  continue;
816
1020
  }
817
- let nodeSize = fork.size, startPos = fork.pos - nodeSize;
1021
+ let startPos = fork.pos - nodeSize;
818
1022
  if (nodeSize < 0 || startPos < minPos || fork.start < minStart)
819
1023
  break;
820
1024
  let localSkipped = fork.id >= minRepeatType ? 4 : 0;
821
1025
  let nodeStart = fork.start;
822
1026
  fork.next();
823
1027
  while (fork.pos > startPos) {
824
- if (fork.size < 0)
825
- break scan;
826
- if (fork.id >= minRepeatType)
1028
+ if (fork.size < 0) {
1029
+ if (fork.size == -3 /* ContextChange */)
1030
+ localSkipped += 4;
1031
+ else
1032
+ break scan;
1033
+ }
1034
+ else if (fork.id >= minRepeatType) {
827
1035
  localSkipped += 4;
1036
+ }
828
1037
  fork.next();
829
1038
  }
830
1039
  start = nodeStart;
@@ -838,182 +1047,110 @@ function buildTree(data) {
838
1047
  }
839
1048
  return result.size > 4 ? result : undefined;
840
1049
  }
841
- function copyToBuffer(bufferStart, buffer, index, inRepeat) {
1050
+ function copyToBuffer(bufferStart, buffer, index) {
842
1051
  let { id, start, end, size } = cursor;
843
1052
  cursor.next();
844
- if (id == inRepeat)
845
- return index;
846
- let startIndex = index;
847
- if (size > 4) {
848
- let endPos = cursor.pos - (size - 4);
849
- while (cursor.pos > endPos)
850
- index = copyToBuffer(bufferStart, buffer, index, inRepeat);
851
- }
852
- if (id < minRepeatType) { // Don't copy repeat nodes into buffers
1053
+ if (size >= 0 && id < minRepeatType) {
1054
+ let startIndex = index;
1055
+ if (size > 4) {
1056
+ let endPos = cursor.pos - (size - 4);
1057
+ while (cursor.pos > endPos)
1058
+ index = copyToBuffer(bufferStart, buffer, index);
1059
+ }
853
1060
  buffer[--index] = startIndex;
854
1061
  buffer[--index] = end - bufferStart;
855
1062
  buffer[--index] = start - bufferStart;
856
1063
  buffer[--index] = id;
857
1064
  }
1065
+ else if (size == -3 /* ContextChange */) {
1066
+ contextHash = id;
1067
+ }
1068
+ else if (size == -4 /* LookAhead */) {
1069
+ lookAhead = id;
1070
+ }
858
1071
  return index;
859
1072
  }
860
1073
  let children = [], positions = [];
861
1074
  while (cursor.pos > 0)
862
- takeNode(data.start || 0, 0, children, positions, -1);
1075
+ takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
863
1076
  let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
864
- return new Tree(types[topID], children.reverse(), positions.reverse(), length);
1077
+ return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
865
1078
  }
866
- function balanceRange(outerType, innerType, children, positions, from, to, start, maxBufferLength, length, contextHash) {
867
- let localChildren = [], localPositions = [];
868
- if (length <= maxBufferLength) {
869
- for (let i = from; i < to; i++) {
870
- localChildren.push(children[i]);
871
- localPositions.push(positions[i] - start);
1079
+ const nodeSizeCache = new WeakMap;
1080
+ function nodeSize(balanceType, node) {
1081
+ if (!balanceType.isAnonymous || node instanceof TreeBuffer || node.type != balanceType)
1082
+ return 1;
1083
+ let size = nodeSizeCache.get(node);
1084
+ if (size == null) {
1085
+ size = 1;
1086
+ for (let child of node.children) {
1087
+ if (child.type != balanceType || !(child instanceof Tree)) {
1088
+ size = 1;
1089
+ break;
1090
+ }
1091
+ size += nodeSize(balanceType, child);
872
1092
  }
1093
+ nodeSizeCache.set(node, size);
873
1094
  }
874
- else {
875
- let maxChild = Math.max(maxBufferLength, Math.ceil(length * 1.5 / BalanceBranchFactor));
1095
+ return size;
1096
+ }
1097
+ function balanceRange(
1098
+ // The type the balanced tree's inner nodes.
1099
+ balanceType,
1100
+ // The direct children and their positions
1101
+ children, positions,
1102
+ // The index range in children/positions to use
1103
+ from, to,
1104
+ // The start position of the nodes, relative to their parent.
1105
+ start,
1106
+ // Length of the outer node
1107
+ length,
1108
+ // Function to build the top node of the balanced tree
1109
+ mkTop,
1110
+ // Function to build internal nodes for the balanced tree
1111
+ mkTree) {
1112
+ let total = 0;
1113
+ for (let i = from; i < to; i++)
1114
+ total += nodeSize(balanceType, children[i]);
1115
+ let maxChild = Math.ceil((total * 1.5) / 8 /* BranchFactor */);
1116
+ let localChildren = [], localPositions = [];
1117
+ function divide(children, positions, from, to, offset) {
876
1118
  for (let i = from; i < to;) {
877
- let groupFrom = i, groupStart = positions[i];
1119
+ let groupFrom = i, groupStart = positions[i], groupSize = nodeSize(balanceType, children[i]);
878
1120
  i++;
879
1121
  for (; i < to; i++) {
880
- let nextEnd = positions[i] + children[i].length;
881
- if (nextEnd - groupStart > maxChild)
1122
+ let nextSize = nodeSize(balanceType, children[i]);
1123
+ if (groupSize + nextSize >= maxChild)
882
1124
  break;
1125
+ groupSize += nextSize;
883
1126
  }
884
1127
  if (i == groupFrom + 1) {
885
- let only = children[groupFrom];
886
- if (only instanceof Tree && only.type == innerType && only.length > maxChild << 1) { // Too big, collapse
887
- for (let j = 0; j < only.children.length; j++) {
888
- localChildren.push(only.children[j]);
889
- localPositions.push(only.positions[j] + groupStart - start);
890
- }
1128
+ if (groupSize > maxChild) {
1129
+ let only = children[groupFrom]; // Only trees can have a size > 1
1130
+ divide(only.children, only.positions, 0, only.children.length, positions[groupFrom] + offset);
891
1131
  continue;
892
1132
  }
893
- localChildren.push(only);
894
- }
895
- else if (i == groupFrom + 1) {
896
1133
  localChildren.push(children[groupFrom]);
897
1134
  }
898
1135
  else {
899
- let inner = balanceRange(innerType, innerType, children, positions, groupFrom, i, groupStart, maxBufferLength, positions[i - 1] + children[i - 1].length - groupStart, contextHash);
900
- if (innerType != NodeType.none && !containsType(inner.children, innerType))
901
- inner = withHash(new Tree(NodeType.none, inner.children, inner.positions, inner.length), contextHash);
902
- localChildren.push(inner);
1136
+ let length = positions[i - 1] + children[i - 1].length - groupStart;
1137
+ localChildren.push(balanceRange(balanceType, children, positions, groupFrom, i, groupStart, length, null, mkTree));
903
1138
  }
904
- localPositions.push(groupStart - start);
905
- }
906
- }
907
- return withHash(new Tree(outerType, localChildren, localPositions, length), contextHash);
908
- }
909
- function containsType(nodes, type) {
910
- for (let elt of nodes)
911
- if (elt.type == type)
912
- return true;
913
- return false;
914
- }
915
- /// Tree fragments are used during [incremental
916
- /// parsing](#lezer.ParseOptions.fragments) to track parts of old
917
- /// trees that can be reused in a new parse. An array of fragments is
918
- /// used to track regions of an old tree whose nodes might be reused
919
- /// in new parses. Use the static
920
- /// [`applyChanges`](#tree.TreeFragment^applyChanges) method to update
921
- /// fragments for document changes.
922
- class TreeFragment {
923
- constructor(
924
- /// The start of the unchanged range pointed to by this fragment.
925
- /// This refers to an offset in the _updated_ document (as opposed
926
- /// to the original tree).
927
- from,
928
- /// The end of the unchanged range.
929
- to,
930
- /// The tree that this fragment is based on.
931
- tree,
932
- /// The offset between the fragment's tree and the document that
933
- /// this fragment can be used against. Add this when going from
934
- /// document to tree positions, subtract it to go from tree to
935
- /// document positions.
936
- offset, open) {
937
- this.from = from;
938
- this.to = to;
939
- this.tree = tree;
940
- this.offset = offset;
941
- this.open = open;
942
- }
943
- get openStart() { return (this.open & 1 /* Start */) > 0; }
944
- get openEnd() { return (this.open & 2 /* End */) > 0; }
945
- /// Apply a set of edits to an array of fragments, removing or
946
- /// splitting fragments as necessary to remove edited ranges, and
947
- /// adjusting offsets for fragments that moved.
948
- static applyChanges(fragments, changes, minGap = 128) {
949
- if (!changes.length)
950
- return fragments;
951
- let result = [];
952
- let fI = 1, nextF = fragments.length ? fragments[0] : null;
953
- for (let cI = 0, pos = 0, off = 0;; cI++) {
954
- let nextC = cI < changes.length ? changes[cI] : null;
955
- let nextPos = nextC ? nextC.fromA : 1e9;
956
- if (nextPos - pos >= minGap)
957
- while (nextF && nextF.from < nextPos) {
958
- let cut = nextF;
959
- if (pos >= cut.from || nextPos <= cut.to || off) {
960
- let fFrom = Math.max(cut.from, pos) - off, fTo = Math.min(cut.to, nextPos) - off;
961
- cut = fFrom >= fTo ? null :
962
- new TreeFragment(fFrom, fTo, cut.tree, cut.offset + off, (cI > 0 ? 1 /* Start */ : 0) | (nextC ? 2 /* End */ : 0));
963
- }
964
- if (cut)
965
- result.push(cut);
966
- if (nextF.to > nextPos)
967
- break;
968
- nextF = fI < fragments.length ? fragments[fI++] : null;
969
- }
970
- if (!nextC)
971
- break;
972
- pos = nextC.toA;
973
- off = nextC.toA - nextC.toB;
1139
+ localPositions.push(groupStart + offset - start);
974
1140
  }
975
- return result;
976
- }
977
- /// Create a set of fragments from a freshly parsed tree, or update
978
- /// an existing set of fragments by replacing the ones that overlap
979
- /// with a tree with content from the new tree. When `partial` is
980
- /// true, the parse is treated as incomplete, and the token at its
981
- /// end is not included in [`safeTo`](#tree.TreeFragment.safeTo).
982
- static addTree(tree, fragments = [], partial = false) {
983
- let result = [new TreeFragment(0, tree.length, tree, 0, partial ? 2 /* End */ : 0)];
984
- for (let f of fragments)
985
- if (f.to > tree.length)
986
- result.push(f);
987
- return result;
988
- }
989
- }
990
- // Creates an `Input` that is backed by a single, flat string.
991
- function stringInput(input) { return new StringInput(input); }
992
- class StringInput {
993
- constructor(string, length = string.length) {
994
- this.string = string;
995
- this.length = length;
996
- }
997
- get(pos) {
998
- return pos < 0 || pos >= this.length ? -1 : this.string.charCodeAt(pos);
999
- }
1000
- lineAfter(pos) {
1001
- if (pos < 0)
1002
- return "";
1003
- let end = this.string.indexOf("\n", pos);
1004
- return this.string.slice(pos, end < 0 ? this.length : Math.min(end, this.length));
1005
1141
  }
1006
- read(from, to) { return this.string.slice(from, Math.min(this.length, to)); }
1007
- clip(at) { return new StringInput(this.string, at); }
1142
+ divide(children, positions, from, to, 0);
1143
+ return (mkTop || mkTree)(localChildren, localPositions, length);
1008
1144
  }
1009
1145
 
1010
1146
  exports.DefaultBufferLength = DefaultBufferLength;
1147
+ exports.MountedTree = MountedTree;
1011
1148
  exports.NodeProp = NodeProp;
1012
1149
  exports.NodeSet = NodeSet;
1013
1150
  exports.NodeType = NodeType;
1151
+ exports.Range = Range;
1014
1152
  exports.Tree = Tree;
1015
1153
  exports.TreeBuffer = TreeBuffer;
1016
1154
  exports.TreeCursor = TreeCursor;
1017
- exports.TreeFragment = TreeFragment;
1018
- exports.stringInput = stringInput;
1155
+ exports.TreeNode = TreeNode;
1019
1156
  //# sourceMappingURL=tree.cjs.map