diff options
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.c | 714 |
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 | |||
| 7 | typedef 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 | |||
| 19 | static 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 | |||
| 35 | static 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 | |||
| 61 | static 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. | ||
| 104 | static 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 | |||
| 116 | static 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 | |||
| 153 | TSTreeCursor 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 | |||
| 159 | void ts_tree_cursor_reset(TSTreeCursor *_self, TSNode node) { | ||
| 160 | ts_tree_cursor_init((TreeCursor *)_self, node); | ||
| 161 | } | ||
| 162 | |||
| 163 | void 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 | |||
| 179 | void ts_tree_cursor_delete(TSTreeCursor *_self) { | ||
| 180 | TreeCursor *self = (TreeCursor *)_self; | ||
| 181 | array_delete(&self->stack); | ||
| 182 | } | ||
| 183 | |||
| 184 | // TSTreeCursor - walking the tree | ||
| 185 | |||
| 186 | TreeCursorStep 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 | |||
| 204 | bool 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 | |||
| 218 | TreeCursorStep 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 | |||
| 245 | bool 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 | |||
| 259 | static 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 | |||
| 301 | int64_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 | |||
| 305 | int64_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 | |||
| 309 | TreeCursorStep 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 | |||
| 344 | TreeCursorStep 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 | |||
| 348 | bool 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 | |||
| 360 | TreeCursorStep 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 | |||
| 395 | bool 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 | |||
| 407 | bool 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 | |||
| 418 | void 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 | |||
| 469 | uint32_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 | |||
| 475 | TSNode 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. | ||
| 497 | void 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 | |||
| 617 | uint32_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 | |||
| 628 | TSNode 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 | |||
| 655 | TSFieldId 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 | |||
| 686 | const 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 | |||
| 696 | TSTreeCursor 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(©->stack); | ||
| 703 | array_push_all(©->stack, &cursor->stack); | ||
| 704 | return res; | ||
| 705 | } | ||
| 706 | |||
| 707 | void 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(©->stack); | ||
| 713 | array_push_all(©->stack, &cursor->stack); | ||
| 714 | } | ||
