Extract an iterator from TreeCursor methods

This commit is contained in:
Max Brunsfeld 2018-05-22 14:42:57 -07:00
parent c0763c69c4
commit babb8261a3
2 changed files with 114 additions and 123 deletions

View file

@ -10,7 +10,7 @@ typedef struct {
uint32_t child_index;
uint32_t structural_child_index;
const TSSymbol *alias_sequence;
} NodeChildIterator;
} ChildIterator;
// TSNode - constructors
@ -48,16 +48,16 @@ static inline const TSTree *ts_node__tree(const TSNode *self) {
return self->tree;
}
// NodeChildIterator
// ChildIterator
static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) {
static inline ChildIterator ts_node_iterate_children(const TSNode *node) {
const TSTree *tree = ts_node__tree(node);
const Subtree *subtree = ts_node__subtree(*node);
const TSSymbol *alias_sequence = ts_language_alias_sequence(
tree->language,
subtree->alias_sequence_id
);
return (NodeChildIterator) {
return (ChildIterator) {
.tree = tree,
.parent = subtree,
.position = {ts_node_start_byte(*node), ts_node_start_point(*node)},
@ -67,7 +67,7 @@ static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node)
};
}
static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) {
static inline bool ts_node_child_iterator_next(ChildIterator *self, TSNode *result) {
if (self->child_index == self->parent->children.size) return false;
const Subtree *child = self->parent->children.contents[self->child_index];
TSSymbol alias_symbol = 0;
@ -133,7 +133,7 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool incl
TSNode child;
uint32_t index = 0;
NodeChildIterator iterator = ts_node_child_iterator_begin(&result);
ChildIterator iterator = ts_node_iterate_children(&result);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (ts_node__is_relevant(child, include_anonymous)) {
if (index == child_index) return child;
@ -168,7 +168,7 @@ static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous)
bool found_child_containing_target = false;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes >= target_end_byte) {
found_child_containing_target = ts_node__subtree(child) != ts_node__subtree(self);
@ -217,7 +217,7 @@ static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous)
TSNode child_containing_target = ts_node__null();
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes < target_end_byte) continue;
if (ts_node_start_byte(child) <= ts_node_start_byte(self)) {
@ -268,7 +268,7 @@ static inline TSNode ts_node__first_child_for_byte(TSNode self, uint32_t goal,
did_descend = false;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (ts_node_end_byte(child) > goal) {
if (ts_node__is_relevant(child, include_anonymous)) {
@ -296,7 +296,7 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi
did_descend = false;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes > max) {
if (ts_node_start_byte(child) > min) break;
@ -324,7 +324,7 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi
did_descend = false;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
const Subtree *child_tree = ts_node__subtree(child);
if (iterator.child_index != 1) {
@ -407,7 +407,7 @@ TSNode ts_node_parent(TSNode self) {
did_descend = false;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
ChildIterator iterator = ts_node_iterate_children(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (
ts_node_start_byte(child) > ts_node_start_byte(self) ||

View file

@ -4,6 +4,56 @@
#include "runtime/language.h"
#include "runtime/tree.h"
typedef struct {
const Subtree *parent;
const TSTree *tree;
Length position;
uint32_t child_index;
uint32_t structural_child_index;
const TSSymbol *alias_sequence;
} ChildIterator;
// ChildIterator
static inline ChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self) {
TreeCursorEntry *last_entry = array_back(&self->stack);
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->tree->language,
last_entry->subtree->alias_sequence_id
);
return (ChildIterator) {
.tree = self->tree,
.parent = last_entry->subtree,
.position = last_entry->position,
.child_index = 0,
.structural_child_index = 0,
.alias_sequence = alias_sequence,
};
}
static inline bool ts_tree_cursor_child_iterator_next(ChildIterator *self,
TreeCursorEntry *result,
bool *visible) {
if (self->child_index == self->parent->children.size) return false;
const Subtree *child = self->parent->children.contents[self->child_index];
*result = (TreeCursorEntry) {
.subtree = child,
.position = self->position,
.child_index = self->child_index,
.structural_child_index = self->structural_child_index,
};
*visible = child->visible;
if (!child->extra && self->alias_sequence) {
*visible |= self->alias_sequence[self->structural_child_index];
}
self->position = length_add(self->position, ts_subtree_total_size(child));
self->child_index++;
if (!child->extra) self->structural_child_index++;
return true;
}
// TSTreeCursor - lifecycle
TSTreeCursor ts_tree_cursor_new(const TSTree *tree) {
TSTreeCursor self;
ts_tree_cursor_init((TreeCursor *)&self, tree);
@ -26,47 +76,29 @@ void ts_tree_cursor_delete(TSTreeCursor *_self) {
array_delete(&self->stack);
}
// TSTreeCursor - walking the tree
bool ts_tree_cursor_goto_first_child(TSTreeCursor *_self) {
TreeCursor *self = (TreeCursor *)_self;
TreeCursorEntry *last_entry = array_back(&self->stack);
const Subtree *subtree = last_entry->subtree;
if (subtree->children.size == 0 || subtree->visible_child_count == 0) return false;
Length position = last_entry->position;
bool did_descend;
do {
did_descend = false;
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->tree->language,
subtree->alias_sequence_id
);
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < subtree->children.size; i++) {
const Subtree *child = subtree->children.contents[i];
bool visible = child->visible;
if (!child->extra) {
visible |= alias_sequence && alias_sequence[structural_child_index];
bool visible;
TreeCursorEntry entry;
ChildIterator iterator = ts_tree_cursor_iterate_children(self);
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
if (visible) {
array_push(&self->stack, entry);
return true;
}
if (visible || (child->children.size > 0 && child->visible_child_count > 0)) {
array_push(&self->stack, ((TreeCursorEntry) {
.subtree = child,
.child_index = i,
.structural_child_index = structural_child_index,
.position = position,
}));
if (visible) {
return true;
} else {
subtree = child;
did_descend = true;
break;
}
if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) {
array_push(&self->stack, entry);
did_descend = true;
break;
}
if (!child->extra) structural_child_index++;
position = length_add(position, ts_subtree_total_size(child));
}
} while (did_descend);
@ -76,59 +108,37 @@ 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) {
TreeCursor *self = (TreeCursor *)_self;
uint32_t initial_size = self->stack.size;
TreeCursorEntry *last_entry = array_back(&self->stack);
const Subtree *subtree = last_entry->subtree;
Length position = last_entry->position;
uint32_t visible_child_index = 0;
bool did_descend;
do {
did_descend = false;
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->tree->language,
subtree->alias_sequence_id
);
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < subtree->children.size; i++) {
const Subtree *child = subtree->children.contents[i];
Length next_position = length_add(position, ts_subtree_total_size(child));
bool at_goal = next_position.bytes > goal_byte;
bool visible = child->visible;
if (!child->extra) {
visible |= alias_sequence && alias_sequence[structural_child_index];
}
uint32_t visible_child_count = child->children.size > 0 ? child->visible_child_count : 0;
bool visible;
TreeCursorEntry entry;
ChildIterator iterator = ts_tree_cursor_iterate_children(self);
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
bool at_goal = iterator.position.bytes > goal_byte;
uint32_t visible_child_count = entry.subtree->children.size > 0
? entry.subtree->visible_child_count
: 0;
if (at_goal) {
if (visible || visible_child_count > 0) {
array_push(&self->stack, ((TreeCursorEntry) {
.subtree = child,
.child_index = i,
.structural_child_index = structural_child_index,
.position = position,
}));
if (visible) {
return visible_child_index;
} else {
subtree = child;
did_descend = true;
break;
}
}
} else {
if (visible) {
visible_child_index++;
} else {
visible_child_index += visible_child_count;
array_push(&self->stack, entry);
return visible_child_index;
}
}
if (!child->extra) structural_child_index++;
position = next_position;
if (visible_child_count > 0) {
array_push(&self->stack, entry);
did_descend = true;
break;
}
} else if (visible) {
visible_child_index++;
} else {
visible_child_index += visible_child_count;
}
}
} while (did_descend);
@ -138,53 +148,34 @@ int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *_self, uint32_t g
bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *_self) {
TreeCursor *self = (TreeCursor *)_self;
TreeCursorEntry *child_entry = array_back(&self->stack);
uint32_t initial_size = self->stack.size;
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *parent_entry = &self->stack.contents[i];
while (self->stack.size > 1) {
bool visible;
TreeCursorEntry entry = array_pop(&self->stack);
ChildIterator iterator = ts_tree_cursor_iterate_children(self);
iterator.child_index = entry.child_index;
iterator.structural_child_index = entry.structural_child_index;
iterator.position = entry.position;
const Subtree *parent = parent_entry->subtree;
uint32_t child_index = child_entry->child_index;
uint32_t structural_child_index = child_entry->structural_child_index;
Length position = child_entry->position;
const Subtree *child = parent->children.contents[child_index];
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->tree->language,
parent->alias_sequence_id
);
ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible);
if (visible && self->stack.size + 1 < initial_size) break;
while (++child_index < parent->children.size) {
if (!child->extra) structural_child_index++;
position = length_add(position, ts_subtree_total_size(child));
child = parent->children.contents[child_index];
bool visible = child->visible;
if (!child->extra) {
visible |= alias_sequence && alias_sequence[structural_child_index];
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
if (visible) {
array_push(&self->stack, entry);
return true;
}
if (visible || (child->children.size > 0 && child->visible_child_count > 0)) {
self->stack.contents[i + 1] = (TreeCursorEntry) {
.subtree = child,
.child_index = child_index,
.structural_child_index = structural_child_index,
.position = position,
};
self->stack.size = i + 2;
if (visible) {
return true;
} else {
ts_tree_cursor_goto_first_child(_self);
return true;
}
if (entry.subtree->children.size > 0 && entry.subtree->visible_child_count > 0) {
array_push(&self->stack, entry);
ts_tree_cursor_goto_first_child(_self);
return true;
}
}
child_entry = parent_entry;
if (parent->visible) break;
}
self->stack.size = initial_size;
return false;
}