Rizin
unix-like reverse engineering framework and cli tools
tree_cursor.c File Reference
#include "tree_sitter/api.h"
#include "./alloc.h"
#include "./tree_cursor.h"
#include "./language.h"
#include "./tree.h"

Go to the source code of this file.

Classes

struct  CursorChildIterator
 

Macros

#define subtree_symbol(subtree, structural_child_index)
 

Functions

static CursorChildIterator ts_tree_cursor_iterate_children (const TreeCursor *self)
 
static bool ts_tree_cursor_child_iterator_next (CursorChildIterator *self, TreeCursorEntry *result, bool *visible)
 
TSTreeCursor ts_tree_cursor_new (TSNode node)
 
void ts_tree_cursor_reset (TSTreeCursor *_self, TSNode node)
 
void ts_tree_cursor_init (TreeCursor *self, TSNode node)
 
void ts_tree_cursor_delete (TSTreeCursor *_self)
 
bool ts_tree_cursor_goto_first_child (TSTreeCursor *_self)
 
int64_t ts_tree_cursor_goto_first_child_for_byte (TSTreeCursor *_self, uint32_t goal_byte)
 
int64_t ts_tree_cursor_goto_first_child_for_point (TSTreeCursor *_self, TSPoint goal_point)
 
bool ts_tree_cursor_goto_next_sibling (TSTreeCursor *_self)
 
bool ts_tree_cursor_goto_parent (TSTreeCursor *_self)
 
TSNode ts_tree_cursor_current_node (const TSTreeCursor *_self)
 
void ts_tree_cursor_current_status (const TSTreeCursor *_self, TSFieldId *field_id, bool *has_later_siblings, bool *has_later_named_siblings, bool *can_have_later_siblings_with_this_field, TSSymbol *supertypes, unsigned *supertype_count)
 
TSNode ts_tree_cursor_parent_node (const TSTreeCursor *_self)
 
TSFieldId ts_tree_cursor_current_field_id (const TSTreeCursor *_self)
 
const char * ts_tree_cursor_current_field_name (const TSTreeCursor *_self)
 
TSTreeCursor ts_tree_cursor_copy (const TSTreeCursor *_cursor)
 

Macro Definition Documentation

◆ subtree_symbol

#define subtree_symbol (   subtree,
  structural_child_index 
)
Value:
(( \
!ts_subtree_extra(subtree) && \
alias_sequence && \
alias_sequence[structural_child_index] \
) ? \
alias_sequence[structural_child_index] : \
static bool ts_subtree_extra(Subtree self)
Definition: subtree.h:216
static TSSymbol ts_subtree_symbol(Subtree self)
Definition: subtree.h:213

Function Documentation

◆ ts_tree_cursor_child_iterator_next()

static bool ts_tree_cursor_child_iterator_next ( CursorChildIterator self,
TreeCursorEntry result,
bool visible 
)
inlinestatic

Definition at line 37 of file tree_cursor.c.

41  {
42  if (!self->parent.ptr || self->child_index == self->parent.ptr->child_count) return false;
43  const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
44  *result = (TreeCursorEntry) {
45  .subtree = child,
46  .position = self->position,
47  .child_index = self->child_index,
48  .structural_child_index = self->structural_child_index,
49  };
50  *visible = ts_subtree_visible(*child);
51  bool extra = ts_subtree_extra(*child);
52  if (!extra && self->alias_sequence) {
53  *visible |= self->alias_sequence[self->structural_child_index];
54  self->structural_child_index++;
55  }
56 
57  self->position = length_add(self->position, ts_subtree_size(*child));
58  self->child_index++;
59 
60  if (self->child_index < self->parent.ptr->child_count) {
61  Subtree next_child = ts_subtree_children(self->parent)[self->child_index];
62  self->position = length_add(self->position, ts_subtree_padding(next_child));
63  }
64 
65  return true;
66 }
static Length length_add(Length len1, Length len2)
Definition: length.h:25
const TSSymbol * alias_sequence
Definition: tree_cursor.c:13
uint32_t child_index
Definition: tree_cursor.c:11
uint32_t child_count
Definition: subtree.h:117
const Subtree * subtree
Definition: tree_cursor.h:7
#define ts_subtree_children(self)
Definition: subtree.h:233
static bool ts_subtree_visible(Subtree self)
Definition: subtree.h:214
static Length ts_subtree_size(Subtree self)
Definition: subtree.h:265
static Length ts_subtree_padding(Subtree self)
Definition: subtree.h:256
const SubtreeHeapData * ptr
Definition: subtree.h:158

References length_add(), TreeCursorEntry::subtree, ts_subtree_children, ts_subtree_extra(), ts_subtree_padding(), ts_subtree_size(), and ts_subtree_visible().

Referenced by ts_tree_cursor_goto_first_child(), ts_tree_cursor_goto_first_child_for_byte(), ts_tree_cursor_goto_first_child_for_point(), and ts_tree_cursor_goto_next_sibling().

◆ ts_tree_cursor_copy()

TSTreeCursor ts_tree_cursor_copy ( const TSTreeCursor _cursor)

Definition at line 479 of file tree_cursor.c.

479  {
480  const TreeCursor *cursor = (const TreeCursor *)_cursor;
481  TSTreeCursor res = {NULL, NULL, {0, 0}};
482  TreeCursor *copy = (TreeCursor *)&res;
483  copy->tree = cursor->tree;
484  array_init(&copy->stack);
485  array_push_all(&copy->stack, &cursor->stack);
486  return res;
487 }
#define array_init(self)
Definition: array.h:22
#define array_push_all(self, other)
Definition: array.h:54
#define NULL
Definition: cris-opc.c:27
const TSTree * tree
Definition: tree_cursor.h:14

References array_init, array_push_all, NULL, and TreeCursor::tree.

◆ ts_tree_cursor_current_field_id()

TSFieldId ts_tree_cursor_current_field_id ( const TSTreeCursor _self)

Get the field id of the tree cursor's current node.

This returns zero if the current node doesn't have a field. See also ts_node_child_by_field_id, ts_language_field_id_for_name.

Definition at line 431 of file tree_cursor.c.

431  {
432  const TreeCursor *self = (const TreeCursor *)_self;
433 
434  // Walk up the tree, visiting the current node and its invisible ancestors.
435  for (unsigned i = self->stack.size - 1; i > 0; i--) {
436  TreeCursorEntry *entry = &self->stack.contents[i];
437  TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
438 
439  // Stop walking up when another visible node is found.
440  if (i != self->stack.size - 1) {
441  if (ts_subtree_visible(*entry->subtree)) break;
442  if (
443  !ts_subtree_extra(*entry->subtree) &&
445  self->tree->language,
446  parent_entry->subtree->ptr->production_id,
447  entry->structural_child_index
448  )
449  ) break;
450  }
451 
452  if (ts_subtree_extra(*entry->subtree)) break;
453 
454  const TSFieldMapEntry *field_map, *field_map_end;
456  self->tree->language,
457  parent_entry->subtree->ptr->production_id,
458  &field_map, &field_map_end
459  );
460  for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) {
461  if (!i->inherited && i->child_index == entry->structural_child_index) {
462  return i->field_id;
463  }
464  }
465  }
466  return 0;
467 }
lzma_index ** i
Definition: index.h:629
static void ts_language_field_map(const TSLanguage *self, uint32_t production_id, const TSFieldMapEntry **start, const TSFieldMapEntry **end)
Definition: language.h:246
static TSSymbol ts_language_alias_at(const TSLanguage *self, uint32_t production_id, uint32_t child_index)
Definition: language.h:236
uint16_t production_id
Definition: subtree.h:140
Definition: zipcmp.c:77

References i, SubtreeHeapData::production_id, Subtree::ptr, TreeCursorEntry::subtree, ts_language_alias_at(), ts_language_field_map(), ts_subtree_extra(), and ts_subtree_visible().

Referenced by ts_tree_cursor_current_field_id_wasm(), and ts_tree_cursor_current_field_name().

◆ ts_tree_cursor_current_field_name()

const char* ts_tree_cursor_current_field_name ( const TSTreeCursor _self)

Get the field name of the tree cursor's current node.

This returns NULL if the current node doesn't have a field. See also ts_node_child_by_field_name.

Definition at line 469 of file tree_cursor.c.

469  {
471  if (id) {
472  const TreeCursor *self = (const TreeCursor *)_self;
473  return self->tree->language->field_names[id];
474  } else {
475  return NULL;
476  }
477 }
int id
Definition: op.c:540
uint16_t TSFieldId
Definition: parser.h:20
const char *const * field_names
Definition: parser.h:106
const TSLanguage * language
Definition: tree.h:17
TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self)
Definition: tree_cursor.c:431

References id, NULL, TSTreeCursor::tree, and ts_tree_cursor_current_field_id().

◆ ts_tree_cursor_current_node()

TSNode ts_tree_cursor_current_node ( const TSTreeCursor _self)

Get the tree cursor's current node.

Definition at line 262 of file tree_cursor.c.

262  {
263  const TreeCursor *self = (const TreeCursor *)_self;
264  TreeCursorEntry *last_entry = array_back(&self->stack);
265  TSSymbol alias_symbol = 0;
266  if (self->stack.size > 1 && !ts_subtree_extra(*last_entry->subtree)) {
267  TreeCursorEntry *parent_entry = &self->stack.contents[self->stack.size - 2];
268  alias_symbol = ts_language_alias_at(
269  self->tree->language,
270  parent_entry->subtree->ptr->production_id,
271  last_entry->structural_child_index
272  );
273  }
274  return ts_node_new(
275  self->tree,
276  last_entry->subtree,
277  last_entry->position,
278  alias_symbol
279  );
280 }
#define array_back(self)
Definition: array.h:33
TSNode ts_node_new(const TSTree *tree, const Subtree *subtree, Length position, TSSymbol alias)
Definition: node.c:17
uint16_t TSSymbol
Definition: parser.h:19
Length position
Definition: tree_cursor.h:8
uint32_t structural_child_index
Definition: tree_cursor.h:10

References array_back, TreeCursorEntry::position, SubtreeHeapData::production_id, Subtree::ptr, TreeCursorEntry::structural_child_index, TreeCursorEntry::subtree, ts_language_alias_at(), ts_node_new(), and ts_subtree_extra().

Referenced by ts_node_children_wasm(), ts_node_descendants_of_type_wasm(), ts_node_named_children_wasm(), ts_query_cursor__advance(), ts_tree_cursor_current_node_id_wasm(), ts_tree_cursor_current_node_is_missing_wasm(), ts_tree_cursor_current_node_is_named_wasm(), ts_tree_cursor_current_node_type_id_wasm(), ts_tree_cursor_current_node_wasm(), ts_tree_cursor_end_index_wasm(), ts_tree_cursor_end_position_wasm(), ts_tree_cursor_start_index_wasm(), and ts_tree_cursor_start_position_wasm().

◆ ts_tree_cursor_current_status()

void ts_tree_cursor_current_status ( const TSTreeCursor _self,
TSFieldId field_id,
bool has_later_siblings,
bool has_later_named_siblings,
bool can_have_later_siblings_with_this_field,
TSSymbol supertypes,
unsigned supertype_count 
)

Definition at line 284 of file tree_cursor.c.

292  {
293  const TreeCursor *self = (const TreeCursor *)_self;
294  unsigned max_supertypes = *supertype_count;
295  *field_id = 0;
296  *supertype_count = 0;
297  *has_later_siblings = false;
298  *has_later_named_siblings = false;
299  *can_have_later_siblings_with_this_field = false;
300 
301  // Walk up the tree, visiting the current node and its invisible ancestors,
302  // because fields can refer to nodes through invisible *wrapper* nodes,
303  for (unsigned i = self->stack.size - 1; i > 0; i--) {
304  TreeCursorEntry *entry = &self->stack.contents[i];
305  TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
306 
307  const TSSymbol *alias_sequence = ts_language_alias_sequence(
308  self->tree->language,
309  parent_entry->subtree->ptr->production_id
310  );
311 
312  #define subtree_symbol(subtree, structural_child_index) \
313  (( \
314  !ts_subtree_extra(subtree) && \
315  alias_sequence && \
316  alias_sequence[structural_child_index] \
317  ) ? \
318  alias_sequence[structural_child_index] : \
319  ts_subtree_symbol(subtree))
320 
321  // Stop walking up when a visible ancestor is found.
322  TSSymbol entry_symbol = subtree_symbol(
323  *entry->subtree,
324  entry->structural_child_index
325  );
327  self->tree->language,
328  entry_symbol
329  );
330  if (i != self->stack.size - 1 && entry_metadata.visible) break;
331 
332  // Record any supertypes
333  if (entry_metadata.supertype && *supertype_count < max_supertypes) {
334  supertypes[*supertype_count] = entry_symbol;
335  (*supertype_count)++;
336  }
337 
338  // Determine if the current node has later siblings.
339  if (!*has_later_siblings) {
340  unsigned sibling_count = parent_entry->subtree->ptr->child_count;
341  unsigned structural_child_index = entry->structural_child_index;
342  if (!ts_subtree_extra(*entry->subtree)) structural_child_index++;
343  for (unsigned j = entry->child_index + 1; j < sibling_count; j++) {
344  Subtree sibling = ts_subtree_children(*parent_entry->subtree)[j];
346  self->tree->language,
347  subtree_symbol(sibling, structural_child_index)
348  );
349  if (sibling_metadata.visible) {
350  *has_later_siblings = true;
351  if (*has_later_named_siblings) break;
352  if (sibling_metadata.named) {
353  *has_later_named_siblings = true;
354  break;
355  }
356  } else if (ts_subtree_visible_child_count(sibling) > 0) {
357  *has_later_siblings = true;
358  if (*has_later_named_siblings) break;
359  if (sibling.ptr->named_child_count > 0) {
360  *has_later_named_siblings = true;
361  break;
362  }
363  }
364  if (!ts_subtree_extra(sibling)) structural_child_index++;
365  }
366  }
367 
368  #undef subtree_symbol
369 
370  if (!ts_subtree_extra(*entry->subtree)) {
371  const TSFieldMapEntry *field_map, *field_map_end;
373  self->tree->language,
374  parent_entry->subtree->ptr->production_id,
375  &field_map, &field_map_end
376  );
377 
378  // Look for a field name associated with the current node.
379  if (!*field_id) {
380  for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) {
381  if (!i->inherited && i->child_index == entry->structural_child_index) {
382  *field_id = i->field_id;
383  break;
384  }
385  }
386  }
387 
388  // Determine if the current node can have later siblings with the same field name.
389  if (*field_id) {
390  for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) {
391  if (
392  i->field_id == *field_id &&
393  i->child_index > entry->structural_child_index
394  ) {
395  *can_have_later_siblings_with_this_field = true;
396  break;
397  }
398  }
399  }
400  }
401  }
402 }
TSSymbolMetadata ts_language_symbol_metadata(const TSLanguage *self, TSSymbol symbol)
Definition: language.c:38
static const TSSymbol * ts_language_alias_sequence(const TSLanguage *self, uint32_t production_id)
Definition: language.h:227
@ field_id
Definition: parser.c:1736
uint32_t named_child_count
Definition: subtree.h:136
bool visible
Definition: parser.h:36
bool supertype
Definition: parser.h:38
static uint32_t ts_subtree_visible_child_count(Subtree self)
Definition: subtree.h:294
#define subtree_symbol(subtree, structural_child_index)

References SubtreeHeapData::child_count, field_id, i, TSSymbolMetadata::named, SubtreeHeapData::named_child_count, SubtreeHeapData::production_id, Subtree::ptr, TreeCursorEntry::subtree, subtree_symbol, TSSymbolMetadata::supertype, ts_language_alias_sequence(), ts_language_field_map(), ts_language_symbol_metadata(), ts_subtree_children, ts_subtree_extra(), ts_subtree_visible_child_count(), and TSSymbolMetadata::visible.

Referenced by ts_query_cursor__advance().

◆ ts_tree_cursor_delete()

void ts_tree_cursor_delete ( TSTreeCursor _self)

Delete a tree cursor, freeing all of the memory that it used.

Definition at line 94 of file tree_cursor.c.

94  {
95  TreeCursor *self = (TreeCursor *)_self;
96  array_delete(&self->stack);
97 }
#define array_delete(self)
Definition: array.h:41

References array_delete.

Referenced by ts_query_cursor_delete(), and ts_tree_cursor_delete_wasm().

◆ ts_tree_cursor_goto_first_child()

bool ts_tree_cursor_goto_first_child ( TSTreeCursor _self)

Move the cursor to the first child of its current node.

This returns true if the cursor successfully moved, and returns false if there were no children.

Definition at line 101 of file tree_cursor.c.

101  {
102  TreeCursor *self = (TreeCursor *)_self;
103 
104  bool did_descend;
105  do {
106  did_descend = false;
107 
108  bool visible;
111  while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
112  if (visible) {
113  array_push(&self->stack, entry);
114  return true;
115  }
116 
117  if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
118  array_push(&self->stack, entry);
119  did_descend = true;
120  break;
121  }
122  }
123  } while (did_descend);
124 
125  return false;
126 }
const MCPhysReg * iterator
#define array_push(self, element)
Definition: array.h:43
static CursorChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self)
Definition: tree_cursor.c:18
static bool ts_tree_cursor_child_iterator_next(CursorChildIterator *self, TreeCursorEntry *result, bool *visible)
Definition: tree_cursor.c:37

References array_push, ts_subtree_visible_child_count(), ts_tree_cursor_child_iterator_next(), and ts_tree_cursor_iterate_children().

Referenced by ts_node_children_wasm(), ts_node_descendants_of_type_wasm(), ts_node_named_children_wasm(), ts_query_cursor__advance(), ts_tree_cursor_goto_first_child_wasm(), and ts_tree_cursor_goto_next_sibling().

◆ ts_tree_cursor_goto_first_child_for_byte()

int64_t ts_tree_cursor_goto_first_child_for_byte ( TSTreeCursor _self,
uint32_t  goal_byte 
)

Move the cursor to the first child of its current node that extends beyond the given byte offset or point.

This returns the index of the child node if one was found, and returns -1 if no such child was found.

Definition at line 128 of file tree_cursor.c.

128  {
129  TreeCursor *self = (TreeCursor *)_self;
130  uint32_t initial_size = self->stack.size;
131  uint32_t visible_child_index = 0;
132 
133  bool did_descend;
134  do {
135  did_descend = false;
136 
137  bool visible;
140  while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
141  uint32_t end_byte = entry.position.bytes + ts_subtree_size(*entry.subtree).bytes;
142  bool at_goal = end_byte >= goal_byte;
143  uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree);
144 
145  if (at_goal) {
146  if (visible) {
147  array_push(&self->stack, entry);
148  return visible_child_index;
149  }
150 
151  if (visible_child_count > 0) {
152  array_push(&self->stack, entry);
153  did_descend = true;
154  break;
155  }
156  } else if (visible) {
157  visible_child_index++;
158  } else {
159  visible_child_index += visible_child_count;
160  }
161  }
162  } while (did_descend);
163 
164  self->stack.size = initial_size;
165  return -1;
166 }
unsigned int uint32_t
Definition: sftypes.h:29
uint32_t bytes
Definition: length.h:10

References array_push, Length::bytes, ts_subtree_size(), ts_subtree_visible_child_count(), ts_tree_cursor_child_iterator_next(), and ts_tree_cursor_iterate_children().

◆ ts_tree_cursor_goto_first_child_for_point()

int64_t ts_tree_cursor_goto_first_child_for_point ( TSTreeCursor _self,
TSPoint  goal_point 
)

Definition at line 168 of file tree_cursor.c.

168  {
169  TreeCursor *self = (TreeCursor *)_self;
170  uint32_t initial_size = self->stack.size;
171  uint32_t visible_child_index = 0;
172 
173  bool did_descend;
174  do {
175  did_descend = false;
176 
177  bool visible;
180  while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
181  TSPoint end_point = point_add(entry.position.extent, ts_subtree_size(*entry.subtree).extent);
182  bool at_goal = point_gte(end_point, goal_point);
183  uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree);
184  if (at_goal) {
185  if (visible) {
186  array_push(&self->stack, entry);
187  return visible_child_index;
188  }
189  if (visible_child_count > 0) {
190  array_push(&self->stack, entry);
191  did_descend = true;
192  break;
193  }
194  } else if (visible) {
195  visible_child_index++;
196  } else {
197  visible_child_index += visible_child_count;
198  }
199  }
200  } while (did_descend);
201 
202  self->stack.size = initial_size;
203  return -1;
204 }
static TSPoint point_add(TSPoint a, TSPoint b)
Definition: point.h:14
static bool point_gte(TSPoint a, TSPoint b)
Definition: point.h:40
TSPoint extent
Definition: length.h:11
Definition: api.h:55

References array_push, Length::extent, point_add(), point_gte(), ts_subtree_size(), ts_subtree_visible_child_count(), ts_tree_cursor_child_iterator_next(), and ts_tree_cursor_iterate_children().

◆ ts_tree_cursor_goto_next_sibling()

bool ts_tree_cursor_goto_next_sibling ( TSTreeCursor _self)

Move the cursor to the next sibling of its current node.

This returns true if the cursor successfully moved, and returns false if there was no next sibling node.

Definition at line 206 of file tree_cursor.c.

206  {
207  TreeCursor *self = (TreeCursor *)_self;
208  uint32_t initial_size = self->stack.size;
209 
210  while (self->stack.size > 1) {
211  TreeCursorEntry entry = array_pop(&self->stack);
213  iterator.child_index = entry.child_index;
214  iterator.structural_child_index = entry.structural_child_index;
215  iterator.position = entry.position;
216 
217  bool visible = false;
219  if (visible && self->stack.size + 1 < initial_size) break;
220 
221  while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
222  if (visible) {
223  array_push(&self->stack, entry);
224  return true;
225  }
226 
227  if (ts_subtree_visible_child_count(*entry.subtree)) {
228  array_push(&self->stack, entry);
230  return true;
231  }
232  }
233  }
234 
235  self->stack.size = initial_size;
236  return false;
237 }
#define array_pop(self)
Definition: array.h:82
bool ts_tree_cursor_goto_first_child(TSTreeCursor *_self)
Definition: tree_cursor.c:101

References array_pop, array_push, ts_subtree_visible_child_count(), ts_tree_cursor_child_iterator_next(), ts_tree_cursor_goto_first_child(), and ts_tree_cursor_iterate_children().

Referenced by ts_node_children_wasm(), ts_node_descendants_of_type_wasm(), ts_node_named_children_wasm(), ts_query_cursor__advance(), and ts_tree_cursor_goto_next_sibling_wasm().

◆ ts_tree_cursor_goto_parent()

bool ts_tree_cursor_goto_parent ( TSTreeCursor _self)

Move the cursor to the parent of its current node.

This returns true if the cursor successfully moved, and returns false if there was no parent node (the cursor was already on the root node).

Definition at line 239 of file tree_cursor.c.

239  {
240  TreeCursor *self = (TreeCursor *)_self;
241  for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
242  TreeCursorEntry *entry = &self->stack.contents[i];
243  if (ts_subtree_visible(*entry->subtree)) {
244  self->stack.size = i + 1;
245  return true;
246  }
247  if (i > 0 && !ts_subtree_extra(*entry->subtree)) {
248  TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
250  self->tree->language,
251  parent_entry->subtree->ptr->production_id,
252  entry->structural_child_index
253  )) {
254  self->stack.size = i + 1;
255  return true;
256  }
257  }
258  }
259  return false;
260 }
zip_uint64_t size
Definition: zipcmp.c:79

References i, SubtreeHeapData::production_id, Subtree::ptr, entry::size, TreeCursorEntry::subtree, ts_language_alias_at(), ts_subtree_extra(), and ts_subtree_visible().

Referenced by ts_node_descendants_of_type_wasm(), ts_query_cursor__advance(), and ts_tree_cursor_goto_parent_wasm().

◆ ts_tree_cursor_init()

void ts_tree_cursor_init ( TreeCursor self,
TSNode  node 
)

Definition at line 80 of file tree_cursor.c.

80  {
81  self->tree = node.tree;
82  array_clear(&self->stack);
83  array_push(&self->stack, ((TreeCursorEntry) {
84  .subtree = (const Subtree *)node.id,
85  .position = {
86  ts_node_start_byte(node),
87  ts_node_start_point(node)
88  },
89  .child_index = 0,
90  .structural_child_index = 0,
91  }));
92 }
#define array_clear(self)
Definition: array.h:35
const TSTree * tree
Definition: api.h:95

References array_clear, array_push, and TSNode::tree.

Referenced by ts_tree_cursor_new(), ts_tree_cursor_reset(), and ts_tree_get_changed_ranges().

◆ ts_tree_cursor_iterate_children()

static CursorChildIterator ts_tree_cursor_iterate_children ( const TreeCursor self)
inlinestatic

Definition at line 18 of file tree_cursor.c.

18  {
19  TreeCursorEntry *last_entry = array_back(&self->stack);
20  if (ts_subtree_child_count(*last_entry->subtree) == 0) {
21  return (CursorChildIterator) {NULL_SUBTREE, self->tree, length_zero(), 0, 0, NULL};
22  }
23  const TSSymbol *alias_sequence = ts_language_alias_sequence(
24  self->tree->language,
25  last_entry->subtree->ptr->production_id
26  );
27  return (CursorChildIterator) {
28  .tree = self->tree,
29  .parent = *last_entry->subtree,
30  .position = last_entry->position,
31  .child_index = 0,
32  .structural_child_index = 0,
33  .alias_sequence = alias_sequence,
34  };
35 }
static Length length_zero(void)
Definition: length.h:39
static uint32_t ts_subtree_child_count(Subtree self)
Definition: subtree.h:282
#define NULL_SUBTREE
Definition: subtree.h:19

References array_back, length_zero(), NULL, NULL_SUBTREE, TreeCursorEntry::position, SubtreeHeapData::production_id, Subtree::ptr, TreeCursorEntry::subtree, ts_language_alias_sequence(), and ts_subtree_child_count().

Referenced by ts_tree_cursor_goto_first_child(), ts_tree_cursor_goto_first_child_for_byte(), ts_tree_cursor_goto_first_child_for_point(), and ts_tree_cursor_goto_next_sibling().

◆ ts_tree_cursor_new()

TSTreeCursor ts_tree_cursor_new ( TSNode  node)

Create a new tree cursor starting from the given node.

A tree cursor allows you to walk a syntax tree more efficiently than is possible using the TSNode functions. It is a mutable object that is always on a certain syntax node, and can be moved imperatively to different nodes.

Definition at line 70 of file tree_cursor.c.

70  {
71  TSTreeCursor self = {NULL, NULL, {0, 0}};
72  ts_tree_cursor_init((TreeCursor *)&self, node);
73  return self;
74 }
void ts_tree_cursor_init(TreeCursor *self, TSNode node)
Definition: tree_cursor.c:80

References NULL, and ts_tree_cursor_init().

Referenced by ts_tree_cursor_new_wasm().

◆ ts_tree_cursor_parent_node()

TSNode ts_tree_cursor_parent_node ( const TSTreeCursor _self)

Definition at line 404 of file tree_cursor.c.

404  {
405  const TreeCursor *self = (const TreeCursor *)_self;
406  for (int i = (int)self->stack.size - 2; i >= 0; i--) {
407  TreeCursorEntry *entry = &self->stack.contents[i];
408  bool is_visible = true;
409  TSSymbol alias_symbol = 0;
410  if (i > 0) {
411  TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
412  alias_symbol = ts_language_alias_at(
413  self->tree->language,
414  parent_entry->subtree->ptr->production_id,
415  entry->structural_child_index
416  );
417  is_visible = (alias_symbol != 0) || ts_subtree_visible(*entry->subtree);
418  }
419  if (is_visible) {
420  return ts_node_new(
421  self->tree,
422  entry->subtree,
423  entry->position,
424  alias_symbol
425  );
426  }
427  }
428  return ts_node_new(NULL, NULL, length_zero(), 0);
429 }

References i, length_zero(), NULL, SubtreeHeapData::production_id, Subtree::ptr, TreeCursorEntry::subtree, ts_language_alias_at(), ts_node_new(), and ts_subtree_visible().

Referenced by ts_query_cursor__advance().

◆ ts_tree_cursor_reset()

void ts_tree_cursor_reset ( TSTreeCursor _self,
TSNode  node 
)

Re-initialize a tree cursor to start at a different node.

Definition at line 76 of file tree_cursor.c.

76  {
77  ts_tree_cursor_init((TreeCursor *)_self, node);
78 }

References ts_tree_cursor_init().

Referenced by ts_node_children_wasm(), ts_node_descendants_of_type_wasm(), ts_node_named_children_wasm(), ts_query_cursor_exec(), and ts_tree_cursor_reset_wasm().