API extensions
This commit is contained in:
parent
08f4e82bb2
commit
c47e217e73
14 changed files with 741 additions and 29 deletions
|
|
@ -97,6 +97,40 @@ static inline bool ts_tree_cursor_child_iterator_next(
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline bool ts_tree_cursor_child_iterator_previous(
|
||||
CursorChildIterator *self,
|
||||
TreeCursorEntry *result,
|
||||
bool *visible
|
||||
) {
|
||||
// this is mostly a reverse `ts_tree_cursor_child_iterator_next` taking into
|
||||
// account unsigned underflow
|
||||
if (!self->parent.ptr || (int8_t)self->child_index == -1) return false;
|
||||
const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
|
||||
*result = (TreeCursorEntry) {
|
||||
.subtree = child,
|
||||
.position = self->position,
|
||||
.child_index = self->child_index,
|
||||
.structural_child_index = self->structural_child_index,
|
||||
};
|
||||
*visible = ts_subtree_visible(*child);
|
||||
bool extra = ts_subtree_extra(*child);
|
||||
if (!extra && self->alias_sequence) {
|
||||
*visible |= self->alias_sequence[self->structural_child_index];
|
||||
self->structural_child_index--;
|
||||
}
|
||||
|
||||
self->position = length_sub(self->position, ts_subtree_padding(*child));
|
||||
self->child_index--;
|
||||
|
||||
// unsigned can underflow so compare it to child_count
|
||||
if (self->child_index < self->parent.ptr->child_count) {
|
||||
Subtree previous_child = ts_subtree_children(self->parent)[self->child_index];
|
||||
self->position = length_sub(self->position, ts_subtree_size(previous_child));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TSTreeCursor - lifecycle
|
||||
|
||||
TSTreeCursor ts_tree_cursor_new(TSNode node) {
|
||||
|
|
@ -163,6 +197,47 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
|
|||
return false;
|
||||
}
|
||||
|
||||
TreeCursorStep ts_tree_cursor_goto_last_child_internal(TSTreeCursor *_self) {
|
||||
TreeCursor *self = (TreeCursor *)_self;
|
||||
bool visible;
|
||||
TreeCursorEntry entry;
|
||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
||||
if (!iterator.parent.ptr || iterator.parent.ptr->child_count == 0) return TreeCursorStepNone;
|
||||
|
||||
TreeCursorEntry last_entry;
|
||||
bool last_visible;
|
||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
||||
if (visible) {
|
||||
last_entry = entry;
|
||||
last_visible = true;
|
||||
}
|
||||
else if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
|
||||
last_entry = entry;
|
||||
last_visible = false;
|
||||
}
|
||||
}
|
||||
if (last_entry.subtree) {
|
||||
array_push(&self->stack, last_entry);
|
||||
return last_visible? TreeCursorStepVisible : TreeCursorStepHidden;
|
||||
}
|
||||
|
||||
return TreeCursorStepNone;
|
||||
}
|
||||
|
||||
bool ts_tree_cursor_goto_last_child(TSTreeCursor *self) {
|
||||
for (;;) {
|
||||
switch (ts_tree_cursor_goto_last_child_internal(self)) {
|
||||
case TreeCursorStepHidden:
|
||||
continue;
|
||||
case TreeCursorStepVisible:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point(
|
||||
TSTreeCursor *_self,
|
||||
uint32_t goal_byte,
|
||||
|
|
@ -213,7 +288,9 @@ int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint go
|
|||
return ts_tree_cursor_goto_first_child_for_byte_and_point(self, 0, goal_point);
|
||||
}
|
||||
|
||||
TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
|
||||
TreeCursorStep ts_tree_cursor_goto_sibling_internal(
|
||||
TSTreeCursor *_self,
|
||||
bool (*advance)(CursorChildIterator *, TreeCursorEntry *, bool *)) {
|
||||
TreeCursor *self = (TreeCursor *)_self;
|
||||
uint32_t initial_size = self->stack.size;
|
||||
|
||||
|
|
@ -226,10 +303,10 @@ TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
|
|||
iterator.descendant_index = entry.descendant_index;
|
||||
|
||||
bool visible = false;
|
||||
ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible);
|
||||
advance(&iterator, &entry, &visible);
|
||||
if (visible && self->stack.size + 1 < initial_size) break;
|
||||
|
||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
||||
while (advance(&iterator, &entry, &visible)) {
|
||||
if (visible) {
|
||||
array_push(&self->stack, entry);
|
||||
return TreeCursorStepVisible;
|
||||
|
|
@ -246,6 +323,10 @@ TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
|
|||
return TreeCursorStepNone;
|
||||
}
|
||||
|
||||
TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
|
||||
return ts_tree_cursor_goto_sibling_internal(_self, ts_tree_cursor_child_iterator_next);
|
||||
}
|
||||
|
||||
bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
|
||||
switch (ts_tree_cursor_goto_next_sibling_internal(self)) {
|
||||
case TreeCursorStepHidden:
|
||||
|
|
@ -258,6 +339,50 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
|
|||
}
|
||||
}
|
||||
|
||||
TreeCursorStep ts_tree_cursor_goto_previous_sibling_internal(TSTreeCursor *_self) {
|
||||
// since subtracting across row loses column information, we may have to
|
||||
// restore it
|
||||
TreeCursor *self = (TreeCursor *)_self;
|
||||
|
||||
// for that, save current position before traversing
|
||||
Length position = array_back(&self->stack)->position;
|
||||
TreeCursorStep step = ts_tree_cursor_goto_sibling_internal(
|
||||
_self, ts_tree_cursor_child_iterator_previous);
|
||||
if (step == TreeCursorStepNone)
|
||||
return step;
|
||||
|
||||
// if row has not changed, column is still valid
|
||||
if (array_back(&self->stack)->position.extent.row == position.extent.row)
|
||||
return step;
|
||||
|
||||
// restore position from the parent node
|
||||
const TreeCursorEntry *parent = &self->stack.contents[self->stack.size - 2];
|
||||
position = parent->position;
|
||||
uint32_t child_index = array_back(&self->stack)->child_index;
|
||||
const Subtree *children = ts_subtree_children((*(parent->subtree)));
|
||||
for (uint32_t i = 0; i < child_index; ++i) {
|
||||
position = length_add(position, ts_subtree_total_size(children[i]));
|
||||
}
|
||||
if (child_index > 0)
|
||||
position = length_add(position, ts_subtree_padding(children[child_index]));
|
||||
|
||||
array_back(&self->stack)->position = position;
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self) {
|
||||
switch (ts_tree_cursor_goto_previous_sibling_internal(self)) {
|
||||
case TreeCursorStepHidden:
|
||||
ts_tree_cursor_goto_last_child(self);
|
||||
return true;
|
||||
case TreeCursorStepVisible:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ts_tree_cursor_goto_parent(TSTreeCursor *_self) {
|
||||
TreeCursor *self = (TreeCursor *)_self;
|
||||
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
|
||||
|
|
@ -556,3 +681,11 @@ TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *_cursor) {
|
|||
array_push_all(©->stack, &cursor->stack);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ts_tree_cursor_reset_to(TSTreeCursor *_dst, const TSTreeCursor *_src) {
|
||||
const TreeCursor *cursor = (const TreeCursor *)_src;
|
||||
TreeCursor *copy = (TreeCursor *)_dst;
|
||||
copy->tree = cursor->tree;
|
||||
array_clear(©->stack);
|
||||
array_push_all(©->stack, &cursor->stack);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue