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