@lezer/common 1.0.2 → 1.0.4
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/LICENSE +1 -1
- package/dist/index.cjs +512 -285
- package/dist/index.d.cts +1115 -0
- package/dist/index.d.ts +1115 -3
- package/dist/index.js +512 -283
- package/package.json +6 -11
- 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,8 @@
|
|
|
1
1
|
// FIXME profile adding a per-Tree TreeNode cache, validating it by
|
|
2
2
|
// parent pointer
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
The default maximum length of a `TreeBuffer` node.
|
|
5
|
+
*/
|
|
4
6
|
const DefaultBufferLength = 1024;
|
|
5
7
|
let nextPropID = 0;
|
|
6
8
|
class Range {
|
|
@@ -9,11 +11,15 @@ class Range {
|
|
|
9
11
|
this.to = to;
|
|
10
12
|
}
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
+
*/
|
|
15
19
|
class NodeProp {
|
|
16
|
-
|
|
20
|
+
/**
|
|
21
|
+
Create a new node prop type.
|
|
22
|
+
*/
|
|
17
23
|
constructor(config = {}) {
|
|
18
24
|
this.id = nextPropID++;
|
|
19
25
|
this.perNode = !!config.perNode;
|
|
@@ -21,13 +27,15 @@ class NodeProp {
|
|
|
21
27
|
throw new Error("This node type doesn't define a deserialize function");
|
|
22
28
|
});
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
+
*/
|
|
31
39
|
add(match) {
|
|
32
40
|
if (this.perNode)
|
|
33
41
|
throw new RangeError("Can't add per-node props to node types");
|
|
@@ -39,48 +47,68 @@ class NodeProp {
|
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
+
*/
|
|
46
56
|
NodeProp.closedBy = new NodeProp({ deserialize: str => str.split(" ") });
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
+
*/
|
|
50
62
|
NodeProp.openedBy = new NodeProp({ deserialize: str => str.split(" ") });
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
*/
|
|
54
68
|
NodeProp.group = new NodeProp({ deserialize: str => str.split(" ") });
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
*/
|
|
58
74
|
NodeProp.contextHash = new NodeProp({ perNode: true });
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
+
*/
|
|
63
81
|
NodeProp.lookAhead = new NodeProp({ perNode: true });
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
*/
|
|
67
87
|
NodeProp.mounted = new NodeProp({ perNode: true });
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
+
*/
|
|
71
93
|
class MountedTree {
|
|
72
94
|
constructor(
|
|
73
|
-
|
|
95
|
+
/**
|
|
96
|
+
The inner tree.
|
|
97
|
+
*/
|
|
74
98
|
tree,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
+
*/
|
|
82
108
|
overlay,
|
|
83
|
-
|
|
109
|
+
/**
|
|
110
|
+
The parser used to create this subtree.
|
|
111
|
+
*/
|
|
84
112
|
parser) {
|
|
85
113
|
this.tree = tree;
|
|
86
114
|
this.overlay = overlay;
|
|
@@ -88,28 +116,42 @@ class MountedTree {
|
|
|
88
116
|
}
|
|
89
117
|
}
|
|
90
118
|
const noProps = Object.create(null);
|
|
91
|
-
|
|
119
|
+
/**
|
|
120
|
+
Each node in a syntax tree has a node type associated with it.
|
|
121
|
+
*/
|
|
92
122
|
class NodeType {
|
|
93
|
-
|
|
123
|
+
/**
|
|
124
|
+
@internal
|
|
125
|
+
*/
|
|
94
126
|
constructor(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
/**
|
|
128
|
+
The name of the node type. Not necessarily unique, but if the
|
|
129
|
+
grammar was written properly, different node types with the
|
|
130
|
+
same name within a node set should play the same semantic
|
|
131
|
+
role.
|
|
132
|
+
*/
|
|
99
133
|
name,
|
|
100
|
-
|
|
134
|
+
/**
|
|
135
|
+
@internal
|
|
136
|
+
*/
|
|
101
137
|
props,
|
|
102
|
-
|
|
103
|
-
|
|
138
|
+
/**
|
|
139
|
+
The id of this node in its set. Corresponds to the term ids
|
|
140
|
+
used in the parser.
|
|
141
|
+
*/
|
|
104
142
|
id,
|
|
105
|
-
|
|
143
|
+
/**
|
|
144
|
+
@internal
|
|
145
|
+
*/
|
|
106
146
|
flags = 0) {
|
|
107
147
|
this.name = name;
|
|
108
148
|
this.props = props;
|
|
109
149
|
this.id = id;
|
|
110
150
|
this.flags = flags;
|
|
111
151
|
}
|
|
112
|
-
|
|
152
|
+
/**
|
|
153
|
+
Define a node type.
|
|
154
|
+
*/
|
|
113
155
|
static define(spec) {
|
|
114
156
|
let props = spec.props && spec.props.length ? Object.create(null) : noProps;
|
|
115
157
|
let flags = (spec.top ? 1 /* NodeFlag.Top */ : 0) | (spec.skipped ? 2 /* NodeFlag.Skipped */ : 0) |
|
|
@@ -127,20 +169,32 @@ class NodeType {
|
|
|
127
169
|
}
|
|
128
170
|
return type;
|
|
129
171
|
}
|
|
130
|
-
|
|
131
|
-
|
|
172
|
+
/**
|
|
173
|
+
Retrieves a node prop for this type. Will return `undefined` if
|
|
174
|
+
the prop isn't present on this node.
|
|
175
|
+
*/
|
|
132
176
|
prop(prop) { return this.props[prop.id]; }
|
|
133
|
-
|
|
177
|
+
/**
|
|
178
|
+
True when this is the top node of a grammar.
|
|
179
|
+
*/
|
|
134
180
|
get isTop() { return (this.flags & 1 /* NodeFlag.Top */) > 0; }
|
|
135
|
-
|
|
181
|
+
/**
|
|
182
|
+
True when this node is produced by a skip rule.
|
|
183
|
+
*/
|
|
136
184
|
get isSkipped() { return (this.flags & 2 /* NodeFlag.Skipped */) > 0; }
|
|
137
|
-
|
|
185
|
+
/**
|
|
186
|
+
Indicates whether this is an error node.
|
|
187
|
+
*/
|
|
138
188
|
get isError() { return (this.flags & 4 /* NodeFlag.Error */) > 0; }
|
|
139
|
-
|
|
140
|
-
|
|
189
|
+
/**
|
|
190
|
+
When true, this node type doesn't correspond to a user-declared
|
|
191
|
+
named node, for example because it is used to cache repetition.
|
|
192
|
+
*/
|
|
141
193
|
get isAnonymous() { return (this.flags & 8 /* NodeFlag.Anonymous */) > 0; }
|
|
142
|
-
|
|
143
|
-
|
|
194
|
+
/**
|
|
195
|
+
Returns true when this node's name or one of its
|
|
196
|
+
[groups](#common.NodeProp^group) matches the given string.
|
|
197
|
+
*/
|
|
144
198
|
is(name) {
|
|
145
199
|
if (typeof name == 'string') {
|
|
146
200
|
if (this.name == name)
|
|
@@ -150,12 +204,14 @@ class NodeType {
|
|
|
150
204
|
}
|
|
151
205
|
return this.id == name;
|
|
152
206
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
207
|
+
/**
|
|
208
|
+
Create a function from node types to arbitrary values by
|
|
209
|
+
specifying an object whose property names are node or
|
|
210
|
+
[group](#common.NodeProp^group) names. Often useful with
|
|
211
|
+
[`NodeProp.add`](#common.NodeProp.add). You can put multiple
|
|
212
|
+
names, separated by spaces, in a single property name to map
|
|
213
|
+
multiple node names to a single value.
|
|
214
|
+
*/
|
|
159
215
|
static match(map) {
|
|
160
216
|
let direct = Object.create(null);
|
|
161
217
|
for (let prop in map)
|
|
@@ -170,29 +226,39 @@ class NodeType {
|
|
|
170
226
|
};
|
|
171
227
|
}
|
|
172
228
|
}
|
|
173
|
-
|
|
229
|
+
/**
|
|
230
|
+
An empty dummy node type to use when no actual type is available.
|
|
231
|
+
*/
|
|
174
232
|
NodeType.none = new NodeType("", Object.create(null), 0, 8 /* NodeFlag.Anonymous */);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
233
|
+
/**
|
|
234
|
+
A node set holds a collection of node types. It is used to
|
|
235
|
+
compactly represent trees by storing their type ids, rather than a
|
|
236
|
+
full pointer to the type object, in a numeric array. Each parser
|
|
237
|
+
[has](#lr.LRParser.nodeSet) a node set, and [tree
|
|
238
|
+
buffers](#common.TreeBuffer) can only store collections of nodes
|
|
239
|
+
from the same set. A set can have a maximum of 2**16 (65536) node
|
|
240
|
+
types in it, so that the ids fit into 16-bit typed array slots.
|
|
241
|
+
*/
|
|
182
242
|
class NodeSet {
|
|
183
|
-
|
|
184
|
-
|
|
243
|
+
/**
|
|
244
|
+
Create a set with the given types. The `id` property of each
|
|
245
|
+
type should correspond to its position within the array.
|
|
246
|
+
*/
|
|
185
247
|
constructor(
|
|
186
|
-
|
|
248
|
+
/**
|
|
249
|
+
The node types in this set, by id.
|
|
250
|
+
*/
|
|
187
251
|
types) {
|
|
188
252
|
this.types = types;
|
|
189
253
|
for (let i = 0; i < types.length; i++)
|
|
190
254
|
if (types[i].id != i)
|
|
191
255
|
throw new RangeError("Node type ids should correspond to array positions when creating a node set");
|
|
192
256
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
257
|
+
/**
|
|
258
|
+
Create a copy of this set with some node properties added. The
|
|
259
|
+
arguments to this method can be created with
|
|
260
|
+
[`NodeProp.add`](#common.NodeProp.add).
|
|
261
|
+
*/
|
|
196
262
|
extend(...props) {
|
|
197
263
|
let newTypes = [];
|
|
198
264
|
for (let type of this.types) {
|
|
@@ -211,61 +277,87 @@ class NodeSet {
|
|
|
211
277
|
}
|
|
212
278
|
}
|
|
213
279
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
214
|
-
|
|
215
|
-
|
|
280
|
+
/**
|
|
281
|
+
Options that control iteration. Can be combined with the `|`
|
|
282
|
+
operator to enable multiple ones.
|
|
283
|
+
*/
|
|
216
284
|
var IterMode;
|
|
217
285
|
(function (IterMode) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
286
|
+
/**
|
|
287
|
+
When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
288
|
+
objects, not nodes packed into
|
|
289
|
+
[`TreeBuffer`](#common.TreeBuffer)s.
|
|
290
|
+
*/
|
|
221
291
|
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
292
|
+
/**
|
|
293
|
+
Enable this to make iteration include anonymous nodes (such as
|
|
294
|
+
the nodes that wrap repeated grammar constructs into a balanced
|
|
295
|
+
tree).
|
|
296
|
+
*/
|
|
225
297
|
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
298
|
+
/**
|
|
299
|
+
By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
300
|
+
replace their base node in iteration. Enable this to ignore them
|
|
301
|
+
instead.
|
|
302
|
+
*/
|
|
229
303
|
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
304
|
+
/**
|
|
305
|
+
This option only applies in
|
|
306
|
+
[`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
307
|
+
library to not enter mounted overlays if one covers the given
|
|
308
|
+
position.
|
|
309
|
+
*/
|
|
234
310
|
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
235
311
|
})(IterMode || (IterMode = {}));
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
312
|
+
/**
|
|
313
|
+
A piece of syntax tree. There are two ways to approach these
|
|
314
|
+
trees: the way they are actually stored in memory, and the
|
|
315
|
+
convenient way.
|
|
316
|
+
|
|
317
|
+
Syntax trees are stored as a tree of `Tree` and `TreeBuffer`
|
|
318
|
+
objects. By packing detail information into `TreeBuffer` leaf
|
|
319
|
+
nodes, the representation is made a lot more memory-efficient.
|
|
320
|
+
|
|
321
|
+
However, when you want to actually work with tree nodes, this
|
|
322
|
+
representation is very awkward, so most client code will want to
|
|
323
|
+
use the [`TreeCursor`](#common.TreeCursor) or
|
|
324
|
+
[`SyntaxNode`](#common.SyntaxNode) interface instead, which provides
|
|
325
|
+
a view on some part of this data structure, and can be used to
|
|
326
|
+
move around to adjacent nodes.
|
|
327
|
+
*/
|
|
250
328
|
class Tree {
|
|
251
|
-
|
|
329
|
+
/**
|
|
330
|
+
Construct a new tree. See also [`Tree.build`](#common.Tree^build).
|
|
331
|
+
*/
|
|
252
332
|
constructor(
|
|
253
|
-
|
|
333
|
+
/**
|
|
334
|
+
The type of the top node.
|
|
335
|
+
*/
|
|
254
336
|
type,
|
|
255
|
-
|
|
337
|
+
/**
|
|
338
|
+
This node's child nodes.
|
|
339
|
+
*/
|
|
256
340
|
children,
|
|
257
|
-
|
|
258
|
-
|
|
341
|
+
/**
|
|
342
|
+
The positions (offsets relative to the start of this tree) of
|
|
343
|
+
the children.
|
|
344
|
+
*/
|
|
259
345
|
positions,
|
|
260
|
-
|
|
346
|
+
/**
|
|
347
|
+
The total length of this tree
|
|
348
|
+
*/
|
|
261
349
|
length,
|
|
262
|
-
|
|
350
|
+
/**
|
|
351
|
+
Per-node [node props](#common.NodeProp) to associate with this node.
|
|
352
|
+
*/
|
|
263
353
|
props) {
|
|
264
354
|
this.type = type;
|
|
265
355
|
this.children = children;
|
|
266
356
|
this.positions = positions;
|
|
267
357
|
this.length = length;
|
|
268
|
-
|
|
358
|
+
/**
|
|
359
|
+
@internal
|
|
360
|
+
*/
|
|
269
361
|
this.props = null;
|
|
270
362
|
if (props && props.length) {
|
|
271
363
|
this.props = Object.create(null);
|
|
@@ -273,7 +365,9 @@ class Tree {
|
|
|
273
365
|
this.props[typeof prop == "number" ? prop : prop.id] = value;
|
|
274
366
|
}
|
|
275
367
|
}
|
|
276
|
-
|
|
368
|
+
/**
|
|
369
|
+
@internal
|
|
370
|
+
*/
|
|
277
371
|
toString() {
|
|
278
372
|
let mounted = this.prop(NodeProp.mounted);
|
|
279
373
|
if (mounted && !mounted.overlay)
|
|
@@ -291,15 +385,19 @@ class Tree {
|
|
|
291
385
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
292
386
|
(children.length ? "(" + children + ")" : "");
|
|
293
387
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
388
|
+
/**
|
|
389
|
+
Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
390
|
+
the tree. Mode can be used to [control](#common.IterMode) which
|
|
391
|
+
nodes the cursor visits.
|
|
392
|
+
*/
|
|
297
393
|
cursor(mode = 0) {
|
|
298
394
|
return new TreeCursor(this.topNode, mode);
|
|
299
395
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
396
|
+
/**
|
|
397
|
+
Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
398
|
+
at the given position and side (see
|
|
399
|
+
[`moveTo`](#common.TreeCursor.moveTo).
|
|
400
|
+
*/
|
|
303
401
|
cursorAt(pos, side = 0, mode = 0) {
|
|
304
402
|
let scope = CachedNode.get(this) || this.topNode;
|
|
305
403
|
let cursor = new TreeCursor(scope);
|
|
@@ -307,51 +405,60 @@ class Tree {
|
|
|
307
405
|
CachedNode.set(this, cursor._tree);
|
|
308
406
|
return cursor;
|
|
309
407
|
}
|
|
310
|
-
|
|
311
|
-
|
|
408
|
+
/**
|
|
409
|
+
Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
410
|
+
tree.
|
|
411
|
+
*/
|
|
312
412
|
get topNode() {
|
|
313
413
|
return new TreeNode(this, 0, 0, null);
|
|
314
414
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
415
|
+
/**
|
|
416
|
+
Get the [syntax node](#common.SyntaxNode) at the given position.
|
|
417
|
+
If `side` is -1, this will move into nodes that end at the
|
|
418
|
+
position. If 1, it'll move into nodes that start at the
|
|
419
|
+
position. With 0, it'll only enter nodes that cover the position
|
|
420
|
+
from both sides.
|
|
421
|
+
|
|
422
|
+
Note that this will not enter
|
|
423
|
+
[overlays](#common.MountedTree.overlay), and you often want
|
|
424
|
+
[`resolveInner`](#common.Tree.resolveInner) instead.
|
|
425
|
+
*/
|
|
324
426
|
resolve(pos, side = 0) {
|
|
325
427
|
let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
|
|
326
428
|
CachedNode.set(this, node);
|
|
327
429
|
return node;
|
|
328
430
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
431
|
+
/**
|
|
432
|
+
Like [`resolve`](#common.Tree.resolve), but will enter
|
|
433
|
+
[overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
|
|
434
|
+
pointing into the innermost overlaid tree at the given position
|
|
435
|
+
(with parent links going through all parent structure, including
|
|
436
|
+
the host trees).
|
|
437
|
+
*/
|
|
334
438
|
resolveInner(pos, side = 0) {
|
|
335
439
|
let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
|
|
336
440
|
CachedInnerNode.set(this, node);
|
|
337
441
|
return node;
|
|
338
442
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
443
|
+
/**
|
|
444
|
+
Iterate over the tree and its children, calling `enter` for any
|
|
445
|
+
node that touches the `from`/`to` region (if given) before
|
|
446
|
+
running over such a node's children, and `leave` (if given) when
|
|
447
|
+
leaving the node. When `enter` returns `false`, that node will
|
|
448
|
+
not have its children iterated over (or `leave` called).
|
|
449
|
+
*/
|
|
344
450
|
iterate(spec) {
|
|
345
451
|
let { enter, leave, from = 0, to = this.length } = spec;
|
|
346
|
-
|
|
452
|
+
let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0;
|
|
453
|
+
for (let c = this.cursor(mode | IterMode.IncludeAnonymous);;) {
|
|
347
454
|
let entered = false;
|
|
348
|
-
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c) !== false)) {
|
|
455
|
+
if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) {
|
|
349
456
|
if (c.firstChild())
|
|
350
457
|
continue;
|
|
351
458
|
entered = true;
|
|
352
459
|
}
|
|
353
460
|
for (;;) {
|
|
354
|
-
if (entered && leave && !c.type.isAnonymous)
|
|
461
|
+
if (entered && leave && (anon || !c.type.isAnonymous))
|
|
355
462
|
leave(c);
|
|
356
463
|
if (c.nextSibling())
|
|
357
464
|
break;
|
|
@@ -361,14 +468,18 @@ class Tree {
|
|
|
361
468
|
}
|
|
362
469
|
}
|
|
363
470
|
}
|
|
364
|
-
|
|
365
|
-
|
|
471
|
+
/**
|
|
472
|
+
Get the value of the given [node prop](#common.NodeProp) for this
|
|
473
|
+
node. Works with both per-node and per-type props.
|
|
474
|
+
*/
|
|
366
475
|
prop(prop) {
|
|
367
476
|
return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : undefined;
|
|
368
477
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
478
|
+
/**
|
|
479
|
+
Returns the node's [per-node props](#common.NodeProp.perNode) in a
|
|
480
|
+
format that can be passed to the [`Tree`](#common.Tree)
|
|
481
|
+
constructor.
|
|
482
|
+
*/
|
|
372
483
|
get propValues() {
|
|
373
484
|
let result = [];
|
|
374
485
|
if (this.props)
|
|
@@ -376,18 +487,24 @@ class Tree {
|
|
|
376
487
|
result.push([+id, this.props[id]]);
|
|
377
488
|
return result;
|
|
378
489
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
490
|
+
/**
|
|
491
|
+
Balance the direct children of this tree, producing a copy of
|
|
492
|
+
which may have children grouped into subtrees with type
|
|
493
|
+
[`NodeType.none`](#common.NodeType^none).
|
|
494
|
+
*/
|
|
382
495
|
balance(config = {}) {
|
|
383
496
|
return this.children.length <= 8 /* Balance.BranchFactor */ ? this :
|
|
384
497
|
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)));
|
|
385
498
|
}
|
|
386
|
-
|
|
387
|
-
|
|
499
|
+
/**
|
|
500
|
+
Build a tree from a postfix-ordered buffer of node information,
|
|
501
|
+
or a cursor over such a buffer.
|
|
502
|
+
*/
|
|
388
503
|
static build(data) { return buildTree(data); }
|
|
389
504
|
}
|
|
390
|
-
|
|
505
|
+
/**
|
|
506
|
+
The empty tree
|
|
507
|
+
*/
|
|
391
508
|
Tree.empty = new Tree(NodeType.none, [], [], 0);
|
|
392
509
|
class FlatBufferCursor {
|
|
393
510
|
constructor(buffer, index) {
|
|
@@ -402,26 +519,40 @@ class FlatBufferCursor {
|
|
|
402
519
|
next() { this.index -= 4; }
|
|
403
520
|
fork() { return new FlatBufferCursor(this.buffer, this.index); }
|
|
404
521
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
522
|
+
/**
|
|
523
|
+
Tree buffers contain (type, start, end, endIndex) quads for each
|
|
524
|
+
node. In such a buffer, nodes are stored in prefix order (parents
|
|
525
|
+
before children, with the endIndex of the parent indicating which
|
|
526
|
+
children belong to it).
|
|
527
|
+
*/
|
|
409
528
|
class TreeBuffer {
|
|
410
|
-
|
|
529
|
+
/**
|
|
530
|
+
Create a tree buffer.
|
|
531
|
+
*/
|
|
411
532
|
constructor(
|
|
412
|
-
|
|
533
|
+
/**
|
|
534
|
+
The buffer's content.
|
|
535
|
+
*/
|
|
413
536
|
buffer,
|
|
414
|
-
|
|
537
|
+
/**
|
|
538
|
+
The total length of the group of nodes in the buffer.
|
|
539
|
+
*/
|
|
415
540
|
length,
|
|
416
|
-
|
|
541
|
+
/**
|
|
542
|
+
The node set used in this buffer.
|
|
543
|
+
*/
|
|
417
544
|
set) {
|
|
418
545
|
this.buffer = buffer;
|
|
419
546
|
this.length = length;
|
|
420
547
|
this.set = set;
|
|
421
548
|
}
|
|
422
|
-
|
|
549
|
+
/**
|
|
550
|
+
@internal
|
|
551
|
+
*/
|
|
423
552
|
get type() { return NodeType.none; }
|
|
424
|
-
|
|
553
|
+
/**
|
|
554
|
+
@internal
|
|
555
|
+
*/
|
|
425
556
|
toString() {
|
|
426
557
|
let result = [];
|
|
427
558
|
for (let index = 0; index < this.buffer.length;) {
|
|
@@ -430,7 +561,9 @@ class TreeBuffer {
|
|
|
430
561
|
}
|
|
431
562
|
return result.join(",");
|
|
432
563
|
}
|
|
433
|
-
|
|
564
|
+
/**
|
|
565
|
+
@internal
|
|
566
|
+
*/
|
|
434
567
|
childString(index) {
|
|
435
568
|
let id = this.buffer[index], endIndex = this.buffer[index + 3];
|
|
436
569
|
let type = this.set.types[id], result = type.name;
|
|
@@ -446,7 +579,9 @@ class TreeBuffer {
|
|
|
446
579
|
}
|
|
447
580
|
return result + "(" + children.join(",") + ")";
|
|
448
581
|
}
|
|
449
|
-
|
|
582
|
+
/**
|
|
583
|
+
@internal
|
|
584
|
+
*/
|
|
450
585
|
findChild(startIndex, endIndex, dir, pos, side) {
|
|
451
586
|
let { buffer } = this, pick = -1;
|
|
452
587
|
for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
|
|
@@ -458,7 +593,9 @@ class TreeBuffer {
|
|
|
458
593
|
}
|
|
459
594
|
return pick;
|
|
460
595
|
}
|
|
461
|
-
|
|
596
|
+
/**
|
|
597
|
+
@internal
|
|
598
|
+
*/
|
|
462
599
|
slice(startI, endI, from) {
|
|
463
600
|
let b = this.buffer;
|
|
464
601
|
let copy = new Uint16Array(endI - startI), len = 0;
|
|
@@ -617,7 +754,9 @@ class TreeNode {
|
|
|
617
754
|
getChildren(type, before = null, after = null) {
|
|
618
755
|
return getChildren(this, type, before, after);
|
|
619
756
|
}
|
|
620
|
-
|
|
757
|
+
/**
|
|
758
|
+
@internal
|
|
759
|
+
*/
|
|
621
760
|
toString() { return this._tree.toString(); }
|
|
622
761
|
get node() { return this; }
|
|
623
762
|
matchContext(context) { return matchNodeContext(this, context); }
|
|
@@ -725,7 +864,9 @@ class BufferNode {
|
|
|
725
864
|
return resolveNode(this, pos, side, true);
|
|
726
865
|
}
|
|
727
866
|
enterUnfinishedNodesBefore(pos) { return enterUnfinishedNodesBefore(this, pos); }
|
|
728
|
-
|
|
867
|
+
/**
|
|
868
|
+
@internal
|
|
869
|
+
*/
|
|
729
870
|
toString() { return this.context.buffer.childString(this.index); }
|
|
730
871
|
getChild(type, before = null, after = null) {
|
|
731
872
|
let r = getChildren(this, type, before, after);
|
|
@@ -737,20 +878,32 @@ class BufferNode {
|
|
|
737
878
|
get node() { return this; }
|
|
738
879
|
matchContext(context) { return matchNodeContext(this, context); }
|
|
739
880
|
}
|
|
740
|
-
|
|
741
|
-
|
|
881
|
+
/**
|
|
882
|
+
A tree cursor object focuses on a given node in a syntax tree, and
|
|
883
|
+
allows you to move to adjacent nodes.
|
|
884
|
+
*/
|
|
742
885
|
class TreeCursor {
|
|
743
|
-
|
|
886
|
+
/**
|
|
887
|
+
Shorthand for `.type.name`.
|
|
888
|
+
*/
|
|
744
889
|
get name() { return this.type.name; }
|
|
745
|
-
|
|
890
|
+
/**
|
|
891
|
+
@internal
|
|
892
|
+
*/
|
|
746
893
|
constructor(node,
|
|
747
|
-
|
|
894
|
+
/**
|
|
895
|
+
@internal
|
|
896
|
+
*/
|
|
748
897
|
mode = 0) {
|
|
749
898
|
this.mode = mode;
|
|
750
|
-
|
|
899
|
+
/**
|
|
900
|
+
@internal
|
|
901
|
+
*/
|
|
751
902
|
this.buffer = null;
|
|
752
903
|
this.stack = [];
|
|
753
|
-
|
|
904
|
+
/**
|
|
905
|
+
@internal
|
|
906
|
+
*/
|
|
754
907
|
this.index = 0;
|
|
755
908
|
this.bufferNode = null;
|
|
756
909
|
if (node instanceof TreeNode) {
|
|
@@ -792,11 +945,15 @@ class TreeCursor {
|
|
|
792
945
|
this.buffer = node.context;
|
|
793
946
|
return this.yieldBuf(node.index, node.type);
|
|
794
947
|
}
|
|
795
|
-
|
|
948
|
+
/**
|
|
949
|
+
@internal
|
|
950
|
+
*/
|
|
796
951
|
toString() {
|
|
797
952
|
return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString();
|
|
798
953
|
}
|
|
799
|
-
|
|
954
|
+
/**
|
|
955
|
+
@internal
|
|
956
|
+
*/
|
|
800
957
|
enterChild(dir, pos, side) {
|
|
801
958
|
if (!this.buffer)
|
|
802
959
|
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
@@ -807,26 +964,38 @@ class TreeCursor {
|
|
|
807
964
|
this.stack.push(this.index);
|
|
808
965
|
return this.yieldBuf(index);
|
|
809
966
|
}
|
|
810
|
-
|
|
811
|
-
|
|
967
|
+
/**
|
|
968
|
+
Move the cursor to this node's first child. When this returns
|
|
969
|
+
false, the node has no child, and the cursor has not been moved.
|
|
970
|
+
*/
|
|
812
971
|
firstChild() { return this.enterChild(1, 0, 4 /* Side.DontCare */); }
|
|
813
|
-
|
|
972
|
+
/**
|
|
973
|
+
Move the cursor to this node's last child.
|
|
974
|
+
*/
|
|
814
975
|
lastChild() { return this.enterChild(-1, 0, 4 /* Side.DontCare */); }
|
|
815
|
-
|
|
976
|
+
/**
|
|
977
|
+
Move the cursor to the first child that ends after `pos`.
|
|
978
|
+
*/
|
|
816
979
|
childAfter(pos) { return this.enterChild(1, pos, 2 /* Side.After */); }
|
|
817
|
-
|
|
980
|
+
/**
|
|
981
|
+
Move to the last child that starts before `pos`.
|
|
982
|
+
*/
|
|
818
983
|
childBefore(pos) { return this.enterChild(-1, pos, -2 /* Side.Before */); }
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
984
|
+
/**
|
|
985
|
+
Move the cursor to the child around `pos`. If side is -1 the
|
|
986
|
+
child may end at that position, when 1 it may start there. This
|
|
987
|
+
will also enter [overlaid](#common.MountedTree.overlay)
|
|
988
|
+
[mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
989
|
+
set to false.
|
|
990
|
+
*/
|
|
824
991
|
enter(pos, side, mode = this.mode) {
|
|
825
992
|
if (!this.buffer)
|
|
826
993
|
return this.yield(this._tree.enter(pos, side, mode));
|
|
827
994
|
return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
828
995
|
}
|
|
829
|
-
|
|
996
|
+
/**
|
|
997
|
+
Move to the node's parent node, if this isn't the top node.
|
|
998
|
+
*/
|
|
830
999
|
parent() {
|
|
831
1000
|
if (!this.buffer)
|
|
832
1001
|
return this.yieldNode((this.mode & IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
@@ -836,7 +1005,9 @@ class TreeCursor {
|
|
|
836
1005
|
this.buffer = null;
|
|
837
1006
|
return this.yieldNode(parent);
|
|
838
1007
|
}
|
|
839
|
-
|
|
1008
|
+
/**
|
|
1009
|
+
@internal
|
|
1010
|
+
*/
|
|
840
1011
|
sibling(dir) {
|
|
841
1012
|
if (!this.buffer)
|
|
842
1013
|
return !this._tree._parent ? false
|
|
@@ -855,9 +1026,13 @@ class TreeCursor {
|
|
|
855
1026
|
}
|
|
856
1027
|
return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4 /* Side.DontCare */, this.mode)) : false;
|
|
857
1028
|
}
|
|
858
|
-
|
|
1029
|
+
/**
|
|
1030
|
+
Move to this node's next sibling, if any.
|
|
1031
|
+
*/
|
|
859
1032
|
nextSibling() { return this.sibling(1); }
|
|
860
|
-
|
|
1033
|
+
/**
|
|
1034
|
+
Move to this node's previous sibling, if any.
|
|
1035
|
+
*/
|
|
861
1036
|
prevSibling() { return this.sibling(-1); }
|
|
862
1037
|
atLastNode(dir) {
|
|
863
1038
|
let index, parent, { buffer } = this;
|
|
@@ -899,20 +1074,26 @@ class TreeCursor {
|
|
|
899
1074
|
return false;
|
|
900
1075
|
}
|
|
901
1076
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1077
|
+
/**
|
|
1078
|
+
Move to the next node in a
|
|
1079
|
+
[pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
|
|
1080
|
+
traversal, going from a node to its first child or, if the
|
|
1081
|
+
current node is empty or `enter` is false, its next sibling or
|
|
1082
|
+
the next sibling of the first parent node that has one.
|
|
1083
|
+
*/
|
|
907
1084
|
next(enter = true) { return this.move(1, enter); }
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1085
|
+
/**
|
|
1086
|
+
Move to the next node in a last-to-first pre-order traveral. A
|
|
1087
|
+
node is followed by its last child or, if it has none, its
|
|
1088
|
+
previous sibling or the previous sibling of the first parent
|
|
1089
|
+
node that has one.
|
|
1090
|
+
*/
|
|
912
1091
|
prev(enter = true) { return this.move(-1, enter); }
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1092
|
+
/**
|
|
1093
|
+
Move the cursor to the innermost node that covers `pos`. If
|
|
1094
|
+
`side` is -1, it will enter nodes that end at `pos`. If it is 1,
|
|
1095
|
+
it will enter nodes that start at `pos`.
|
|
1096
|
+
*/
|
|
916
1097
|
moveTo(pos, side = 0) {
|
|
917
1098
|
// Move up to a node that actually holds the position, if possible
|
|
918
1099
|
while (this.from == this.to ||
|
|
@@ -924,8 +1105,10 @@ class TreeCursor {
|
|
|
924
1105
|
while (this.enterChild(1, pos, side)) { }
|
|
925
1106
|
return this;
|
|
926
1107
|
}
|
|
927
|
-
|
|
928
|
-
|
|
1108
|
+
/**
|
|
1109
|
+
Get a [syntax node](#common.SyntaxNode) at the cursor's current
|
|
1110
|
+
position.
|
|
1111
|
+
*/
|
|
929
1112
|
get node() {
|
|
930
1113
|
if (!this.buffer)
|
|
931
1114
|
return this._tree;
|
|
@@ -947,16 +1130,20 @@ class TreeCursor {
|
|
|
947
1130
|
result = new BufferNode(this.buffer, result, this.stack[i]);
|
|
948
1131
|
return this.bufferNode = new BufferNode(this.buffer, result, this.index);
|
|
949
1132
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1133
|
+
/**
|
|
1134
|
+
Get the [tree](#common.Tree) that represents the current node, if
|
|
1135
|
+
any. Will return null when the node is in a [tree
|
|
1136
|
+
buffer](#common.TreeBuffer).
|
|
1137
|
+
*/
|
|
953
1138
|
get tree() {
|
|
954
1139
|
return this.buffer ? null : this._tree._tree;
|
|
955
1140
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1141
|
+
/**
|
|
1142
|
+
Iterate over the current node and all its descendants, calling
|
|
1143
|
+
`enter` when entering a node and `leave`, if given, when leaving
|
|
1144
|
+
one. When `enter` returns `false`, any children of that node are
|
|
1145
|
+
skipped, and `leave` isn't called for it.
|
|
1146
|
+
*/
|
|
960
1147
|
iterate(enter, leave) {
|
|
961
1148
|
for (let depth = 0;;) {
|
|
962
1149
|
let mustLeave = false;
|
|
@@ -982,9 +1169,11 @@ class TreeCursor {
|
|
|
982
1169
|
}
|
|
983
1170
|
}
|
|
984
1171
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1172
|
+
/**
|
|
1173
|
+
Test whether the current node matches a given context—a sequence
|
|
1174
|
+
of direct parent node names. Empty strings in the context array
|
|
1175
|
+
are treated as wildcards.
|
|
1176
|
+
*/
|
|
988
1177
|
matchContext(context) {
|
|
989
1178
|
if (!this.buffer)
|
|
990
1179
|
return matchNodeContext(this.node, context);
|
|
@@ -1259,9 +1448,11 @@ mkTree) {
|
|
|
1259
1448
|
divide(children, positions, from, to, 0);
|
|
1260
1449
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1261
1450
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1451
|
+
/**
|
|
1452
|
+
Provides a way to associate values with pieces of trees. As long
|
|
1453
|
+
as that part of the tree is reused, the associated values can be
|
|
1454
|
+
retrieved from an updated tree.
|
|
1455
|
+
*/
|
|
1265
1456
|
class NodeWeakMap {
|
|
1266
1457
|
constructor() {
|
|
1267
1458
|
this.map = new WeakMap();
|
|
@@ -1276,57 +1467,77 @@ class NodeWeakMap {
|
|
|
1276
1467
|
let inner = this.map.get(buffer);
|
|
1277
1468
|
return inner && inner.get(index);
|
|
1278
1469
|
}
|
|
1279
|
-
|
|
1470
|
+
/**
|
|
1471
|
+
Set the value for this syntax node.
|
|
1472
|
+
*/
|
|
1280
1473
|
set(node, value) {
|
|
1281
1474
|
if (node instanceof BufferNode)
|
|
1282
1475
|
this.setBuffer(node.context.buffer, node.index, value);
|
|
1283
1476
|
else if (node instanceof TreeNode)
|
|
1284
1477
|
this.map.set(node.tree, value);
|
|
1285
1478
|
}
|
|
1286
|
-
|
|
1479
|
+
/**
|
|
1480
|
+
Retrieve value for this syntax node, if it exists in the map.
|
|
1481
|
+
*/
|
|
1287
1482
|
get(node) {
|
|
1288
1483
|
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1289
1484
|
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1290
1485
|
}
|
|
1291
|
-
|
|
1486
|
+
/**
|
|
1487
|
+
Set the value for the node that a cursor currently points to.
|
|
1488
|
+
*/
|
|
1292
1489
|
cursorSet(cursor, value) {
|
|
1293
1490
|
if (cursor.buffer)
|
|
1294
1491
|
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1295
1492
|
else
|
|
1296
1493
|
this.map.set(cursor.tree, value);
|
|
1297
1494
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1495
|
+
/**
|
|
1496
|
+
Retrieve the value for the node that a cursor currently points
|
|
1497
|
+
to.
|
|
1498
|
+
*/
|
|
1300
1499
|
cursorGet(cursor) {
|
|
1301
1500
|
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1302
1501
|
}
|
|
1303
1502
|
}
|
|
1304
1503
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1504
|
+
/**
|
|
1505
|
+
Tree fragments are used during [incremental
|
|
1506
|
+
parsing](#common.Parser.startParse) to track parts of old trees
|
|
1507
|
+
that can be reused in a new parse. An array of fragments is used
|
|
1508
|
+
to track regions of an old tree whose nodes might be reused in new
|
|
1509
|
+
parses. Use the static
|
|
1510
|
+
[`applyChanges`](#common.TreeFragment^applyChanges) method to
|
|
1511
|
+
update fragments for document changes.
|
|
1512
|
+
*/
|
|
1312
1513
|
class TreeFragment {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1514
|
+
/**
|
|
1515
|
+
Construct a tree fragment. You'll usually want to use
|
|
1516
|
+
[`addTree`](#common.TreeFragment^addTree) and
|
|
1517
|
+
[`applyChanges`](#common.TreeFragment^applyChanges) instead of
|
|
1518
|
+
calling this directly.
|
|
1519
|
+
*/
|
|
1317
1520
|
constructor(
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1521
|
+
/**
|
|
1522
|
+
The start of the unchanged range pointed to by this fragment.
|
|
1523
|
+
This refers to an offset in the _updated_ document (as opposed
|
|
1524
|
+
to the original tree).
|
|
1525
|
+
*/
|
|
1321
1526
|
from,
|
|
1322
|
-
|
|
1527
|
+
/**
|
|
1528
|
+
The end of the unchanged range.
|
|
1529
|
+
*/
|
|
1323
1530
|
to,
|
|
1324
|
-
|
|
1531
|
+
/**
|
|
1532
|
+
The tree that this fragment is based on.
|
|
1533
|
+
*/
|
|
1325
1534
|
tree,
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1535
|
+
/**
|
|
1536
|
+
The offset between the fragment's tree and the document that
|
|
1537
|
+
this fragment can be used against. Add this when going from
|
|
1538
|
+
document to tree positions, subtract it to go from tree to
|
|
1539
|
+
document positions.
|
|
1540
|
+
*/
|
|
1330
1541
|
offset, openStart = false, openEnd = false) {
|
|
1331
1542
|
this.from = from;
|
|
1332
1543
|
this.to = to;
|
|
@@ -1334,20 +1545,26 @@ class TreeFragment {
|
|
|
1334
1545
|
this.offset = offset;
|
|
1335
1546
|
this.open = (openStart ? 1 /* Open.Start */ : 0) | (openEnd ? 2 /* Open.End */ : 0);
|
|
1336
1547
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1548
|
+
/**
|
|
1549
|
+
Whether the start of the fragment represents the start of a
|
|
1550
|
+
parse, or the end of a change. (In the second case, it may not
|
|
1551
|
+
be safe to reuse some nodes at the start, depending on the
|
|
1552
|
+
parsing algorithm.)
|
|
1553
|
+
*/
|
|
1341
1554
|
get openStart() { return (this.open & 1 /* Open.Start */) > 0; }
|
|
1342
|
-
|
|
1343
|
-
|
|
1555
|
+
/**
|
|
1556
|
+
Whether the end of the fragment represents the end of a
|
|
1557
|
+
full-document parse, or the start of a change.
|
|
1558
|
+
*/
|
|
1344
1559
|
get openEnd() { return (this.open & 2 /* Open.End */) > 0; }
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1560
|
+
/**
|
|
1561
|
+
Create a set of fragments from a freshly parsed tree, or update
|
|
1562
|
+
an existing set of fragments by replacing the ones that overlap
|
|
1563
|
+
with a tree with content from the new tree. When `partial` is
|
|
1564
|
+
true, the parse is treated as incomplete, and the resulting
|
|
1565
|
+
fragment has [`openEnd`](#common.TreeFragment.openEnd) set to
|
|
1566
|
+
true.
|
|
1567
|
+
*/
|
|
1351
1568
|
static addTree(tree, fragments = [], partial = false) {
|
|
1352
1569
|
let result = [new TreeFragment(0, tree.length, tree, 0, false, partial)];
|
|
1353
1570
|
for (let f of fragments)
|
|
@@ -1355,9 +1572,11 @@ class TreeFragment {
|
|
|
1355
1572
|
result.push(f);
|
|
1356
1573
|
return result;
|
|
1357
1574
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1575
|
+
/**
|
|
1576
|
+
Apply a set of edits to an array of fragments, removing or
|
|
1577
|
+
splitting fragments as necessary to remove edited ranges, and
|
|
1578
|
+
adjusting offsets for fragments that moved.
|
|
1579
|
+
*/
|
|
1361
1580
|
static applyChanges(fragments, changes, minGap = 128) {
|
|
1362
1581
|
if (!changes.length)
|
|
1363
1582
|
return fragments;
|
|
@@ -1387,23 +1606,29 @@ class TreeFragment {
|
|
|
1387
1606
|
return result;
|
|
1388
1607
|
}
|
|
1389
1608
|
}
|
|
1390
|
-
|
|
1609
|
+
/**
|
|
1610
|
+
A superclass that parsers should extend.
|
|
1611
|
+
*/
|
|
1391
1612
|
class Parser {
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1613
|
+
/**
|
|
1614
|
+
Start a parse, returning a [partial parse](#common.PartialParse)
|
|
1615
|
+
object. [`fragments`](#common.TreeFragment) can be passed in to
|
|
1616
|
+
make the parse incremental.
|
|
1617
|
+
|
|
1618
|
+
By default, the entire input is parsed. You can pass `ranges`,
|
|
1619
|
+
which should be a sorted array of non-empty, non-overlapping
|
|
1620
|
+
ranges, to parse only those ranges. The tree returned in that
|
|
1621
|
+
case will start at `ranges[0].from`.
|
|
1622
|
+
*/
|
|
1400
1623
|
startParse(input, fragments, ranges) {
|
|
1401
1624
|
if (typeof input == "string")
|
|
1402
1625
|
input = new StringInput(input);
|
|
1403
1626
|
ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map(r => new Range(r.from, r.to)) : [new Range(0, 0)];
|
|
1404
1627
|
return this.createParse(input, fragments || [], ranges);
|
|
1405
1628
|
}
|
|
1406
|
-
|
|
1629
|
+
/**
|
|
1630
|
+
Run a full parse, returning the resulting tree.
|
|
1631
|
+
*/
|
|
1407
1632
|
parse(input, fragments, ranges) {
|
|
1408
1633
|
let parse = this.startParse(input, fragments, ranges);
|
|
1409
1634
|
for (;;) {
|
|
@@ -1423,11 +1648,13 @@ class StringInput {
|
|
|
1423
1648
|
read(from, to) { return this.string.slice(from, to); }
|
|
1424
1649
|
}
|
|
1425
1650
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1651
|
+
/**
|
|
1652
|
+
Create a parse wrapper that, after the inner parse completes,
|
|
1653
|
+
scans its tree for mixed language regions with the `nest`
|
|
1654
|
+
function, runs the resulting [inner parses](#common.NestedParse),
|
|
1655
|
+
and then [mounts](#common.NodeProp^mounted) their results onto the
|
|
1656
|
+
tree.
|
|
1657
|
+
*/
|
|
1431
1658
|
function parseMixed(nest) {
|
|
1432
1659
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1433
1660
|
}
|
|
@@ -1438,6 +1665,8 @@ class InnerParse {
|
|
|
1438
1665
|
this.overlay = overlay;
|
|
1439
1666
|
this.target = target;
|
|
1440
1667
|
this.ranges = ranges;
|
|
1668
|
+
if (!ranges.length || ranges.some(r => r.from >= r.to))
|
|
1669
|
+
throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
|
|
1441
1670
|
}
|
|
1442
1671
|
}
|
|
1443
1672
|
class ActiveOverlay {
|