@lezer/common 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +611 -338
- package/dist/index.d.cts +1126 -0
- package/dist/index.d.ts +1126 -3
- package/dist/index.js +611 -336
- package/package.json +5 -10
- package/dist/mix.d.ts +0 -13
- package/dist/parse.d.ts +0 -48
- package/dist/tree.d.ts +0 -262
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// parent pointer
|
|
7
|
-
/// The default maximum length of a `TreeBuffer` node.
|
|
3
|
+
/**
|
|
4
|
+
The default maximum length of a `TreeBuffer` node.
|
|
5
|
+
*/
|
|
8
6
|
const DefaultBufferLength = 1024;
|
|
9
7
|
let nextPropID = 0;
|
|
10
8
|
class Range {
|
|
@@ -13,11 +11,15 @@ class Range {
|
|
|
13
11
|
this.to = to;
|
|
14
12
|
}
|
|
15
13
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
/**
|
|
15
|
+
Each [node type](#common.NodeType) or [individual tree](#common.Tree)
|
|
16
|
+
can have metadata associated with it in props. Instances of this
|
|
17
|
+
class represent prop names.
|
|
18
|
+
*/
|
|
19
19
|
class NodeProp {
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
Create a new node prop type.
|
|
22
|
+
*/
|
|
21
23
|
constructor(config = {}) {
|
|
22
24
|
this.id = nextPropID++;
|
|
23
25
|
this.perNode = !!config.perNode;
|
|
@@ -25,13 +27,15 @@ class NodeProp {
|
|
|
25
27
|
throw new Error("This node type doesn't define a deserialize function");
|
|
26
28
|
});
|
|
27
29
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
/**
|
|
31
|
+
This is meant to be used with
|
|
32
|
+
[`NodeSet.extend`](#common.NodeSet.extend) or
|
|
33
|
+
[`LRParser.configure`](#lr.ParserConfig.props) to compute
|
|
34
|
+
prop values for each node type in the set. Takes a [match
|
|
35
|
+
object](#common.NodeType^match) or function that returns undefined
|
|
36
|
+
if the node type doesn't get this prop, and the prop's value if
|
|
37
|
+
it does.
|
|
38
|
+
*/
|
|
35
39
|
add(match) {
|
|
36
40
|
if (this.perNode)
|
|
37
41
|
throw new RangeError("Can't add per-node props to node types");
|
|
@@ -43,77 +47,117 @@ class NodeProp {
|
|
|
43
47
|
};
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
/**
|
|
51
|
+
Prop that is used to describe matching delimiters. For opening
|
|
52
|
+
delimiters, this holds an array of node names (written as a
|
|
53
|
+
space-separated string when declaring this prop in a grammar)
|
|
54
|
+
for the node types of closing delimiters that match it.
|
|
55
|
+
*/
|
|
50
56
|
NodeProp.closedBy = new NodeProp({ deserialize: str => str.split(" ") });
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
/**
|
|
58
|
+
The inverse of [`closedBy`](#common.NodeProp^closedBy). This is
|
|
59
|
+
attached to closing delimiters, holding an array of node names
|
|
60
|
+
of types of matching opening delimiters.
|
|
61
|
+
*/
|
|
54
62
|
NodeProp.openedBy = new NodeProp({ deserialize: str => str.split(" ") });
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
/**
|
|
64
|
+
Used to assign node types to groups (for example, all node
|
|
65
|
+
types that represent an expression could be tagged with an
|
|
66
|
+
`"Expression"` group).
|
|
67
|
+
*/
|
|
58
68
|
NodeProp.group = new NodeProp({ deserialize: str => str.split(" ") });
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
/**
|
|
70
|
+
The hash of the [context](#lr.ContextTracker.constructor)
|
|
71
|
+
that the node was parsed in, if any. Used to limit reuse of
|
|
72
|
+
contextual nodes.
|
|
73
|
+
*/
|
|
62
74
|
NodeProp.contextHash = new NodeProp({ perNode: true });
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
/**
|
|
76
|
+
The distance beyond the end of the node that the tokenizer
|
|
77
|
+
looked ahead for any of the tokens inside the node. (The LR
|
|
78
|
+
parser only stores this when it is larger than 25, for
|
|
79
|
+
efficiency reasons.)
|
|
80
|
+
*/
|
|
67
81
|
NodeProp.lookAhead = new NodeProp({ perNode: true });
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
/**
|
|
83
|
+
This per-node prop is used to replace a given node, or part of a
|
|
84
|
+
node, with another tree. This is useful to include trees from
|
|
85
|
+
different languages in mixed-language parsers.
|
|
86
|
+
*/
|
|
71
87
|
NodeProp.mounted = new NodeProp({ perNode: true });
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
/**
|
|
89
|
+
A mounted tree, which can be [stored](#common.NodeProp^mounted) on
|
|
90
|
+
a tree node to indicate that parts of its content are
|
|
91
|
+
represented by another tree.
|
|
92
|
+
*/
|
|
75
93
|
class MountedTree {
|
|
76
94
|
constructor(
|
|
77
|
-
|
|
95
|
+
/**
|
|
96
|
+
The inner tree.
|
|
97
|
+
*/
|
|
78
98
|
tree,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
/**
|
|
100
|
+
If this is null, this tree replaces the entire node (it will
|
|
101
|
+
be included in the regular iteration instead of its host
|
|
102
|
+
node). If not, only the given ranges are considered to be
|
|
103
|
+
covered by this tree. This is used for trees that are mixed in
|
|
104
|
+
a way that isn't strictly hierarchical. Such mounted trees are
|
|
105
|
+
only entered by [`resolveInner`](#common.Tree.resolveInner)
|
|
106
|
+
and [`enter`](#common.SyntaxNode.enter).
|
|
107
|
+
*/
|
|
86
108
|
overlay,
|
|
87
|
-
|
|
109
|
+
/**
|
|
110
|
+
The parser used to create this subtree.
|
|
111
|
+
*/
|
|
88
112
|
parser) {
|
|
89
113
|
this.tree = tree;
|
|
90
114
|
this.overlay = overlay;
|
|
91
115
|
this.parser = parser;
|
|
92
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
@internal
|
|
119
|
+
*/
|
|
120
|
+
static get(tree) {
|
|
121
|
+
return tree && tree.props && tree.props[NodeProp.mounted.id];
|
|
122
|
+
}
|
|
93
123
|
}
|
|
94
124
|
const noProps = Object.create(null);
|
|
95
|
-
|
|
125
|
+
/**
|
|
126
|
+
Each node in a syntax tree has a node type associated with it.
|
|
127
|
+
*/
|
|
96
128
|
class NodeType {
|
|
97
|
-
|
|
129
|
+
/**
|
|
130
|
+
@internal
|
|
131
|
+
*/
|
|
98
132
|
constructor(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
133
|
+
/**
|
|
134
|
+
The name of the node type. Not necessarily unique, but if the
|
|
135
|
+
grammar was written properly, different node types with the
|
|
136
|
+
same name within a node set should play the same semantic
|
|
137
|
+
role.
|
|
138
|
+
*/
|
|
103
139
|
name,
|
|
104
|
-
|
|
140
|
+
/**
|
|
141
|
+
@internal
|
|
142
|
+
*/
|
|
105
143
|
props,
|
|
106
|
-
|
|
107
|
-
|
|
144
|
+
/**
|
|
145
|
+
The id of this node in its set. Corresponds to the term ids
|
|
146
|
+
used in the parser.
|
|
147
|
+
*/
|
|
108
148
|
id,
|
|
109
|
-
|
|
149
|
+
/**
|
|
150
|
+
@internal
|
|
151
|
+
*/
|
|
110
152
|
flags = 0) {
|
|
111
153
|
this.name = name;
|
|
112
154
|
this.props = props;
|
|
113
155
|
this.id = id;
|
|
114
156
|
this.flags = flags;
|
|
115
157
|
}
|
|
116
|
-
|
|
158
|
+
/**
|
|
159
|
+
Define a node type.
|
|
160
|
+
*/
|
|
117
161
|
static define(spec) {
|
|
118
162
|
let props = spec.props && spec.props.length ? Object.create(null) : noProps;
|
|
119
163
|
let flags = (spec.top ? 1 /* NodeFlag.Top */ : 0) | (spec.skipped ? 2 /* NodeFlag.Skipped */ : 0) |
|
|
@@ -131,20 +175,32 @@ class NodeType {
|
|
|
131
175
|
}
|
|
132
176
|
return type;
|
|
133
177
|
}
|
|
134
|
-
|
|
135
|
-
|
|
178
|
+
/**
|
|
179
|
+
Retrieves a node prop for this type. Will return `undefined` if
|
|
180
|
+
the prop isn't present on this node.
|
|
181
|
+
*/
|
|
136
182
|
prop(prop) { return this.props[prop.id]; }
|
|
137
|
-
|
|
183
|
+
/**
|
|
184
|
+
True when this is the top node of a grammar.
|
|
185
|
+
*/
|
|
138
186
|
get isTop() { return (this.flags & 1 /* NodeFlag.Top */) > 0; }
|
|
139
|
-
|
|
187
|
+
/**
|
|
188
|
+
True when this node is produced by a skip rule.
|
|
189
|
+
*/
|
|
140
190
|
get isSkipped() { return (this.flags & 2 /* NodeFlag.Skipped */) > 0; }
|
|
141
|
-
|
|
191
|
+
/**
|
|
192
|
+
Indicates whether this is an error node.
|
|
193
|
+
*/
|
|
142
194
|
get isError() { return (this.flags & 4 /* NodeFlag.Error */) > 0; }
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
/**
|
|
196
|
+
When true, this node type doesn't correspond to a user-declared
|
|
197
|
+
named node, for example because it is used to cache repetition.
|
|
198
|
+
*/
|
|
145
199
|
get isAnonymous() { return (this.flags & 8 /* NodeFlag.Anonymous */) > 0; }
|
|
146
|
-
|
|
147
|
-
|
|
200
|
+
/**
|
|
201
|
+
Returns true when this node's name or one of its
|
|
202
|
+
[groups](#common.NodeProp^group) matches the given string.
|
|
203
|
+
*/
|
|
148
204
|
is(name) {
|
|
149
205
|
if (typeof name == 'string') {
|
|
150
206
|
if (this.name == name)
|
|
@@ -154,12 +210,14 @@ class NodeType {
|
|
|
154
210
|
}
|
|
155
211
|
return this.id == name;
|
|
156
212
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
213
|
+
/**
|
|
214
|
+
Create a function from node types to arbitrary values by
|
|
215
|
+
specifying an object whose property names are node or
|
|
216
|
+
[group](#common.NodeProp^group) names. Often useful with
|
|
217
|
+
[`NodeProp.add`](#common.NodeProp.add). You can put multiple
|
|
218
|
+
names, separated by spaces, in a single property name to map
|
|
219
|
+
multiple node names to a single value.
|
|
220
|
+
*/
|
|
163
221
|
static match(map) {
|
|
164
222
|
let direct = Object.create(null);
|
|
165
223
|
for (let prop in map)
|
|
@@ -174,29 +232,39 @@ class NodeType {
|
|
|
174
232
|
};
|
|
175
233
|
}
|
|
176
234
|
}
|
|
177
|
-
|
|
235
|
+
/**
|
|
236
|
+
An empty dummy node type to use when no actual type is available.
|
|
237
|
+
*/
|
|
178
238
|
NodeType.none = new NodeType("", Object.create(null), 0, 8 /* NodeFlag.Anonymous */);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
239
|
+
/**
|
|
240
|
+
A node set holds a collection of node types. It is used to
|
|
241
|
+
compactly represent trees by storing their type ids, rather than a
|
|
242
|
+
full pointer to the type object, in a numeric array. Each parser
|
|
243
|
+
[has](#lr.LRParser.nodeSet) a node set, and [tree
|
|
244
|
+
buffers](#common.TreeBuffer) can only store collections of nodes
|
|
245
|
+
from the same set. A set can have a maximum of 2**16 (65536) node
|
|
246
|
+
types in it, so that the ids fit into 16-bit typed array slots.
|
|
247
|
+
*/
|
|
186
248
|
class NodeSet {
|
|
187
|
-
|
|
188
|
-
|
|
249
|
+
/**
|
|
250
|
+
Create a set with the given types. The `id` property of each
|
|
251
|
+
type should correspond to its position within the array.
|
|
252
|
+
*/
|
|
189
253
|
constructor(
|
|
190
|
-
|
|
254
|
+
/**
|
|
255
|
+
The node types in this set, by id.
|
|
256
|
+
*/
|
|
191
257
|
types) {
|
|
192
258
|
this.types = types;
|
|
193
259
|
for (let i = 0; i < types.length; i++)
|
|
194
260
|
if (types[i].id != i)
|
|
195
261
|
throw new RangeError("Node type ids should correspond to array positions when creating a node set");
|
|
196
262
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
263
|
+
/**
|
|
264
|
+
Create a copy of this set with some node properties added. The
|
|
265
|
+
arguments to this method can be created with
|
|
266
|
+
[`NodeProp.add`](#common.NodeProp.add).
|
|
267
|
+
*/
|
|
200
268
|
extend(...props) {
|
|
201
269
|
let newTypes = [];
|
|
202
270
|
for (let type of this.types) {
|
|
@@ -215,61 +283,87 @@ class NodeSet {
|
|
|
215
283
|
}
|
|
216
284
|
}
|
|
217
285
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
218
|
-
|
|
219
|
-
|
|
286
|
+
/**
|
|
287
|
+
Options that control iteration. Can be combined with the `|`
|
|
288
|
+
operator to enable multiple ones.
|
|
289
|
+
*/
|
|
220
290
|
exports.IterMode = void 0;
|
|
221
291
|
(function (IterMode) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
292
|
+
/**
|
|
293
|
+
When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
294
|
+
objects, not nodes packed into
|
|
295
|
+
[`TreeBuffer`](#common.TreeBuffer)s.
|
|
296
|
+
*/
|
|
225
297
|
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
298
|
+
/**
|
|
299
|
+
Enable this to make iteration include anonymous nodes (such as
|
|
300
|
+
the nodes that wrap repeated grammar constructs into a balanced
|
|
301
|
+
tree).
|
|
302
|
+
*/
|
|
229
303
|
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
304
|
+
/**
|
|
305
|
+
By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
306
|
+
replace their base node in iteration. Enable this to ignore them
|
|
307
|
+
instead.
|
|
308
|
+
*/
|
|
233
309
|
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
310
|
+
/**
|
|
311
|
+
This option only applies in
|
|
312
|
+
[`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
313
|
+
library to not enter mounted overlays if one covers the given
|
|
314
|
+
position.
|
|
315
|
+
*/
|
|
238
316
|
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
239
317
|
})(exports.IterMode || (exports.IterMode = {}));
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
318
|
+
/**
|
|
319
|
+
A piece of syntax tree. There are two ways to approach these
|
|
320
|
+
trees: the way they are actually stored in memory, and the
|
|
321
|
+
convenient way.
|
|
322
|
+
|
|
323
|
+
Syntax trees are stored as a tree of `Tree` and `TreeBuffer`
|
|
324
|
+
objects. By packing detail information into `TreeBuffer` leaf
|
|
325
|
+
nodes, the representation is made a lot more memory-efficient.
|
|
326
|
+
|
|
327
|
+
However, when you want to actually work with tree nodes, this
|
|
328
|
+
representation is very awkward, so most client code will want to
|
|
329
|
+
use the [`TreeCursor`](#common.TreeCursor) or
|
|
330
|
+
[`SyntaxNode`](#common.SyntaxNode) interface instead, which provides
|
|
331
|
+
a view on some part of this data structure, and can be used to
|
|
332
|
+
move around to adjacent nodes.
|
|
333
|
+
*/
|
|
254
334
|
class Tree {
|
|
255
|
-
|
|
335
|
+
/**
|
|
336
|
+
Construct a new tree. See also [`Tree.build`](#common.Tree^build).
|
|
337
|
+
*/
|
|
256
338
|
constructor(
|
|
257
|
-
|
|
339
|
+
/**
|
|
340
|
+
The type of the top node.
|
|
341
|
+
*/
|
|
258
342
|
type,
|
|
259
|
-
|
|
343
|
+
/**
|
|
344
|
+
This node's child nodes.
|
|
345
|
+
*/
|
|
260
346
|
children,
|
|
261
|
-
|
|
262
|
-
|
|
347
|
+
/**
|
|
348
|
+
The positions (offsets relative to the start of this tree) of
|
|
349
|
+
the children.
|
|
350
|
+
*/
|
|
263
351
|
positions,
|
|
264
|
-
|
|
352
|
+
/**
|
|
353
|
+
The total length of this tree
|
|
354
|
+
*/
|
|
265
355
|
length,
|
|
266
|
-
|
|
356
|
+
/**
|
|
357
|
+
Per-node [node props](#common.NodeProp) to associate with this node.
|
|
358
|
+
*/
|
|
267
359
|
props) {
|
|
268
360
|
this.type = type;
|
|
269
361
|
this.children = children;
|
|
270
362
|
this.positions = positions;
|
|
271
363
|
this.length = length;
|
|
272
|
-
|
|
364
|
+
/**
|
|
365
|
+
@internal
|
|
366
|
+
*/
|
|
273
367
|
this.props = null;
|
|
274
368
|
if (props && props.length) {
|
|
275
369
|
this.props = Object.create(null);
|
|
@@ -277,9 +371,11 @@ class Tree {
|
|
|
277
371
|
this.props[typeof prop == "number" ? prop : prop.id] = value;
|
|
278
372
|
}
|
|
279
373
|
}
|
|
280
|
-
|
|
374
|
+
/**
|
|
375
|
+
@internal
|
|
376
|
+
*/
|
|
281
377
|
toString() {
|
|
282
|
-
let mounted =
|
|
378
|
+
let mounted = MountedTree.get(this);
|
|
283
379
|
if (mounted && !mounted.overlay)
|
|
284
380
|
return mounted.tree.toString();
|
|
285
381
|
let children = "";
|
|
@@ -295,15 +391,19 @@ class Tree {
|
|
|
295
391
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
296
392
|
(children.length ? "(" + children + ")" : "");
|
|
297
393
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
394
|
+
/**
|
|
395
|
+
Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
396
|
+
the tree. Mode can be used to [control](#common.IterMode) which
|
|
397
|
+
nodes the cursor visits.
|
|
398
|
+
*/
|
|
301
399
|
cursor(mode = 0) {
|
|
302
400
|
return new TreeCursor(this.topNode, mode);
|
|
303
401
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
402
|
+
/**
|
|
403
|
+
Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
404
|
+
at the given position and side (see
|
|
405
|
+
[`moveTo`](#common.TreeCursor.moveTo).
|
|
406
|
+
*/
|
|
307
407
|
cursorAt(pos, side = 0, mode = 0) {
|
|
308
408
|
let scope = CachedNode.get(this) || this.topNode;
|
|
309
409
|
let cursor = new TreeCursor(scope);
|
|
@@ -311,40 +411,58 @@ class Tree {
|
|
|
311
411
|
CachedNode.set(this, cursor._tree);
|
|
312
412
|
return cursor;
|
|
313
413
|
}
|
|
314
|
-
|
|
315
|
-
|
|
414
|
+
/**
|
|
415
|
+
Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
416
|
+
tree.
|
|
417
|
+
*/
|
|
316
418
|
get topNode() {
|
|
317
419
|
return new TreeNode(this, 0, 0, null);
|
|
318
420
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
421
|
+
/**
|
|
422
|
+
Get the [syntax node](#common.SyntaxNode) at the given position.
|
|
423
|
+
If `side` is -1, this will move into nodes that end at the
|
|
424
|
+
position. If 1, it'll move into nodes that start at the
|
|
425
|
+
position. With 0, it'll only enter nodes that cover the position
|
|
426
|
+
from both sides.
|
|
427
|
+
|
|
428
|
+
Note that this will not enter
|
|
429
|
+
[overlays](#common.MountedTree.overlay), and you often want
|
|
430
|
+
[`resolveInner`](#common.Tree.resolveInner) instead.
|
|
431
|
+
*/
|
|
328
432
|
resolve(pos, side = 0) {
|
|
329
433
|
let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
|
|
330
434
|
CachedNode.set(this, node);
|
|
331
435
|
return node;
|
|
332
436
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
437
|
+
/**
|
|
438
|
+
Like [`resolve`](#common.Tree.resolve), but will enter
|
|
439
|
+
[overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
|
|
440
|
+
pointing into the innermost overlaid tree at the given position
|
|
441
|
+
(with parent links going through all parent structure, including
|
|
442
|
+
the host trees).
|
|
443
|
+
*/
|
|
338
444
|
resolveInner(pos, side = 0) {
|
|
339
445
|
let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
|
|
340
446
|
CachedInnerNode.set(this, node);
|
|
341
447
|
return node;
|
|
342
448
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
449
|
+
/**
|
|
450
|
+
In some situations, it can be useful to iterate through all
|
|
451
|
+
nodes around a position, including those in overlays that don't
|
|
452
|
+
directly cover the position. This method gives you an iterator
|
|
453
|
+
that will produce all nodes, from small to big, around the given
|
|
454
|
+
position.
|
|
455
|
+
*/
|
|
456
|
+
resolveStack(pos, side = 0) {
|
|
457
|
+
return stackIterator(this, pos, side);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
Iterate over the tree and its children, calling `enter` for any
|
|
461
|
+
node that touches the `from`/`to` region (if given) before
|
|
462
|
+
running over such a node's children, and `leave` (if given) when
|
|
463
|
+
leaving the node. When `enter` returns `false`, that node will
|
|
464
|
+
not have its children iterated over (or `leave` called).
|
|
465
|
+
*/
|
|
348
466
|
iterate(spec) {
|
|
349
467
|
let { enter, leave, from = 0, to = this.length } = spec;
|
|
350
468
|
let mode = spec.mode || 0, anon = (mode & exports.IterMode.IncludeAnonymous) > 0;
|
|
@@ -366,14 +484,18 @@ class Tree {
|
|
|
366
484
|
}
|
|
367
485
|
}
|
|
368
486
|
}
|
|
369
|
-
|
|
370
|
-
|
|
487
|
+
/**
|
|
488
|
+
Get the value of the given [node prop](#common.NodeProp) for this
|
|
489
|
+
node. Works with both per-node and per-type props.
|
|
490
|
+
*/
|
|
371
491
|
prop(prop) {
|
|
372
492
|
return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : undefined;
|
|
373
493
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
494
|
+
/**
|
|
495
|
+
Returns the node's [per-node props](#common.NodeProp.perNode) in a
|
|
496
|
+
format that can be passed to the [`Tree`](#common.Tree)
|
|
497
|
+
constructor.
|
|
498
|
+
*/
|
|
377
499
|
get propValues() {
|
|
378
500
|
let result = [];
|
|
379
501
|
if (this.props)
|
|
@@ -381,18 +503,24 @@ class Tree {
|
|
|
381
503
|
result.push([+id, this.props[id]]);
|
|
382
504
|
return result;
|
|
383
505
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
506
|
+
/**
|
|
507
|
+
Balance the direct children of this tree, producing a copy of
|
|
508
|
+
which may have children grouped into subtrees with type
|
|
509
|
+
[`NodeType.none`](#common.NodeType^none).
|
|
510
|
+
*/
|
|
387
511
|
balance(config = {}) {
|
|
388
512
|
return this.children.length <= 8 /* Balance.BranchFactor */ ? this :
|
|
389
513
|
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)));
|
|
390
514
|
}
|
|
391
|
-
|
|
392
|
-
|
|
515
|
+
/**
|
|
516
|
+
Build a tree from a postfix-ordered buffer of node information,
|
|
517
|
+
or a cursor over such a buffer.
|
|
518
|
+
*/
|
|
393
519
|
static build(data) { return buildTree(data); }
|
|
394
520
|
}
|
|
395
|
-
|
|
521
|
+
/**
|
|
522
|
+
The empty tree
|
|
523
|
+
*/
|
|
396
524
|
Tree.empty = new Tree(NodeType.none, [], [], 0);
|
|
397
525
|
class FlatBufferCursor {
|
|
398
526
|
constructor(buffer, index) {
|
|
@@ -407,26 +535,40 @@ class FlatBufferCursor {
|
|
|
407
535
|
next() { this.index -= 4; }
|
|
408
536
|
fork() { return new FlatBufferCursor(this.buffer, this.index); }
|
|
409
537
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
538
|
+
/**
|
|
539
|
+
Tree buffers contain (type, start, end, endIndex) quads for each
|
|
540
|
+
node. In such a buffer, nodes are stored in prefix order (parents
|
|
541
|
+
before children, with the endIndex of the parent indicating which
|
|
542
|
+
children belong to it).
|
|
543
|
+
*/
|
|
414
544
|
class TreeBuffer {
|
|
415
|
-
|
|
545
|
+
/**
|
|
546
|
+
Create a tree buffer.
|
|
547
|
+
*/
|
|
416
548
|
constructor(
|
|
417
|
-
|
|
549
|
+
/**
|
|
550
|
+
The buffer's content.
|
|
551
|
+
*/
|
|
418
552
|
buffer,
|
|
419
|
-
|
|
553
|
+
/**
|
|
554
|
+
The total length of the group of nodes in the buffer.
|
|
555
|
+
*/
|
|
420
556
|
length,
|
|
421
|
-
|
|
557
|
+
/**
|
|
558
|
+
The node set used in this buffer.
|
|
559
|
+
*/
|
|
422
560
|
set) {
|
|
423
561
|
this.buffer = buffer;
|
|
424
562
|
this.length = length;
|
|
425
563
|
this.set = set;
|
|
426
564
|
}
|
|
427
|
-
|
|
565
|
+
/**
|
|
566
|
+
@internal
|
|
567
|
+
*/
|
|
428
568
|
get type() { return NodeType.none; }
|
|
429
|
-
|
|
569
|
+
/**
|
|
570
|
+
@internal
|
|
571
|
+
*/
|
|
430
572
|
toString() {
|
|
431
573
|
let result = [];
|
|
432
574
|
for (let index = 0; index < this.buffer.length;) {
|
|
@@ -435,7 +577,9 @@ class TreeBuffer {
|
|
|
435
577
|
}
|
|
436
578
|
return result.join(",");
|
|
437
579
|
}
|
|
438
|
-
|
|
580
|
+
/**
|
|
581
|
+
@internal
|
|
582
|
+
*/
|
|
439
583
|
childString(index) {
|
|
440
584
|
let id = this.buffer[index], endIndex = this.buffer[index + 3];
|
|
441
585
|
let type = this.set.types[id], result = type.name;
|
|
@@ -451,7 +595,9 @@ class TreeBuffer {
|
|
|
451
595
|
}
|
|
452
596
|
return result + "(" + children.join(",") + ")";
|
|
453
597
|
}
|
|
454
|
-
|
|
598
|
+
/**
|
|
599
|
+
@internal
|
|
600
|
+
*/
|
|
455
601
|
findChild(startIndex, endIndex, dir, pos, side) {
|
|
456
602
|
let { buffer } = this, pick = -1;
|
|
457
603
|
for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
|
|
@@ -463,7 +609,9 @@ class TreeBuffer {
|
|
|
463
609
|
}
|
|
464
610
|
return pick;
|
|
465
611
|
}
|
|
466
|
-
|
|
612
|
+
/**
|
|
613
|
+
@internal
|
|
614
|
+
*/
|
|
467
615
|
slice(startI, endI, from) {
|
|
468
616
|
let b = this.buffer;
|
|
469
617
|
let copy = new Uint16Array(endI - startI), len = 0;
|
|
@@ -487,22 +635,6 @@ function checkSide(side, pos, from, to) {
|
|
|
487
635
|
case 4 /* Side.DontCare */: return true;
|
|
488
636
|
}
|
|
489
637
|
}
|
|
490
|
-
function enterUnfinishedNodesBefore(node, pos) {
|
|
491
|
-
let scan = node.childBefore(pos);
|
|
492
|
-
while (scan) {
|
|
493
|
-
let last = scan.lastChild;
|
|
494
|
-
if (!last || last.to != scan.to)
|
|
495
|
-
break;
|
|
496
|
-
if (last.type.isError && last.from == last.to) {
|
|
497
|
-
node = scan;
|
|
498
|
-
scan = last.prevSibling;
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
scan = last;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
return node;
|
|
505
|
-
}
|
|
506
638
|
function resolveNode(node, pos, side, overlays) {
|
|
507
639
|
var _a;
|
|
508
640
|
// Move up to a node that actually holds the position, if possible
|
|
@@ -528,10 +660,48 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
528
660
|
node = inner;
|
|
529
661
|
}
|
|
530
662
|
}
|
|
531
|
-
class
|
|
663
|
+
class BaseNode {
|
|
664
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
665
|
+
getChild(type, before = null, after = null) {
|
|
666
|
+
let r = getChildren(this, type, before, after);
|
|
667
|
+
return r.length ? r[0] : null;
|
|
668
|
+
}
|
|
669
|
+
getChildren(type, before = null, after = null) {
|
|
670
|
+
return getChildren(this, type, before, after);
|
|
671
|
+
}
|
|
672
|
+
resolve(pos, side = 0) {
|
|
673
|
+
return resolveNode(this, pos, side, false);
|
|
674
|
+
}
|
|
675
|
+
resolveInner(pos, side = 0) {
|
|
676
|
+
return resolveNode(this, pos, side, true);
|
|
677
|
+
}
|
|
678
|
+
matchContext(context) {
|
|
679
|
+
return matchNodeContext(this, context);
|
|
680
|
+
}
|
|
681
|
+
enterUnfinishedNodesBefore(pos) {
|
|
682
|
+
let scan = this.childBefore(pos), node = this;
|
|
683
|
+
while (scan) {
|
|
684
|
+
let last = scan.lastChild;
|
|
685
|
+
if (!last || last.to != scan.to)
|
|
686
|
+
break;
|
|
687
|
+
if (last.type.isError && last.from == last.to) {
|
|
688
|
+
node = scan;
|
|
689
|
+
scan = last.prevSibling;
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
scan = last;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return node;
|
|
696
|
+
}
|
|
697
|
+
get node() { return this; }
|
|
698
|
+
get next() { return this.parent; }
|
|
699
|
+
}
|
|
700
|
+
class TreeNode extends BaseNode {
|
|
532
701
|
constructor(_tree, from,
|
|
533
702
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
534
703
|
index, _parent) {
|
|
704
|
+
super();
|
|
535
705
|
this._tree = _tree;
|
|
536
706
|
this.from = from;
|
|
537
707
|
this.index = index;
|
|
@@ -555,8 +725,7 @@ class TreeNode {
|
|
|
555
725
|
}
|
|
556
726
|
else if ((mode & exports.IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
557
727
|
let mounted;
|
|
558
|
-
if (!(mode & exports.IterMode.IgnoreMounts) &&
|
|
559
|
-
next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
|
|
728
|
+
if (!(mode & exports.IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
|
|
560
729
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
561
730
|
let inner = new TreeNode(next, start, i, parent);
|
|
562
731
|
return (mode & exports.IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
@@ -580,7 +749,7 @@ class TreeNode {
|
|
|
580
749
|
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
|
|
581
750
|
enter(pos, side, mode = 0) {
|
|
582
751
|
let mounted;
|
|
583
|
-
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = this._tree
|
|
752
|
+
if (!(mode & exports.IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
|
|
584
753
|
let rPos = pos - this.from;
|
|
585
754
|
for (let { from, to } of mounted.overlay) {
|
|
586
755
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -605,27 +774,12 @@ class TreeNode {
|
|
|
605
774
|
get prevSibling() {
|
|
606
775
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
|
|
607
776
|
}
|
|
608
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
609
777
|
get tree() { return this._tree; }
|
|
610
778
|
toTree() { return this._tree; }
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
resolveInner(pos, side = 0) {
|
|
615
|
-
return resolveNode(this, pos, side, true);
|
|
616
|
-
}
|
|
617
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
618
|
-
getChild(type, before = null, after = null) {
|
|
619
|
-
let r = getChildren(this, type, before, after);
|
|
620
|
-
return r.length ? r[0] : null;
|
|
621
|
-
}
|
|
622
|
-
getChildren(type, before = null, after = null) {
|
|
623
|
-
return getChildren(this, type, before, after);
|
|
624
|
-
}
|
|
625
|
-
/// @internal
|
|
779
|
+
/**
|
|
780
|
+
@internal
|
|
781
|
+
*/
|
|
626
782
|
toString() { return this._tree.toString(); }
|
|
627
|
-
get node() { return this; }
|
|
628
|
-
matchContext(context) { return matchNodeContext(this, context); }
|
|
629
783
|
}
|
|
630
784
|
function getChildren(node, type, before, after) {
|
|
631
785
|
let cur = node.cursor(), result = [];
|
|
@@ -664,11 +818,12 @@ class BufferContext {
|
|
|
664
818
|
this.start = start;
|
|
665
819
|
}
|
|
666
820
|
}
|
|
667
|
-
class BufferNode {
|
|
821
|
+
class BufferNode extends BaseNode {
|
|
668
822
|
get name() { return this.type.name; }
|
|
669
823
|
get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
|
|
670
824
|
get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
|
|
671
825
|
constructor(context, _parent, index) {
|
|
826
|
+
super();
|
|
672
827
|
this.context = context;
|
|
673
828
|
this._parent = _parent;
|
|
674
829
|
this.index = index;
|
|
@@ -710,7 +865,6 @@ class BufferNode {
|
|
|
710
865
|
return this.externalSibling(-1);
|
|
711
866
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
|
|
712
867
|
}
|
|
713
|
-
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
714
868
|
get tree() { return null; }
|
|
715
869
|
toTree() {
|
|
716
870
|
let children = [], positions = [];
|
|
@@ -723,39 +877,84 @@ class BufferNode {
|
|
|
723
877
|
}
|
|
724
878
|
return new Tree(this.type, children, positions, this.to - this.from);
|
|
725
879
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
resolveInner(pos, side = 0) {
|
|
730
|
-
return resolveNode(this, pos, side, true);
|
|
731
|
-
}
|
|
732
|
-
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
733
|
-
/// @internal
|
|
880
|
+
/**
|
|
881
|
+
@internal
|
|
882
|
+
*/
|
|
734
883
|
toString() { return this.context.buffer.childString(this.index); }
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
884
|
+
}
|
|
885
|
+
function iterStack(heads) {
|
|
886
|
+
if (!heads.length)
|
|
887
|
+
return null;
|
|
888
|
+
if (heads.length == 1)
|
|
889
|
+
return heads[0];
|
|
890
|
+
let pick = 0, picked = heads[0];
|
|
891
|
+
for (let i = 1; i < heads.length; i++) {
|
|
892
|
+
let node = heads[i];
|
|
893
|
+
if (node.from > picked.from || node.to < picked.to) {
|
|
894
|
+
picked = node;
|
|
895
|
+
pick = i;
|
|
896
|
+
}
|
|
738
897
|
}
|
|
739
|
-
|
|
740
|
-
|
|
898
|
+
let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
|
|
899
|
+
let newHeads = heads.slice();
|
|
900
|
+
if (next)
|
|
901
|
+
newHeads[pick] = next;
|
|
902
|
+
else
|
|
903
|
+
newHeads.splice(pick, 1);
|
|
904
|
+
return new StackIterator(newHeads, picked);
|
|
905
|
+
}
|
|
906
|
+
class StackIterator {
|
|
907
|
+
constructor(heads, node) {
|
|
908
|
+
this.heads = heads;
|
|
909
|
+
this.node = node;
|
|
741
910
|
}
|
|
742
|
-
get
|
|
743
|
-
|
|
911
|
+
get next() { return iterStack(this.heads); }
|
|
912
|
+
}
|
|
913
|
+
function stackIterator(tree, pos, side) {
|
|
914
|
+
let inner = tree.resolveInner(pos, side), layers = null;
|
|
915
|
+
for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
|
|
916
|
+
if (scan.index < 0) { // This is an overlay root
|
|
917
|
+
let parent = scan.parent;
|
|
918
|
+
(layers || (layers = [inner])).push(parent.resolve(pos, side));
|
|
919
|
+
scan = parent;
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
let mount = MountedTree.get(scan.tree);
|
|
923
|
+
// Relevant overlay branching off
|
|
924
|
+
if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
|
|
925
|
+
let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, 0, null);
|
|
926
|
+
(layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return layers ? iterStack(layers) : inner;
|
|
744
931
|
}
|
|
745
|
-
|
|
746
|
-
|
|
932
|
+
/**
|
|
933
|
+
A tree cursor object focuses on a given node in a syntax tree, and
|
|
934
|
+
allows you to move to adjacent nodes.
|
|
935
|
+
*/
|
|
747
936
|
class TreeCursor {
|
|
748
|
-
|
|
937
|
+
/**
|
|
938
|
+
Shorthand for `.type.name`.
|
|
939
|
+
*/
|
|
749
940
|
get name() { return this.type.name; }
|
|
750
|
-
|
|
941
|
+
/**
|
|
942
|
+
@internal
|
|
943
|
+
*/
|
|
751
944
|
constructor(node,
|
|
752
|
-
|
|
945
|
+
/**
|
|
946
|
+
@internal
|
|
947
|
+
*/
|
|
753
948
|
mode = 0) {
|
|
754
949
|
this.mode = mode;
|
|
755
|
-
|
|
950
|
+
/**
|
|
951
|
+
@internal
|
|
952
|
+
*/
|
|
756
953
|
this.buffer = null;
|
|
757
954
|
this.stack = [];
|
|
758
|
-
|
|
955
|
+
/**
|
|
956
|
+
@internal
|
|
957
|
+
*/
|
|
759
958
|
this.index = 0;
|
|
760
959
|
this.bufferNode = null;
|
|
761
960
|
if (node instanceof TreeNode) {
|
|
@@ -797,11 +996,15 @@ class TreeCursor {
|
|
|
797
996
|
this.buffer = node.context;
|
|
798
997
|
return this.yieldBuf(node.index, node.type);
|
|
799
998
|
}
|
|
800
|
-
|
|
999
|
+
/**
|
|
1000
|
+
@internal
|
|
1001
|
+
*/
|
|
801
1002
|
toString() {
|
|
802
1003
|
return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString();
|
|
803
1004
|
}
|
|
804
|
-
|
|
1005
|
+
/**
|
|
1006
|
+
@internal
|
|
1007
|
+
*/
|
|
805
1008
|
enterChild(dir, pos, side) {
|
|
806
1009
|
if (!this.buffer)
|
|
807
1010
|
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
@@ -812,26 +1015,38 @@ class TreeCursor {
|
|
|
812
1015
|
this.stack.push(this.index);
|
|
813
1016
|
return this.yieldBuf(index);
|
|
814
1017
|
}
|
|
815
|
-
|
|
816
|
-
|
|
1018
|
+
/**
|
|
1019
|
+
Move the cursor to this node's first child. When this returns
|
|
1020
|
+
false, the node has no child, and the cursor has not been moved.
|
|
1021
|
+
*/
|
|
817
1022
|
firstChild() { return this.enterChild(1, 0, 4 /* Side.DontCare */); }
|
|
818
|
-
|
|
1023
|
+
/**
|
|
1024
|
+
Move the cursor to this node's last child.
|
|
1025
|
+
*/
|
|
819
1026
|
lastChild() { return this.enterChild(-1, 0, 4 /* Side.DontCare */); }
|
|
820
|
-
|
|
1027
|
+
/**
|
|
1028
|
+
Move the cursor to the first child that ends after `pos`.
|
|
1029
|
+
*/
|
|
821
1030
|
childAfter(pos) { return this.enterChild(1, pos, 2 /* Side.After */); }
|
|
822
|
-
|
|
1031
|
+
/**
|
|
1032
|
+
Move to the last child that starts before `pos`.
|
|
1033
|
+
*/
|
|
823
1034
|
childBefore(pos) { return this.enterChild(-1, pos, -2 /* Side.Before */); }
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1035
|
+
/**
|
|
1036
|
+
Move the cursor to the child around `pos`. If side is -1 the
|
|
1037
|
+
child may end at that position, when 1 it may start there. This
|
|
1038
|
+
will also enter [overlaid](#common.MountedTree.overlay)
|
|
1039
|
+
[mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
1040
|
+
set to false.
|
|
1041
|
+
*/
|
|
829
1042
|
enter(pos, side, mode = this.mode) {
|
|
830
1043
|
if (!this.buffer)
|
|
831
1044
|
return this.yield(this._tree.enter(pos, side, mode));
|
|
832
1045
|
return mode & exports.IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
833
1046
|
}
|
|
834
|
-
|
|
1047
|
+
/**
|
|
1048
|
+
Move to the node's parent node, if this isn't the top node.
|
|
1049
|
+
*/
|
|
835
1050
|
parent() {
|
|
836
1051
|
if (!this.buffer)
|
|
837
1052
|
return this.yieldNode((this.mode & exports.IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
@@ -841,7 +1056,9 @@ class TreeCursor {
|
|
|
841
1056
|
this.buffer = null;
|
|
842
1057
|
return this.yieldNode(parent);
|
|
843
1058
|
}
|
|
844
|
-
|
|
1059
|
+
/**
|
|
1060
|
+
@internal
|
|
1061
|
+
*/
|
|
845
1062
|
sibling(dir) {
|
|
846
1063
|
if (!this.buffer)
|
|
847
1064
|
return !this._tree._parent ? false
|
|
@@ -860,9 +1077,13 @@ class TreeCursor {
|
|
|
860
1077
|
}
|
|
861
1078
|
return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4 /* Side.DontCare */, this.mode)) : false;
|
|
862
1079
|
}
|
|
863
|
-
|
|
1080
|
+
/**
|
|
1081
|
+
Move to this node's next sibling, if any.
|
|
1082
|
+
*/
|
|
864
1083
|
nextSibling() { return this.sibling(1); }
|
|
865
|
-
|
|
1084
|
+
/**
|
|
1085
|
+
Move to this node's previous sibling, if any.
|
|
1086
|
+
*/
|
|
866
1087
|
prevSibling() { return this.sibling(-1); }
|
|
867
1088
|
atLastNode(dir) {
|
|
868
1089
|
let index, parent, { buffer } = this;
|
|
@@ -904,20 +1125,26 @@ class TreeCursor {
|
|
|
904
1125
|
return false;
|
|
905
1126
|
}
|
|
906
1127
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1128
|
+
/**
|
|
1129
|
+
Move to the next node in a
|
|
1130
|
+
[pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
|
|
1131
|
+
traversal, going from a node to its first child or, if the
|
|
1132
|
+
current node is empty or `enter` is false, its next sibling or
|
|
1133
|
+
the next sibling of the first parent node that has one.
|
|
1134
|
+
*/
|
|
912
1135
|
next(enter = true) { return this.move(1, enter); }
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1136
|
+
/**
|
|
1137
|
+
Move to the next node in a last-to-first pre-order traveral. A
|
|
1138
|
+
node is followed by its last child or, if it has none, its
|
|
1139
|
+
previous sibling or the previous sibling of the first parent
|
|
1140
|
+
node that has one.
|
|
1141
|
+
*/
|
|
917
1142
|
prev(enter = true) { return this.move(-1, enter); }
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1143
|
+
/**
|
|
1144
|
+
Move the cursor to the innermost node that covers `pos`. If
|
|
1145
|
+
`side` is -1, it will enter nodes that end at `pos`. If it is 1,
|
|
1146
|
+
it will enter nodes that start at `pos`.
|
|
1147
|
+
*/
|
|
921
1148
|
moveTo(pos, side = 0) {
|
|
922
1149
|
// Move up to a node that actually holds the position, if possible
|
|
923
1150
|
while (this.from == this.to ||
|
|
@@ -929,8 +1156,10 @@ class TreeCursor {
|
|
|
929
1156
|
while (this.enterChild(1, pos, side)) { }
|
|
930
1157
|
return this;
|
|
931
1158
|
}
|
|
932
|
-
|
|
933
|
-
|
|
1159
|
+
/**
|
|
1160
|
+
Get a [syntax node](#common.SyntaxNode) at the cursor's current
|
|
1161
|
+
position.
|
|
1162
|
+
*/
|
|
934
1163
|
get node() {
|
|
935
1164
|
if (!this.buffer)
|
|
936
1165
|
return this._tree;
|
|
@@ -952,16 +1181,20 @@ class TreeCursor {
|
|
|
952
1181
|
result = new BufferNode(this.buffer, result, this.stack[i]);
|
|
953
1182
|
return this.bufferNode = new BufferNode(this.buffer, result, this.index);
|
|
954
1183
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1184
|
+
/**
|
|
1185
|
+
Get the [tree](#common.Tree) that represents the current node, if
|
|
1186
|
+
any. Will return null when the node is in a [tree
|
|
1187
|
+
buffer](#common.TreeBuffer).
|
|
1188
|
+
*/
|
|
958
1189
|
get tree() {
|
|
959
1190
|
return this.buffer ? null : this._tree._tree;
|
|
960
1191
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1192
|
+
/**
|
|
1193
|
+
Iterate over the current node and all its descendants, calling
|
|
1194
|
+
`enter` when entering a node and `leave`, if given, when leaving
|
|
1195
|
+
one. When `enter` returns `false`, any children of that node are
|
|
1196
|
+
skipped, and `leave` isn't called for it.
|
|
1197
|
+
*/
|
|
965
1198
|
iterate(enter, leave) {
|
|
966
1199
|
for (let depth = 0;;) {
|
|
967
1200
|
let mustLeave = false;
|
|
@@ -987,9 +1220,11 @@ class TreeCursor {
|
|
|
987
1220
|
}
|
|
988
1221
|
}
|
|
989
1222
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1223
|
+
/**
|
|
1224
|
+
Test whether the current node matches a given context—a sequence
|
|
1225
|
+
of direct parent node names. Empty strings in the context array
|
|
1226
|
+
are treated as wildcards.
|
|
1227
|
+
*/
|
|
993
1228
|
matchContext(context) {
|
|
994
1229
|
if (!this.buffer)
|
|
995
1230
|
return matchNodeContext(this.node, context);
|
|
@@ -1264,9 +1499,11 @@ mkTree) {
|
|
|
1264
1499
|
divide(children, positions, from, to, 0);
|
|
1265
1500
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1266
1501
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1502
|
+
/**
|
|
1503
|
+
Provides a way to associate values with pieces of trees. As long
|
|
1504
|
+
as that part of the tree is reused, the associated values can be
|
|
1505
|
+
retrieved from an updated tree.
|
|
1506
|
+
*/
|
|
1270
1507
|
class NodeWeakMap {
|
|
1271
1508
|
constructor() {
|
|
1272
1509
|
this.map = new WeakMap();
|
|
@@ -1281,57 +1518,77 @@ class NodeWeakMap {
|
|
|
1281
1518
|
let inner = this.map.get(buffer);
|
|
1282
1519
|
return inner && inner.get(index);
|
|
1283
1520
|
}
|
|
1284
|
-
|
|
1521
|
+
/**
|
|
1522
|
+
Set the value for this syntax node.
|
|
1523
|
+
*/
|
|
1285
1524
|
set(node, value) {
|
|
1286
1525
|
if (node instanceof BufferNode)
|
|
1287
1526
|
this.setBuffer(node.context.buffer, node.index, value);
|
|
1288
1527
|
else if (node instanceof TreeNode)
|
|
1289
1528
|
this.map.set(node.tree, value);
|
|
1290
1529
|
}
|
|
1291
|
-
|
|
1530
|
+
/**
|
|
1531
|
+
Retrieve value for this syntax node, if it exists in the map.
|
|
1532
|
+
*/
|
|
1292
1533
|
get(node) {
|
|
1293
1534
|
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1294
1535
|
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1295
1536
|
}
|
|
1296
|
-
|
|
1537
|
+
/**
|
|
1538
|
+
Set the value for the node that a cursor currently points to.
|
|
1539
|
+
*/
|
|
1297
1540
|
cursorSet(cursor, value) {
|
|
1298
1541
|
if (cursor.buffer)
|
|
1299
1542
|
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1300
1543
|
else
|
|
1301
1544
|
this.map.set(cursor.tree, value);
|
|
1302
1545
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1546
|
+
/**
|
|
1547
|
+
Retrieve the value for the node that a cursor currently points
|
|
1548
|
+
to.
|
|
1549
|
+
*/
|
|
1305
1550
|
cursorGet(cursor) {
|
|
1306
1551
|
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1307
1552
|
}
|
|
1308
1553
|
}
|
|
1309
1554
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1555
|
+
/**
|
|
1556
|
+
Tree fragments are used during [incremental
|
|
1557
|
+
parsing](#common.Parser.startParse) to track parts of old trees
|
|
1558
|
+
that can be reused in a new parse. An array of fragments is used
|
|
1559
|
+
to track regions of an old tree whose nodes might be reused in new
|
|
1560
|
+
parses. Use the static
|
|
1561
|
+
[`applyChanges`](#common.TreeFragment^applyChanges) method to
|
|
1562
|
+
update fragments for document changes.
|
|
1563
|
+
*/
|
|
1317
1564
|
class TreeFragment {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1565
|
+
/**
|
|
1566
|
+
Construct a tree fragment. You'll usually want to use
|
|
1567
|
+
[`addTree`](#common.TreeFragment^addTree) and
|
|
1568
|
+
[`applyChanges`](#common.TreeFragment^applyChanges) instead of
|
|
1569
|
+
calling this directly.
|
|
1570
|
+
*/
|
|
1322
1571
|
constructor(
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1572
|
+
/**
|
|
1573
|
+
The start of the unchanged range pointed to by this fragment.
|
|
1574
|
+
This refers to an offset in the _updated_ document (as opposed
|
|
1575
|
+
to the original tree).
|
|
1576
|
+
*/
|
|
1326
1577
|
from,
|
|
1327
|
-
|
|
1578
|
+
/**
|
|
1579
|
+
The end of the unchanged range.
|
|
1580
|
+
*/
|
|
1328
1581
|
to,
|
|
1329
|
-
|
|
1582
|
+
/**
|
|
1583
|
+
The tree that this fragment is based on.
|
|
1584
|
+
*/
|
|
1330
1585
|
tree,
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1586
|
+
/**
|
|
1587
|
+
The offset between the fragment's tree and the document that
|
|
1588
|
+
this fragment can be used against. Add this when going from
|
|
1589
|
+
document to tree positions, subtract it to go from tree to
|
|
1590
|
+
document positions.
|
|
1591
|
+
*/
|
|
1335
1592
|
offset, openStart = false, openEnd = false) {
|
|
1336
1593
|
this.from = from;
|
|
1337
1594
|
this.to = to;
|
|
@@ -1339,20 +1596,26 @@ class TreeFragment {
|
|
|
1339
1596
|
this.offset = offset;
|
|
1340
1597
|
this.open = (openStart ? 1 /* Open.Start */ : 0) | (openEnd ? 2 /* Open.End */ : 0);
|
|
1341
1598
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1599
|
+
/**
|
|
1600
|
+
Whether the start of the fragment represents the start of a
|
|
1601
|
+
parse, or the end of a change. (In the second case, it may not
|
|
1602
|
+
be safe to reuse some nodes at the start, depending on the
|
|
1603
|
+
parsing algorithm.)
|
|
1604
|
+
*/
|
|
1346
1605
|
get openStart() { return (this.open & 1 /* Open.Start */) > 0; }
|
|
1347
|
-
|
|
1348
|
-
|
|
1606
|
+
/**
|
|
1607
|
+
Whether the end of the fragment represents the end of a
|
|
1608
|
+
full-document parse, or the start of a change.
|
|
1609
|
+
*/
|
|
1349
1610
|
get openEnd() { return (this.open & 2 /* Open.End */) > 0; }
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1611
|
+
/**
|
|
1612
|
+
Create a set of fragments from a freshly parsed tree, or update
|
|
1613
|
+
an existing set of fragments by replacing the ones that overlap
|
|
1614
|
+
with a tree with content from the new tree. When `partial` is
|
|
1615
|
+
true, the parse is treated as incomplete, and the resulting
|
|
1616
|
+
fragment has [`openEnd`](#common.TreeFragment.openEnd) set to
|
|
1617
|
+
true.
|
|
1618
|
+
*/
|
|
1356
1619
|
static addTree(tree, fragments = [], partial = false) {
|
|
1357
1620
|
let result = [new TreeFragment(0, tree.length, tree, 0, false, partial)];
|
|
1358
1621
|
for (let f of fragments)
|
|
@@ -1360,9 +1623,11 @@ class TreeFragment {
|
|
|
1360
1623
|
result.push(f);
|
|
1361
1624
|
return result;
|
|
1362
1625
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1626
|
+
/**
|
|
1627
|
+
Apply a set of edits to an array of fragments, removing or
|
|
1628
|
+
splitting fragments as necessary to remove edited ranges, and
|
|
1629
|
+
adjusting offsets for fragments that moved.
|
|
1630
|
+
*/
|
|
1366
1631
|
static applyChanges(fragments, changes, minGap = 128) {
|
|
1367
1632
|
if (!changes.length)
|
|
1368
1633
|
return fragments;
|
|
@@ -1392,23 +1657,29 @@ class TreeFragment {
|
|
|
1392
1657
|
return result;
|
|
1393
1658
|
}
|
|
1394
1659
|
}
|
|
1395
|
-
|
|
1660
|
+
/**
|
|
1661
|
+
A superclass that parsers should extend.
|
|
1662
|
+
*/
|
|
1396
1663
|
class Parser {
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1664
|
+
/**
|
|
1665
|
+
Start a parse, returning a [partial parse](#common.PartialParse)
|
|
1666
|
+
object. [`fragments`](#common.TreeFragment) can be passed in to
|
|
1667
|
+
make the parse incremental.
|
|
1668
|
+
|
|
1669
|
+
By default, the entire input is parsed. You can pass `ranges`,
|
|
1670
|
+
which should be a sorted array of non-empty, non-overlapping
|
|
1671
|
+
ranges, to parse only those ranges. The tree returned in that
|
|
1672
|
+
case will start at `ranges[0].from`.
|
|
1673
|
+
*/
|
|
1405
1674
|
startParse(input, fragments, ranges) {
|
|
1406
1675
|
if (typeof input == "string")
|
|
1407
1676
|
input = new StringInput(input);
|
|
1408
1677
|
ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map(r => new Range(r.from, r.to)) : [new Range(0, 0)];
|
|
1409
1678
|
return this.createParse(input, fragments || [], ranges);
|
|
1410
1679
|
}
|
|
1411
|
-
|
|
1680
|
+
/**
|
|
1681
|
+
Run a full parse, returning the resulting tree.
|
|
1682
|
+
*/
|
|
1412
1683
|
parse(input, fragments, ranges) {
|
|
1413
1684
|
let parse = this.startParse(input, fragments, ranges);
|
|
1414
1685
|
for (;;) {
|
|
@@ -1428,11 +1699,13 @@ class StringInput {
|
|
|
1428
1699
|
read(from, to) { return this.string.slice(from, to); }
|
|
1429
1700
|
}
|
|
1430
1701
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1702
|
+
/**
|
|
1703
|
+
Create a parse wrapper that, after the inner parse completes,
|
|
1704
|
+
scans its tree for mixed language regions with the `nest`
|
|
1705
|
+
function, runs the resulting [inner parses](#common.NestedParse),
|
|
1706
|
+
and then [mounts](#common.NodeProp^mounted) their results onto the
|
|
1707
|
+
tree.
|
|
1708
|
+
*/
|
|
1436
1709
|
function parseMixed(nest) {
|
|
1437
1710
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1438
1711
|
}
|