0
# Tree Cursor
1
2
Efficient tree traversal using stateful cursors for performance-critical applications. TreeCursor provides a low-level, memory-efficient way to walk syntax trees without creating intermediate Node objects.
3
4
## Capabilities
5
6
### Cursor Creation and Management
7
8
Create and manage tree cursor instances.
9
10
```typescript { .api }
11
/**
12
* Create a deep copy of the tree cursor (allocates new memory)
13
* @returns New TreeCursor instance
14
*/
15
copy(): TreeCursor;
16
17
/**
18
* Delete the tree cursor and free its resources
19
*/
20
delete(): void;
21
```
22
23
**Usage Example:**
24
25
```typescript
26
const tree = parser.parse("let x = 1 + 2;");
27
const cursor = tree.walk();
28
29
// Create a copy for parallel traversal
30
const cursorCopy = cursor.copy();
31
32
// Clean up when done
33
cursor.delete();
34
cursorCopy.delete();
35
```
36
37
### Current Node Access
38
39
Access information about the current node without creating Node objects.
40
41
```typescript { .api }
42
/**
43
* Get the tree cursor's current Node
44
* @returns Current node (creates Node object)
45
*/
46
get currentNode(): Node;
47
48
/**
49
* Get the numerical field id of this tree cursor's current node
50
* @returns Field ID or 0 if no field
51
*/
52
get currentFieldId(): number;
53
54
/**
55
* Get the field name of this tree cursor's current node
56
* @returns Field name or null if no field
57
*/
58
get currentFieldName(): string | null;
59
```
60
61
### Position Information
62
63
Get cursor position and depth information.
64
65
```typescript { .api }
66
/**
67
* Get the depth of the cursor's current node relative to the original node
68
* @returns Depth from root node
69
*/
70
get currentDepth(): number;
71
72
/**
73
* Get the index of the cursor's current node out of all descendants
74
* @returns Descendant index
75
*/
76
get currentDescendantIndex(): number;
77
```
78
79
### Node Type Information
80
81
Access type information for the current node efficiently.
82
83
```typescript { .api }
84
/**
85
* Get the type of the cursor's current node
86
* @returns Node type as string
87
*/
88
get nodeType(): string;
89
90
/**
91
* Get the type id of the cursor's current node
92
* @returns Node type ID
93
*/
94
get nodeTypeId(): number;
95
96
/**
97
* Get the state id of the cursor's current node
98
* @returns Parse state ID
99
*/
100
get nodeStateId(): number;
101
102
/**
103
* Get the id of the cursor's current node
104
* @returns Unique node ID
105
*/
106
get nodeId(): number;
107
```
108
109
### Node Classification
110
111
Check node properties without creating Node objects.
112
113
```typescript { .api }
114
/**
115
* Check if the cursor's current node is named
116
* @returns True if node corresponds to named rule in grammar
117
*/
118
get nodeIsNamed(): boolean;
119
120
/**
121
* Check if the cursor's current node is missing
122
* @returns True if node was inserted for error recovery
123
*/
124
get nodeIsMissing(): boolean;
125
```
126
127
### Content and Position Access
128
129
Get node content and position information.
130
131
```typescript { .api }
132
/**
133
* Get the string content of the cursor's current node
134
* @returns Text content of current node
135
*/
136
get nodeText(): string;
137
138
/**
139
* Get the start position of the cursor's current node
140
* @returns Start position
141
*/
142
get startPosition(): Point;
143
144
/**
145
* Get the end position of the cursor's current node
146
* @returns End position
147
*/
148
get endPosition(): Point;
149
150
/**
151
* Get the start index of the cursor's current node
152
* @returns Start byte index
153
*/
154
get startIndex(): number;
155
156
/**
157
* Get the end index of the cursor's current node
158
* @returns End byte index
159
*/
160
get endIndex(): number;
161
```
162
163
**Usage Example:**
164
165
```typescript
166
const cursor = tree.walk();
167
168
console.log("Current node type:", cursor.nodeType);
169
console.log("Text:", cursor.nodeText);
170
console.log("Position:", cursor.startPosition, "to", cursor.endPosition);
171
console.log("Depth:", cursor.currentDepth);
172
console.log("Is named:", cursor.nodeIsNamed);
173
```
174
175
### Tree Navigation
176
177
Navigate through the tree structure efficiently.
178
179
```typescript { .api }
180
/**
181
* Move cursor to the first child of current node
182
* @returns True if successfully moved, false if no children
183
*/
184
gotoFirstChild(): boolean;
185
186
/**
187
* Move cursor to the last child of current node
188
* @returns True if successfully moved, false if no children
189
*/
190
gotoLastChild(): boolean;
191
192
/**
193
* Move cursor to the parent of current node
194
* @returns True if successfully moved, false if already at root
195
*/
196
gotoParent(): boolean;
197
198
/**
199
* Move cursor to the next sibling of current node
200
* @returns True if successfully moved, false if no next sibling
201
*/
202
gotoNextSibling(): boolean;
203
204
/**
205
* Move cursor to the previous sibling of current node
206
* @returns True if successfully moved, false if no previous sibling
207
*/
208
gotoPreviousSibling(): boolean;
209
```
210
211
**Usage Example:**
212
213
```typescript
214
const cursor = tree.walk();
215
216
// Walk through all children of root
217
if (cursor.gotoFirstChild()) {
218
do {
219
console.log("Child:", cursor.nodeType, cursor.nodeText);
220
221
// Visit grandchildren
222
if (cursor.gotoFirstChild()) {
223
do {
224
console.log(" Grandchild:", cursor.nodeType);
225
} while (cursor.gotoNextSibling());
226
cursor.gotoParent(); // Back to child level
227
}
228
} while (cursor.gotoNextSibling());
229
}
230
```
231
232
### Advanced Navigation
233
234
Navigate to specific positions and descendants.
235
236
```typescript { .api }
237
/**
238
* Move cursor to the nth descendant of the original node
239
* @param goalDescendantIndex - Index of target descendant (0 = original node)
240
*/
241
gotoDescendant(goalDescendantIndex: number): void;
242
243
/**
244
* Move cursor to first child containing or starting after given byte offset
245
* @param goalIndex - Target byte offset
246
* @returns True if found and moved, false if no such child
247
*/
248
gotoFirstChildForIndex(goalIndex: number): boolean;
249
250
/**
251
* Move cursor to first child containing or starting after given position
252
* @param goalPosition - Target position
253
* @returns True if found and moved, false if no such child
254
*/
255
gotoFirstChildForPosition(goalPosition: Point): boolean;
256
```
257
258
**Usage Example:**
259
260
```typescript
261
// Find node at specific byte offset
262
const cursor = tree.walk();
263
if (cursor.gotoFirstChildForIndex(15)) {
264
console.log("Found node at offset 15:", cursor.nodeType);
265
}
266
267
// Navigate to specific descendant
268
cursor.gotoDescendant(5); // Go to 5th descendant
269
console.log("5th descendant:", cursor.nodeType);
270
```
271
272
### Cursor Reset Operations
273
274
Reset cursor position and state.
275
276
```typescript { .api }
277
/**
278
* Re-initialize cursor to start at the given node
279
* @param node - Node to reset cursor to
280
*/
281
reset(node: Node): void;
282
283
/**
284
* Re-initialize cursor to the same position as another cursor
285
* @param cursor - Cursor to copy position from
286
*/
287
resetTo(cursor: TreeCursor): void;
288
```
289
290
**Usage Example:**
291
292
```typescript
293
const cursor1 = tree.walk();
294
const cursor2 = tree.walk();
295
296
// Move cursor1 to some position
297
cursor1.gotoFirstChild();
298
cursor1.gotoFirstChild();
299
300
// Copy position to cursor2
301
cursor2.resetTo(cursor1);
302
303
console.log("Both cursors at same position:");
304
console.log("Cursor1:", cursor1.nodeType);
305
console.log("Cursor2:", cursor2.nodeType);
306
307
// Reset cursor1 to root
308
cursor1.reset(tree.rootNode);
309
```
310
311
## Performance Benefits
312
313
TreeCursor provides significant performance advantages for tree traversal:
314
315
- **Memory Efficient**: No intermediate Node object creation during navigation
316
- **Cache Friendly**: Maintains position state without repeated tree walks
317
- **Fast Iteration**: Direct access to node properties without object allocation
318
- **Stateful Navigation**: Remembers position for complex traversal patterns
319
320
## Usage Patterns
321
322
### Full Tree Traversal
323
324
```typescript
325
function traverseTree(cursor: TreeCursor, depth: number = 0) {
326
const indent = " ".repeat(depth);
327
console.log(`${indent}${cursor.nodeType}: ${cursor.nodeText}`);
328
329
if (cursor.gotoFirstChild()) {
330
do {
331
traverseTree(cursor, depth + 1);
332
} while (cursor.gotoNextSibling());
333
cursor.gotoParent();
334
}
335
}
336
337
const cursor = tree.walk();
338
traverseTree(cursor);
339
cursor.delete();
340
```
341
342
### Find All Nodes of Type
343
344
```typescript
345
function findNodesOfType(tree: Tree, targetType: string): string[] {
346
const results: string[] = [];
347
const cursor = tree.walk();
348
349
function visit() {
350
if (cursor.nodeType === targetType) {
351
results.push(cursor.nodeText);
352
}
353
354
if (cursor.gotoFirstChild()) {
355
do {
356
visit();
357
} while (cursor.gotoNextSibling());
358
cursor.gotoParent();
359
}
360
}
361
362
visit();
363
cursor.delete();
364
return results;
365
}
366
367
const identifiers = findNodesOfType(tree, "identifier");
368
console.log("Found identifiers:", identifiers);
369
```
370
371
### Range-Based Processing
372
373
```typescript
374
function processRange(tree: Tree, startIndex: number, endIndex: number) {
375
const cursor = tree.walk();
376
377
// Find first node in range
378
if (cursor.gotoFirstChildForIndex(startIndex)) {
379
while (cursor.startIndex <= endIndex) {
380
if (cursor.endIndex >= startIndex) {
381
console.log("Processing:", cursor.nodeType, cursor.nodeText);
382
}
383
384
if (!cursor.gotoNextSibling()) {
385
break;
386
}
387
}
388
}
389
390
cursor.delete();
391
}
392
```