aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c')
-rw-r--r--vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c714
1 files changed, 714 insertions, 0 deletions
diff --git a/vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c b/vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c
new file mode 100644
index 0000000..c1a3d8a
--- /dev/null
+++ b/vendor/github.com/mitjafelicijan/go-tree-sitter/tree_cursor.c
@@ -0,0 +1,714 @@
1#include "api.h"
2#include "./alloc.h"
3#include "./tree_cursor.h"
4#include "./language.h"
5#include "./tree.h"
6
7typedef struct {
8 Subtree parent;
9 const TSTree *tree;
10 Length position;
11 uint32_t child_index;
12 uint32_t structural_child_index;
13 uint32_t descendant_index;
14 const TSSymbol *alias_sequence;
15} CursorChildIterator;
16
17// CursorChildIterator
18
19static inline bool ts_tree_cursor_is_entry_visible(const TreeCursor *self, uint32_t index) {
20 TreeCursorEntry *entry = &self->stack.contents[index];
21 if (index == 0 || ts_subtree_visible(*entry->subtree)) {
22 return true;
23 } else if (!ts_subtree_extra(*entry->subtree)) {
24 TreeCursorEntry *parent_entry = &self->stack.contents[index - 1];
25 return ts_language_alias_at(
26 self->tree->language,
27 parent_entry->subtree->ptr->production_id,
28 entry->structural_child_index
29 );
30 } else {
31 return false;
32 }
33}
34
35static inline CursorChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self) {
36 TreeCursorEntry *last_entry = array_back(&self->stack);
37 if (ts_subtree_child_count(*last_entry->subtree) == 0) {
38 return (CursorChildIterator) {NULL_SUBTREE, self->tree, length_zero(), 0, 0, 0, NULL};
39 }
40 const TSSymbol *alias_sequence = ts_language_alias_sequence(
41 self->tree->language,
42 last_entry->subtree->ptr->production_id
43 );
44
45 uint32_t descendant_index = last_entry->descendant_index;
46 if (ts_tree_cursor_is_entry_visible(self, self->stack.size - 1)) {
47 descendant_index += 1;
48 }
49
50 return (CursorChildIterator) {
51 .tree = self->tree,
52 .parent = *last_entry->subtree,
53 .position = last_entry->position,
54 .child_index = 0,
55 .structural_child_index = 0,
56 .descendant_index = descendant_index,
57 .alias_sequence = alias_sequence,
58 };
59}
60
61static inline bool ts_tree_cursor_child_iterator_next(
62 CursorChildIterator *self,
63 TreeCursorEntry *result,
64 bool *visible
65) {
66 if (!self->parent.ptr || self->child_index == self->parent.ptr->child_count) return false;
67 const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
68 *result = (TreeCursorEntry) {
69 .subtree = child,
70 .position = self->position,
71 .child_index = self->child_index,
72 .structural_child_index = self->structural_child_index,
73 .descendant_index = self->descendant_index,
74 };
75 *visible = ts_subtree_visible(*child);
76 bool extra = ts_subtree_extra(*child);
77 if (!extra) {
78 if (self->alias_sequence) {
79 *visible |= self->alias_sequence[self->structural_child_index];
80 }
81 self->structural_child_index++;
82 }
83
84 self->descendant_index += ts_subtree_visible_descendant_count(*child);
85 if (*visible) {
86 self->descendant_index += 1;
87 }
88
89 self->position = length_add(self->position, ts_subtree_size(*child));
90 self->child_index++;
91
92 if (self->child_index < self->parent.ptr->child_count) {
93 Subtree next_child = ts_subtree_children(self->parent)[self->child_index];
94 self->position = length_add(self->position, ts_subtree_padding(next_child));
95 }
96
97 return true;
98}
99
100// Return a position that, when `b` is added to it, yields `a`. This
101// can only be computed if `b` has zero rows. Otherwise, this function
102// returns `LENGTH_UNDEFINED`, and the caller needs to recompute
103// the position some other way.
104static inline Length length_backtrack(Length a, Length b) {
105 if (length_is_undefined(a) || b.extent.row != 0) {
106 return LENGTH_UNDEFINED;
107 }
108
109 Length result;
110 result.bytes = a.bytes - b.bytes;
111 result.extent.row = a.extent.row;
112 result.extent.column = a.extent.column - b.extent.column;
113 return result;
114}
115
116static inline bool ts_tree_cursor_child_iterator_previous(
117 CursorChildIterator *self,
118 TreeCursorEntry *result,
119 bool *visible
120) {
121 // this is mostly a reverse `ts_tree_cursor_child_iterator_next` taking into
122 // account unsigned underflow
123 if (!self->parent.ptr || (int8_t)self->child_index == -1) return false;
124 const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
125 *result = (TreeCursorEntry) {
126 .subtree = child,
127 .position = self->position,
128 .child_index = self->child_index,
129 .structural_child_index = self->structural_child_index,
130 };
131 *visible = ts_subtree_visible(*child);
132 bool extra = ts_subtree_extra(*child);
133 if (!extra && self->alias_sequence) {
134 *visible |= self->alias_sequence[self->structural_child_index];
135 self->structural_child_index--;
136 }
137
138 self->position = length_backtrack(self->position, ts_subtree_padding(*child));
139 self->child_index--;
140
141 // unsigned can underflow so compare it to child_count
142 if (self->child_index < self->parent.ptr->child_count) {
143 Subtree previous_child = ts_subtree_children(self->parent)[self->child_index];
144 Length size = ts_subtree_size(previous_child);
145 self->position = length_backtrack(self->position, size);
146 }
147
148 return true;
149}
150
151// TSTreeCursor - lifecycle
152
153TSTreeCursor ts_tree_cursor_new(TSNode node) {
154 TSTreeCursor self = {NULL, NULL, {0, 0, 0}};
155 ts_tree_cursor_init((TreeCursor *)&self, node);
156 return self;
157}
158
159void ts_tree_cursor_reset(TSTreeCursor *_self, TSNode node) {
160 ts_tree_cursor_init((TreeCursor *)_self, node);
161}
162
163void ts_tree_cursor_init(TreeCursor *self, TSNode node) {
164 self->tree = node.tree;
165 self->root_alias_symbol = node.context[3];
166 array_clear(&self->stack);
167 array_push(&self->stack, ((TreeCursorEntry) {
168 .subtree = (const Subtree *)node.id,
169 .position = {
170 ts_node_start_byte(node),
171 ts_node_start_point(node)
172 },
173 .child_index = 0,
174 .structural_child_index = 0,
175 .descendant_index = 0,
176 }));
177}
178
179void ts_tree_cursor_delete(TSTreeCursor *_self) {
180 TreeCursor *self = (TreeCursor *)_self;
181 array_delete(&self->stack);
182}
183
184// TSTreeCursor - walking the tree
185
186TreeCursorStep ts_tree_cursor_goto_first_child_internal(TSTreeCursor *_self) {
187 TreeCursor *self = (TreeCursor *)_self;
188 bool visible;
189 TreeCursorEntry entry;
190 CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
191 while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
192 if (visible) {
193 array_push(&self->stack, entry);
194 return TreeCursorStepVisible;
195 }
196 if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
197 array_push(&self->stack, entry);
198 return TreeCursorStepHidden;
199 }
200 }
201 return TreeCursorStepNone;
202}
203
204bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
205 for (;;) {
206 switch (ts_tree_cursor_goto_first_child_internal(self)) {
207 case TreeCursorStepHidden:
208 continue;
209 case TreeCursorStepVisible:
210 return true;
211 default:
212 return false;
213 }
214 }
215 return false;
216}
217
218TreeCursorStep ts_tree_cursor_goto_last_child_internal(TSTreeCursor *_self) {
219 TreeCursor *self = (TreeCursor *)_self;
220 bool visible;
221 TreeCursorEntry entry;
222 CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
223 if (!iterator.parent.ptr || iterator.parent.ptr->child_count == 0) return TreeCursorStepNone;
224
225 TreeCursorEntry last_entry = {0};
226 TreeCursorStep last_step = TreeCursorStepNone;
227 while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
228 if (visible) {
229 last_entry = entry;
230 last_step = TreeCursorStepVisible;
231 }
232 else if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
233 last_entry = entry;
234 last_step = TreeCursorStepHidden;
235 }
236 }
237 if (last_entry.subtree) {
238 array_push(&self->stack, last_entry);
239 return last_step;
240 }
241
242 return TreeCursorStepNone;
243}
244
245bool ts_tree_cursor_goto_last_child(TSTreeCursor *self) {
246 for (;;) {
247 switch (ts_tree_cursor_goto_last_child_internal(self)) {
248 case TreeCursorStepHidden:
249 continue;
250 case TreeCursorStepVisible:
251 return true;
252 default:
253 return false;
254 }
255 }
256 return false;
257}
258
259static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point(
260 TSTreeCursor *_self,
261 uint32_t goal_byte,
262 TSPoint goal_point
263) {
264 TreeCursor *self = (TreeCursor *)_self;
265 uint32_t initial_size = self->stack.size;
266 uint32_t visible_child_index = 0;
267
268 bool did_descend;
269 do {
270 did_descend = false;
271
272 bool visible;
273 TreeCursorEntry entry;
274 CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
275 while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
276 Length entry_end = length_add(entry.position, ts_subtree_size(*entry.subtree));
277 bool at_goal = entry_end.bytes >= goal_byte && point_gte(entry_end.extent, goal_point);
278 uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree);
279 if (at_goal) {
280 if (visible) {
281 array_push(&self->stack, entry);
282 return visible_child_index;
283 }
284 if (visible_child_count > 0) {
285 array_push(&self->stack, entry);
286 did_descend = true;
287 break;
288 }
289 } else if (visible) {
290 visible_child_index++;
291 } else {
292 visible_child_index += visible_child_count;
293 }
294 }
295 } while (did_descend);
296
297 self->stack.size = initial_size;
298 return -1;
299}
300
301int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *self, uint32_t goal_byte) {
302 return ts_tree_cursor_goto_first_child_for_byte_and_point(self, goal_byte, POINT_ZERO);
303}
304
305int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint goal_point) {
306 return ts_tree_cursor_goto_first_child_for_byte_and_point(self, 0, goal_point);
307}
308
309TreeCursorStep ts_tree_cursor_goto_sibling_internal(
310 TSTreeCursor *_self,
311 bool (*advance)(CursorChildIterator *, TreeCursorEntry *, bool *)) {
312 TreeCursor *self = (TreeCursor *)_self;
313 uint32_t initial_size = self->stack.size;
314
315 while (self->stack.size > 1) {
316 TreeCursorEntry entry = array_pop(&self->stack);
317 CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
318 iterator.child_index = entry.child_index;
319 iterator.structural_child_index = entry.structural_child_index;
320 iterator.position = entry.position;
321 iterator.descendant_index = entry.descendant_index;
322
323 bool visible = false;
324 advance(&iterator, &entry, &visible);
325 if (visible && self->stack.size + 1 < initial_size) break;
326
327 while (advance(&iterator, &entry, &visible)) {
328 if (visible) {
329 array_push(&self->stack, entry);
330 return TreeCursorStepVisible;
331 }
332
333 if (ts_subtree_visible_child_count(*entry.subtree)) {
334 array_push(&self->stack, entry);
335 return TreeCursorStepHidden;
336 }
337 }
338 }
339
340 self->stack.size = initial_size;
341 return TreeCursorStepNone;
342}
343
344TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
345 return ts_tree_cursor_goto_sibling_internal(_self, ts_tree_cursor_child_iterator_next);
346}
347
348bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
349 switch (ts_tree_cursor_goto_next_sibling_internal(self)) {
350 case TreeCursorStepHidden:
351 ts_tree_cursor_goto_first_child(self);
352 return true;
353 case TreeCursorStepVisible:
354 return true;
355 default:
356 return false;
357 }
358}
359
360TreeCursorStep ts_tree_cursor_goto_previous_sibling_internal(TSTreeCursor *_self) {
361 // since subtracting across row loses column information, we may have to
362 // restore it
363 TreeCursor *self = (TreeCursor *)_self;
364
365 // for that, save current position before traversing
366 TreeCursorStep step = ts_tree_cursor_goto_sibling_internal(
367 _self, ts_tree_cursor_child_iterator_previous);
368 if (step == TreeCursorStepNone)
369 return step;
370
371 // if length is already valid, there's no need to recompute it
372 if (!length_is_undefined(array_back(&self->stack)->position))
373 return step;
374
375 // restore position from the parent node
376 const TreeCursorEntry *parent = &self->stack.contents[self->stack.size - 2];
377 Length position = parent->position;
378 uint32_t child_index = array_back(&self->stack)->child_index;
379 const Subtree *children = ts_subtree_children((*(parent->subtree)));
380
381 if (child_index > 0) {
382 // skip first child padding since its position should match the position of the parent
383 position = length_add(position, ts_subtree_size(children[0]));
384 for (uint32_t i = 1; i < child_index; ++i) {
385 position = length_add(position, ts_subtree_total_size(children[i]));
386 }
387 position = length_add(position, ts_subtree_padding(children[child_index]));
388 }
389
390 array_back(&self->stack)->position = position;
391
392 return step;
393}
394
395bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self) {
396 switch (ts_tree_cursor_goto_previous_sibling_internal(self)) {
397 case TreeCursorStepHidden:
398 ts_tree_cursor_goto_last_child(self);
399 return true;
400 case TreeCursorStepVisible:
401 return true;
402 default:
403 return false;
404 }
405}
406
407bool ts_tree_cursor_goto_parent(TSTreeCursor *_self) {
408 TreeCursor *self = (TreeCursor *)_self;
409 for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
410 if (ts_tree_cursor_is_entry_visible(self, i)) {
411 self->stack.size = i + 1;
412 return true;
413 }
414 }
415 return false;
416}
417
418void ts_tree_cursor_goto_descendant(
419 TSTreeCursor *_self,
420 uint32_t goal_descendant_index
421) {
422 TreeCursor *self = (TreeCursor *)_self;
423
424 // Ascend to the lowest ancestor that contains the goal node.
425 for (;;) {
426 uint32_t i = self->stack.size - 1;
427 TreeCursorEntry *entry = &self->stack.contents[i];
428 uint32_t next_descendant_index =
429 entry->descendant_index +
430 (ts_tree_cursor_is_entry_visible(self, i) ? 1 : 0) +
431 ts_subtree_visible_descendant_count(*entry->subtree);
432 if (
433 (entry->descendant_index <= goal_descendant_index) &&
434 (next_descendant_index > goal_descendant_index)
435 ) {
436 break;
437 } else if (self->stack.size <= 1) {
438 return;
439 } else {
440 self->stack.size--;
441 }
442 }
443
444 // Descend to the goal node.
445 bool did_descend = true;
446 do {
447 did_descend = false;
448 bool visible;
449 TreeCursorEntry entry;
450 CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
451 if (iterator.descendant_index > goal_descendant_index) {
452 return;
453 }
454
455 while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
456 if (iterator.descendant_index > goal_descendant_index) {
457 array_push(&self->stack, entry);
458 if (visible && entry.descendant_index == goal_descendant_index) {
459 return;
460 } else {
461 did_descend = true;
462 break;
463 }
464 }
465 }
466 } while (did_descend);
467}
468
469uint32_t ts_tree_cursor_current_descendant_index(const TSTreeCursor *_self) {
470 const TreeCursor *self = (const TreeCursor *)_self;
471 TreeCursorEntry *last_entry = array_back(&self->stack);
472 return last_entry->descendant_index;
473}
474
475TSNode ts_tree_cursor_current_node(const TSTreeCursor *_self) {
476 const TreeCursor *self = (const TreeCursor *)_self;
477 TreeCursorEntry *last_entry = array_back(&self->stack);
478 TSSymbol alias_symbol = self->root_alias_symbol;
479 if (self->stack.size > 1 && !ts_subtree_extra(*last_entry->subtree)) {
480 TreeCursorEntry *parent_entry = &self->stack.contents[self->stack.size - 2];
481 alias_symbol = ts_language_alias_at(
482 self->tree->language,
483 parent_entry->subtree->ptr->production_id,
484 last_entry->structural_child_index
485 );
486 }
487 return ts_node_new(
488 self->tree,
489 last_entry->subtree,
490 last_entry->position,
491 alias_symbol
492 );
493}
494
495// Private - Get various facts about the current node that are needed
496// when executing tree queries.
497void ts_tree_cursor_current_status(
498 const TSTreeCursor *_self,
499 TSFieldId *field_id,
500 bool *has_later_siblings,
501 bool *has_later_named_siblings,
502 bool *can_have_later_siblings_with_this_field,
503 TSSymbol *supertypes,
504 unsigned *supertype_count
505) {
506 const TreeCursor *self = (const TreeCursor *)_self;
507 unsigned max_supertypes = *supertype_count;
508 *field_id = 0;
509 *supertype_count = 0;
510 *has_later_siblings = false;
511 *has_later_named_siblings = false;
512 *can_have_later_siblings_with_this_field = false;
513
514 // Walk up the tree, visiting the current node and its invisible ancestors,
515 // because fields can refer to nodes through invisible *wrapper* nodes,
516 for (unsigned i = self->stack.size - 1; i > 0; i--) {
517 TreeCursorEntry *entry = &self->stack.contents[i];
518 TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
519
520 const TSSymbol *alias_sequence = ts_language_alias_sequence(
521 self->tree->language,
522 parent_entry->subtree->ptr->production_id
523 );
524
525 #define subtree_symbol(subtree, structural_child_index) \
526 (( \
527 !ts_subtree_extra(subtree) && \
528 alias_sequence && \
529 alias_sequence[structural_child_index] \
530 ) ? \
531 alias_sequence[structural_child_index] : \
532 ts_subtree_symbol(subtree))
533
534 // Stop walking up when a visible ancestor is found.
535 TSSymbol entry_symbol = subtree_symbol(
536 *entry->subtree,
537 entry->structural_child_index
538 );
539 TSSymbolMetadata entry_metadata = ts_language_symbol_metadata(
540 self->tree->language,
541 entry_symbol
542 );
543 if (i != self->stack.size - 1 && entry_metadata.visible) break;
544
545 // Record any supertypes
546 if (entry_metadata.supertype && *supertype_count < max_supertypes) {
547 supertypes[*supertype_count] = entry_symbol;
548 (*supertype_count)++;
549 }
550
551 // Determine if the current node has later siblings.
552 if (!*has_later_siblings) {
553 unsigned sibling_count = parent_entry->subtree->ptr->child_count;
554 unsigned structural_child_index = entry->structural_child_index;
555 if (!ts_subtree_extra(*entry->subtree)) structural_child_index++;
556 for (unsigned j = entry->child_index + 1; j < sibling_count; j++) {
557 Subtree sibling = ts_subtree_children(*parent_entry->subtree)[j];
558 TSSymbolMetadata sibling_metadata = ts_language_symbol_metadata(
559 self->tree->language,
560 subtree_symbol(sibling, structural_child_index)
561 );
562 if (sibling_metadata.visible) {
563 *has_later_siblings = true;
564 if (*has_later_named_siblings) break;
565 if (sibling_metadata.named) {
566 *has_later_named_siblings = true;
567 break;
568 }
569 } else if (ts_subtree_visible_child_count(sibling) > 0) {
570 *has_later_siblings = true;
571 if (*has_later_named_siblings) break;
572 if (sibling.ptr->named_child_count > 0) {
573 *has_later_named_siblings = true;
574 break;
575 }
576 }
577 if (!ts_subtree_extra(sibling)) structural_child_index++;
578 }
579 }
580
581 #undef subtree_symbol
582
583 if (!ts_subtree_extra(*entry->subtree)) {
584 const TSFieldMapEntry *field_map, *field_map_end;
585 ts_language_field_map(
586 self->tree->language,
587 parent_entry->subtree->ptr->production_id,
588 &field_map, &field_map_end
589 );
590
591 // Look for a field name associated with the current node.
592 if (!*field_id) {
593 for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
594 if (!map->inherited && map->child_index == entry->structural_child_index) {
595 *field_id = map->field_id;
596 break;
597 }
598 }
599 }
600
601 // Determine if the current node can have later siblings with the same field name.
602 if (*field_id) {
603 for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
604 if (
605 map->field_id == *field_id &&
606 map->child_index > entry->structural_child_index
607 ) {
608 *can_have_later_siblings_with_this_field = true;
609 break;
610 }
611 }
612 }
613 }
614 }
615}
616
617uint32_t ts_tree_cursor_current_depth(const TSTreeCursor *_self) {
618 const TreeCursor *self = (const TreeCursor *)_self;
619 uint32_t depth = 0;
620 for (unsigned i = 1; i < self->stack.size; i++) {
621 if (ts_tree_cursor_is_entry_visible(self, i)) {
622 depth++;
623 }
624 }
625 return depth;
626}
627
628TSNode ts_tree_cursor_parent_node(const TSTreeCursor *_self) {
629 const TreeCursor *self = (const TreeCursor *)_self;
630 for (int i = (int)self->stack.size - 2; i >= 0; i--) {
631 TreeCursorEntry *entry = &self->stack.contents[i];
632 bool is_visible = true;
633 TSSymbol alias_symbol = 0;
634 if (i > 0) {
635 TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
636 alias_symbol = ts_language_alias_at(
637 self->tree->language,
638 parent_entry->subtree->ptr->production_id,
639 entry->structural_child_index
640 );
641 is_visible = (alias_symbol != 0) || ts_subtree_visible(*entry->subtree);
642 }
643 if (is_visible) {
644 return ts_node_new(
645 self->tree,
646 entry->subtree,
647 entry->position,
648 alias_symbol
649 );
650 }
651 }
652 return ts_node_new(NULL, NULL, length_zero(), 0);
653}
654
655TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self) {
656 const TreeCursor *self = (const TreeCursor *)_self;
657
658 // Walk up the tree, visiting the current node and its invisible ancestors.
659 for (unsigned i = self->stack.size - 1; i > 0; i--) {
660 TreeCursorEntry *entry = &self->stack.contents[i];
661 TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
662
663 // Stop walking up when another visible node is found.
664 if (
665 i != self->stack.size - 1 &&
666 ts_tree_cursor_is_entry_visible(self, i)
667 ) break;
668
669 if (ts_subtree_extra(*entry->subtree)) break;
670
671 const TSFieldMapEntry *field_map, *field_map_end;
672 ts_language_field_map(
673 self->tree->language,
674 parent_entry->subtree->ptr->production_id,
675 &field_map, &field_map_end
676 );
677 for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
678 if (!map->inherited && map->child_index == entry->structural_child_index) {
679 return map->field_id;
680 }
681 }
682 }
683 return 0;
684}
685
686const char *ts_tree_cursor_current_field_name(const TSTreeCursor *_self) {
687 TSFieldId id = ts_tree_cursor_current_field_id(_self);
688 if (id) {
689 const TreeCursor *self = (const TreeCursor *)_self;
690 return self->tree->language->field_names[id];
691 } else {
692 return NULL;
693 }
694}
695
696TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *_cursor) {
697 const TreeCursor *cursor = (const TreeCursor *)_cursor;
698 TSTreeCursor res = {NULL, NULL, {0, 0}};
699 TreeCursor *copy = (TreeCursor *)&res;
700 copy->tree = cursor->tree;
701 copy->root_alias_symbol = cursor->root_alias_symbol;
702 array_init(&copy->stack);
703 array_push_all(&copy->stack, &cursor->stack);
704 return res;
705}
706
707void ts_tree_cursor_reset_to(TSTreeCursor *_dst, const TSTreeCursor *_src) {
708 const TreeCursor *cursor = (const TreeCursor *)_src;
709 TreeCursor *copy = (TreeCursor *)_dst;
710 copy->tree = cursor->tree;
711 copy->root_alias_symbol = cursor->root_alias_symbol;
712 array_clear(&copy->stack);
713 array_push_all(&copy->stack, &cursor->stack);
714}