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