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