tree-sitter/src/runtime/tree_cursor.c
Max Brunsfeld 666dfb76d2 Remove document parameter from ts_node_type, ts_node_string
Co-Authored-By: Rick Winfrey <rewinfrey@github.com>
2018-05-09 16:47:47 -07:00

134 lines
3.8 KiB
C

#include "tree_sitter/runtime.h"
#include "runtime/alloc.h"
#include "runtime/tree_cursor.h"
#include "runtime/document.h"
#include "runtime/language.h"
TSTreeCursor *ts_tree_cursor_new(const TSDocument *document) {
TSTreeCursor *self = ts_malloc(sizeof(TSTreeCursor));
self->document = document;
array_init(&self->stack);
array_push(&self->stack, ((TreeCursorEntry) {
.tree = document->tree,
.position = length_zero(),
.child_index = 0,
.structural_child_index = 0,
}));
return self;
}
void ts_tree_cursor_delete(TSTreeCursor *self) {
array_delete(&self->stack);
ts_free(self);
}
bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
TreeCursorEntry *last_entry = array_back(&self->stack);
Tree *tree = last_entry->tree;
Length position = last_entry->position;
bool did_descend;
do {
did_descend = false;
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < tree->children.size; i++) {
Tree *child = tree->children.contents[i];
if (child->visible || child->visible_child_count > 0) {
array_push(&self->stack, ((TreeCursorEntry) {
.tree = child,
.child_index = i,
.structural_child_index = structural_child_index,
.position = position,
}));
if (child->visible) {
return true;
} else {
tree = child;
did_descend = true;
break;
}
}
if (!child->extra) structural_child_index++;
position = length_add(position, ts_tree_total_size(child));
}
} while (did_descend);
return false;
}
bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
TreeCursorEntry *child_entry = array_back(&self->stack);
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *parent_entry = &self->stack.contents[i];
Tree *parent = parent_entry->tree;
uint32_t child_index = child_entry->child_index;
uint32_t structural_child_index = child_entry->structural_child_index;
Length position = child_entry->position;
Tree *child = parent->children.contents[child_index];
while (++child_index < parent->children.size) {
if (!child->extra) structural_child_index++;
position = length_add(position, ts_tree_total_size(child));
child = parent->children.contents[child_index];
if (child->visible || child->visible_child_count > 0) {
self->stack.contents[i + 1] = (TreeCursorEntry) {
.tree = child,
.child_index = child_index,
.structural_child_index = structural_child_index,
.position = position,
};
self->stack.size = i + 2;
if (child->visible) {
return true;
} else {
ts_tree_cursor_goto_first_child(self);
return true;
}
}
}
child_entry = parent_entry;
if (parent->visible) break;
}
return false;
}
bool ts_tree_cursor_goto_parent(TSTreeCursor *self) {
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *entry = &self->stack.contents[i];
if (entry->tree->visible) {
self->stack.size = i + 1;
return true;
}
}
return false;
}
TSNode ts_tree_cursor_current_node(TSTreeCursor *self) {
TreeCursorEntry *last_entry = array_back(&self->stack);
TSSymbol alias_symbol = 0;
if (self->stack.size > 1) {
TreeCursorEntry *parent_entry = &self->stack.contents[self->stack.size - 2];
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->document->parser.language,
parent_entry->tree->alias_sequence_id
);
if (alias_sequence) {
alias_symbol = alias_sequence[last_entry->structural_child_index];
}
}
return (TSNode) {
.document = self->document,
.subtree = last_entry->tree,
.position = last_entry->position.extent,
.byte = last_entry->position.bytes,
.alias_symbol = alias_symbol,
};
}