Start work on removing parent pointers

Co-Authored-By: Rick Winfrey <rewinfrey@github.com>
This commit is contained in:
Max Brunsfeld 2018-05-09 10:16:10 -07:00
parent 8300f24fec
commit 973e4a44f0
14 changed files with 410 additions and 324 deletions

View file

@ -58,6 +58,9 @@ extern "C" {
#define array_pop(self) ((self)->contents[--(self)->size])
#define array_assign(self, other) \
array__assign((VoidArray *)(self), (const VoidArray *)(other), array__elem_size(self))
// Private
typedef Array(void) VoidArray;
@ -91,6 +94,12 @@ static inline void array__reserve(VoidArray *self, size_t element_size, uint32_t
}
}
static inline void array__assign(VoidArray *self, const VoidArray *other, size_t element_size) {
array__reserve(self, element_size, other->size);
self->size = other->size;
memcpy(self->contents, other->contents, self->size * element_size);
}
static inline void array__grow(VoidArray *self, size_t element_size) {
if (self->size == self->capacity) {
size_t new_capacity = self->capacity * 2;

View file

@ -1,5 +1,4 @@
#include "runtime/alloc.h"
#include "runtime/node.h"
#include "runtime/tree.h"
#include "runtime/parser.h"
#include "runtime/string_input.h"
@ -171,7 +170,12 @@ void ts_document_invalidate(TSDocument *self) {
}
TSNode ts_document_root_node(const TSDocument *self) {
return ts_node_make(self->tree, 0, 0);
return (TSNode) {
.subtree = self->tree,
.document = self,
.position = {0, 0},
.byte = 0,
};
}
uint32_t ts_document_parse_count(const TSDocument *self) {

View file

@ -1,43 +1,91 @@
#include <stdbool.h>
#include "runtime/node.h"
#include "runtime/tree.h"
#include "runtime/document.h"
#include "runtime/language.h"
TSNode ts_node_make(const Tree *tree, uint32_t byte, uint32_t row) {
return (TSNode){.data = tree, .offset = { byte, row } };
}
// NodeChildIterator
/*
* Private
*/
typedef struct {
const Tree *parent;
const TSDocument *document;
Length position;
uint32_t child_index;
uint32_t structural_child_index;
const TSSymbol *alias_sequence;
} NodeChildIterator;
// TSNode - Private
static inline TSNode ts_node__null() {
return ts_node_make(NULL, 0, 0);
return (TSNode) {
.subtree = NULL,
.document = NULL,
.position = {0, 0},
.byte = 0,
};
}
static inline const Tree *ts_node__tree(TSNode self) {
return self.data;
return self.subtree;
}
static inline uint32_t ts_node__offset_byte(TSNode self) {
return self.offset[0];
static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) {
const Tree *tree = ts_node__tree(*node);
const TSSymbol *alias_sequence = ts_language_alias_sequence(
node->document->parser.language,
tree->alias_sequence_id
);
return (NodeChildIterator) {
.parent = tree,
.document = node->document,
.position = {node->byte, node->position},
.child_index = 0,
.structural_child_index = 0,
.alias_sequence = alias_sequence,
};
}
static inline uint32_t ts_node__offset_row(TSNode self) {
return self.offset[1];
static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) {
if (self->child_index == self->parent->children.size) return false;
Tree *child = self->parent->children.contents[self->child_index];
TSSymbol alias_symbol = 0;
if (!child->extra) {
if (self->alias_sequence) {
alias_symbol = self->alias_sequence[self->structural_child_index];
}
self->structural_child_index++;
}
*result = (TSNode) {
.subtree = child,
.document = self->document,
.position = self->position.extent,
.byte = self->position.bytes,
.alias_symbol = alias_symbol,
};
self->position = length_add(self->position, ts_tree_total_size(child));
self->child_index++;
return true;
}
static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) {
const Tree *tree = ts_node__tree(self);
if (include_anonymous) {
return tree->context.alias_symbol || tree->visible;
return tree->visible || self.alias_symbol;
} else {
return tree->context.alias_is_named || (tree->visible && tree->named);
return (
(tree->visible && tree->named) ||
(
self.alias_symbol &&
ts_language_symbol_metadata(
self.document->parser.language,
self.alias_symbol
).named
)
);
}
}
static inline uint32_t ts_node__relevant_child_count(TSNode self,
bool include_anonymous) {
static inline uint32_t ts_node__relevant_child_count(TSNode self, bool include_anonymous) {
const Tree *tree = ts_node__tree(self);
if (tree->children.size > 0) {
if (include_anonymous) {
@ -50,44 +98,23 @@ static inline uint32_t ts_node__relevant_child_count(TSNode self,
}
}
static inline TSNode ts_node__direct_parent(TSNode self, uint32_t *index) {
const Tree *tree = ts_node__tree(self);
*index = tree->context.index;
return ts_node_make(
tree->context.parent,
ts_node__offset_byte(self) - tree->context.offset.bytes,
ts_node__offset_row(self) - tree->context.offset.extent.row
);
}
static inline TSNode ts_node__direct_child(TSNode self, uint32_t i) {
const Tree *child_tree = ts_node__tree(self)->children.contents[i];
return ts_node_make(
child_tree,
ts_node__offset_byte(self) + child_tree->context.offset.bytes,
ts_node__offset_row(self) + child_tree->context.offset.extent.row
);
}
static inline TSNode ts_node__child(TSNode self, uint32_t child_index,
bool include_anonymous) {
static inline TSNode ts_node__child(TSNode self, uint32_t child_index, bool include_anonymous) {
TSNode result = self;
bool did_descend = true;
while (did_descend) {
did_descend = false;
TSNode child;
uint32_t index = 0;
for (uint32_t i = 0; i < ts_node__tree(result)->children.size; i++) {
TSNode child = ts_node__direct_child(result, i);
NodeChildIterator iterator = ts_node_child_iterator_begin(&result);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (ts_node__is_relevant(child, include_anonymous)) {
if (index == child_index)
return child;
if (index == child_index) return child;
index++;
} else {
uint32_t grandchild_index = child_index - index;
uint32_t grandchild_count =
ts_node__relevant_child_count(child, include_anonymous);
uint32_t grandchild_count = ts_node__relevant_child_count(child, include_anonymous);
if (grandchild_index < grandchild_count) {
did_descend = true;
result = child;
@ -102,48 +129,80 @@ static inline TSNode ts_node__child(TSNode self, uint32_t child_index,
return ts_node__null();
}
static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) {
TSNode result = self;
do {
uint32_t index;
result = ts_node__direct_parent(result, &index);
if (!result.data)
static inline bool ts_node__last_child_before(TSNode self, TSNode target,
bool include_anonymous, TSNode *result) {
TSNode child;
TSNode earlier_child = ts_node__null();
bool earlier_child_is_relevant = false;
bool found_child_containing_target = false;
NodeChildIterator iterator = ts_node_child_iterator_begin(&self);
uint32_t target_end_byte = ts_node_end_byte(target);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes >= target_end_byte) {
found_child_containing_target = true;
break;
for (uint32_t i = index - 1; i + 1 > 0; i--) {
TSNode child = ts_node__direct_child(result, i);
if (ts_node__is_relevant(child, include_anonymous))
return child;
uint32_t grandchild_count =
ts_node__relevant_child_count(child, include_anonymous);
if (grandchild_count > 0)
return ts_node__child(child, grandchild_count - 1, include_anonymous);
}
} while (!ts_node__tree(result)->visible);
return ts_node__null();
if (ts_node__is_relevant(child, include_anonymous)) {
earlier_child = child;
earlier_child_is_relevant = true;
} else if (ts_node__relevant_child_count(child, include_anonymous) > 0) {
earlier_child = child;
earlier_child_is_relevant = false;
}
}
if (found_child_containing_target && child.subtree != target.subtree) {
if (ts_node__last_child_before(child, target, include_anonymous, result)) {
return true;
}
}
if (earlier_child_is_relevant) {
*result = earlier_child;
return true;
}
if (earlier_child.subtree) {
return ts_node__last_child_before(earlier_child, target, include_anonymous, result);
}
return false;
}
static inline TSNode ts_node__prev_sibling(TSNode self, bool include_anonymous) {
TSNode result = ts_node__null();
TSNode parent = ts_node_parent(self);
if (parent.subtree) {
ts_node__last_child_before(parent, self, include_anonymous, &result);
}
return result;
}
static inline TSNode ts_node__next_sibling(TSNode self, bool include_anonymous) {
TSNode result = self;
TSNode node = ts_node_parent(self);
if (!node.subtree) return ts_node__null();
uint32_t end_byte = ts_node_end_byte(self);
do {
uint32_t index;
result = ts_node__direct_parent(result, &index);
if (!result.data)
break;
bool did_descend = true;
while (did_descend) {
did_descend = false;
for (uint32_t i = index + 1; i < ts_node__tree(result)->children.size; i++) {
TSNode child = ts_node__direct_child(result, i);
if (ts_node__is_relevant(child, include_anonymous))
return child;
uint32_t grandchild_count =
ts_node__relevant_child_count(child, include_anonymous);
if (grandchild_count > 0)
return ts_node__child(child, 0, include_anonymous);
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes > end_byte && child.subtree != self.subtree) {
if (ts_node__is_relevant(child, include_anonymous)) {
return child;
}
if (ts_node__relevant_child_count(child, include_anonymous) > 0) {
node = child;
did_descend = true;
break;
}
}
}
} while (!ts_node__tree(result)->visible);
}
return ts_node__null();
}
@ -160,8 +219,9 @@ static inline TSNode ts_node__first_child_for_byte(TSNode self, uint32_t goal,
while (did_descend) {
did_descend = false;
for (uint32_t i = 0; i < ts_node__tree(node)->children.size; i++) {
TSNode child = ts_node__direct_child(node, i);
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (ts_node_end_byte(child) > goal) {
if (ts_node__is_relevant(child, include_anonymous)) {
return child;
@ -187,10 +247,11 @@ static inline TSNode ts_node__descendant_for_byte_range(TSNode self, uint32_t mi
while (did_descend) {
did_descend = false;
for (uint32_t i = 0, n = ts_node__tree(node)->children.size; i < n; i++) {
TSNode child = ts_node__direct_child(node, i);
if (ts_node_end_byte(child) > max) {
if (ts_node_start_byte(child) > min) break;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (iterator.position.bytes > max) {
if (child.byte > min) break;
node = child;
if (ts_node__is_relevant(node, include_anonymous)) last_visible_node = node;
did_descend = true;
@ -214,10 +275,13 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi
while (did_descend) {
did_descend = false;
for (uint32_t i = 0, n = ts_node__tree(node)->children.size; i < n; i++) {
TSNode child = ts_node__direct_child(node, i);
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
const Tree *child_tree = ts_node__tree(child);
if (i > 0) start_position = point_add(start_position, child_tree->padding.extent);
if (iterator.child_index != 1) {
start_position = point_add(start_position, child_tree->padding.extent);
}
end_position = point_add(start_position, child_tree->size.extent);
if (point_gt(end_position, max)) {
if (point_gt(start_position, min)) break;
@ -233,12 +297,10 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi
return last_visible_node;
}
/*
* Public
*/
// TSNode - Public
uint32_t ts_node_start_byte(TSNode self) {
return ts_node__offset_byte(self) + ts_node__tree(self)->padding.bytes;
return self.byte + ts_node__tree(self)->padding.bytes;
}
uint32_t ts_node_end_byte(TSNode self) {
@ -246,21 +308,16 @@ uint32_t ts_node_end_byte(TSNode self) {
}
TSPoint ts_node_start_point(TSNode self) {
const Tree *tree = ts_node__tree(self);
return (TSPoint){ ts_node__offset_row(self) + tree->padding.extent.row,
ts_tree_start_column(tree) };
return point_add(self.position, ts_node__tree(self)->padding.extent);
}
TSPoint ts_node_end_point(TSNode self) {
const Tree *tree = ts_node__tree(self);
return (TSPoint){ ts_node__offset_row(self) + tree->padding.extent.row +
tree->size.extent.row,
ts_tree_end_column(tree) };
return point_add(ts_node_start_point(self), ts_node__tree(self)->size.extent);
}
TSSymbol ts_node_symbol(TSNode self) {
const Tree *tree = ts_node__tree(self);
return tree->context.alias_symbol ? tree->context.alias_symbol : tree->symbol;
return self.alias_symbol ? self.alias_symbol : tree->symbol;
}
const char *ts_node_type(TSNode self, const TSDocument *document) {
@ -272,15 +329,17 @@ char *ts_node_string(TSNode self, const TSDocument *document) {
}
bool ts_node_eq(TSNode self, TSNode other) {
return
return (
ts_tree_eq(ts_node__tree(self), ts_node__tree(other)) &&
self.offset[0] == other.offset[0] &&
self.offset[1] == other.offset[1];
self.byte == other.byte
);
}
bool ts_node_is_named(TSNode self) {
const Tree *tree = ts_node__tree(self);
return tree->context.alias_symbol ? tree->context.alias_is_named : tree->named;
return self.alias_symbol
? ts_language_symbol_metadata(self.document->parser.language, self.alias_symbol).named
: tree->named;
}
bool ts_node_is_missing(TSNode self) {
@ -297,35 +356,31 @@ bool ts_node_has_error(TSNode self) {
}
TSNode ts_node_parent(TSNode self) {
TSNode result = self;
uint32_t index;
TSNode node = ts_document_root_node(self.document);
uint32_t end_byte = ts_node_end_byte(self);
if (node.subtree == self.subtree) return ts_node__null();
do {
result = ts_node__direct_parent(result, &index);
if (!result.data)
return ts_node__null();
} while (!ts_node__tree(result)->visible);
TSNode last_visible_node = node;
bool did_descend = true;
while (did_descend) {
did_descend = false;
return result;
}
uint32_t ts_node_child_index(TSNode self) {
const Tree *tree = ts_node__tree(self);
uint32_t result = 0;
for (;;) {
const Tree *parent = tree->context.parent;
uint32_t index = tree->context.index;
if (!parent) return UINT32_MAX;
for (uint32_t i = 0; i < index; i++) {
Tree *child = parent->children.contents[i];
result += child->visible ? 1 : child->visible_child_count;
TSNode child;
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
while (ts_node_child_iterator_next(&iterator, &child)) {
if (child.byte > self.byte || child.subtree == self.subtree) break;
if (iterator.position.bytes >= end_byte) {
node = child;
if (ts_node__is_relevant(child, true)) {
last_visible_node = node;
}
did_descend = true;
break;
}
}
if (parent->visible) break;
tree = parent;
}
return result;
return last_visible_node;
}
TSNode ts_node_child(TSNode self, uint32_t child_index) {

View file

@ -1,8 +0,0 @@
#ifndef RUNTIME_NODE_H_
#define RUNTIME_NODE_H_
#include "runtime/tree.h"
TSNode ts_node_make(const Tree *, uint32_t byte, uint32_t row);
#endif

View file

@ -119,16 +119,19 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
static void parser__breakdown_lookahead(Parser *self, Tree **lookahead,
TSStateId state,
ReusableNode *reusable_node) {
bool did_break_down = false;
while (reusable_node->tree->children.size > 0 && reusable_node->tree->parse_state != state) {
LOG("state_mismatch sym:%s", SYM_NAME(reusable_node->tree->symbol));
reusable_node_breakdown(reusable_node);
did_break_down = true;
bool did_descend = false;
Tree *tree = reusable_node_tree(reusable_node);
while (tree->children.size > 0 && tree->parse_state != state) {
LOG("state_mismatch sym:%s", SYM_NAME(tree->symbol));
reusable_node_descend(reusable_node);
tree = reusable_node_tree(reusable_node);
did_descend = true;
}
if (did_break_down) {
if (did_descend) {
ts_tree_release(&self->tree_pool, *lookahead);
ts_tree_retain(*lookahead = reusable_node->tree);
*lookahead = tree;
ts_tree_retain(*lookahead);
}
}
@ -419,21 +422,22 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
Tree *last_external_token = ts_stack_last_external_token(self->stack, version);
Tree *result;
while ((result = reusable_node->tree)) {
if (reusable_node->byte_index > position.bytes) {
while ((result = reusable_node_tree(reusable_node))) {
uint32_t byte_offset = reusable_node_byte_offset(reusable_node);
if (byte_offset > position.bytes) {
LOG("before_reusable_node symbol:%s", SYM_NAME(result->symbol));
break;
}
if (reusable_node->byte_index < position.bytes) {
if (byte_offset < position.bytes) {
LOG("past_reusable_node symbol:%s", SYM_NAME(result->symbol));
reusable_node_pop(reusable_node);
reusable_node_advance(reusable_node);
continue;
}
if (!ts_tree_external_token_state_eq(reusable_node->last_external_token, last_external_token)) {
LOG("reusable_node_has_different_external_scanner_state symbol:%s", SYM_NAME(result->symbol));
reusable_node_pop(reusable_node);
reusable_node_advance(reusable_node);
continue;
}
@ -452,8 +456,8 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
if (reason) {
LOG("cant_reuse_node_%s tree:%s", reason, SYM_NAME(result->symbol));
if (!reusable_node_breakdown(reusable_node)) {
reusable_node_pop(reusable_node);
if (!reusable_node_descend(reusable_node)) {
reusable_node_advance(reusable_node);
parser__breakdown_top_of_stack(self, version);
*state = ts_stack_state(self->stack, version);
}
@ -467,7 +471,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
SYM_NAME(result->symbol),
SYM_NAME(result->first_leaf.symbol)
);
reusable_node_pop_leaf(reusable_node);
reusable_node_advance_past_leaf(reusable_node);
break;
}
@ -678,7 +682,7 @@ static void parser__start(Parser *self, TSInput input, Tree *previous_tree) {
ts_lexer_set_input(&self->lexer, input);
ts_stack_clear(self->stack);
self->reusable_node = reusable_node_new(previous_tree);
reusable_node_reset(&self->reusable_node, previous_tree);
self->finished_tree = NULL;
self->accept_count = 0;
self->in_ambiguity = false;
@ -1106,7 +1110,9 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
}
parser__shift(self, version, next_state, lookahead, action.params.extra);
if (lookahead == reusable_node->tree) reusable_node_pop(reusable_node);
if (lookahead == reusable_node_tree(reusable_node)) {
reusable_node_advance(reusable_node);
}
ts_tree_release(&self->tree_pool, lookahead);
return;
}
@ -1136,7 +1142,9 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
parser__breakdown_lookahead(self, &lookahead, state, reusable_node);
}
parser__recover(self, version, lookahead);
if (lookahead == reusable_node->tree) reusable_node_pop(reusable_node);
if (lookahead == reusable_node_tree(reusable_node)) {
reusable_node_advance(reusable_node);
}
ts_tree_release(&self->tree_pool, lookahead);
return;
}
@ -1255,6 +1263,7 @@ bool parser_init(Parser *self) {
ts_tree_pool_init(&self->tree_pool);
self->stack = ts_stack_new(&self->tree_pool);
self->finished_tree = NULL;
self->reusable_node = reusable_node_new();
parser__set_cached_token(self, 0, NULL, NULL);
return true;
}
@ -1277,6 +1286,7 @@ void parser_destroy(Parser *self) {
if (self->reduce_actions.contents)
array_delete(&self->reduce_actions);
ts_tree_pool_delete(&self->tree_pool);
reusable_node_delete(&self->reusable_node);
parser_set_language(self, NULL);
}
@ -1285,11 +1295,12 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err
StackVersion version = STACK_VERSION_NONE;
uint32_t position = 0, last_position = 0;
ReusableNode reusable_node;
ReusableNode reusable_node = reusable_node_new();
reusable_node_assign(&reusable_node, &self->reusable_node);
do {
for (version = 0; version < ts_stack_version_count(self->stack); version++) {
reusable_node = self->reusable_node;
reusable_node_assign(&reusable_node, &self->reusable_node);
while (ts_stack_is_active(self->stack, version)) {
LOG("process version:%d, version_count:%u, state:%d, row:%u, col:%u",
@ -1309,7 +1320,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err
}
}
self->reusable_node = reusable_node;
reusable_node_assign(&self->reusable_node, &reusable_node);
unsigned min_error_cost = parser__condense_stack(self);
if (self->finished_tree && self->finished_tree->error_cost < min_error_cost) {
@ -1322,6 +1333,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err
self->in_ambiguity = version > 1;
} while (version != 0);
reusable_node_delete(&reusable_node);
ts_stack_clear(self->stack);
parser__set_cached_token(self, 0, NULL, NULL);
ts_tree_assign_parents(self->finished_tree, &self->tree_pool, self->language);

View file

@ -2,44 +2,81 @@
typedef struct {
Tree *tree;
uint32_t byte_index;
uint32_t child_index;
uint32_t byte_offset;
} StackEntry;
typedef struct {
Array(StackEntry) stack;
Tree *last_external_token;
} ReusableNode;
static inline ReusableNode reusable_node_new(Tree *tree) {
ReusableNode result = {tree, 0, NULL};
return result;
static inline ReusableNode reusable_node_new() {
return (ReusableNode) {array_new(), NULL};
}
static inline void reusable_node_pop(ReusableNode *self) {
self->byte_index += ts_tree_total_bytes(self->tree);
if (self->tree->has_external_tokens) {
self->last_external_token = ts_tree_last_external_token(self->tree);
}
while (self->tree) {
Tree *parent = self->tree->context.parent;
uint32_t next_index = self->tree->context.index + 1;
if (parent && parent->children.size > next_index) {
self->tree = parent->children.contents[next_index];
return;
}
self->tree = parent;
}
static inline void reusable_node_reset(ReusableNode *self, Tree *tree) {
array_clear(&self->stack);
array_push(&self->stack, ((StackEntry) {
.tree = tree,
.child_index = 0,
.byte_offset = 0,
}));
}
static inline void reusable_node_pop_leaf(ReusableNode *self) {
while (self->tree->children.size > 0) {
self->tree = self->tree->children.contents[0];
}
reusable_node_pop(self);
static inline Tree *reusable_node_tree(ReusableNode *self) {
return array_back(&self->stack)->tree;
}
static inline bool reusable_node_breakdown(ReusableNode *self) {
if (self->tree->children.size == 0) {
return false;
} else {
self->tree = self->tree->children.contents[0];
static inline uint32_t reusable_node_byte_offset(ReusableNode *self) {
return array_back(&self->stack)->byte_offset;
}
static inline void reusable_node_delete(ReusableNode *self) {
array_delete(&self->stack);
}
static inline void reusable_node_assign(ReusableNode *self, const ReusableNode *other) {
array_assign(&self->stack, &other->stack);
}
static inline void reusable_node_advance(ReusableNode *self) {
StackEntry last_entry = *array_back(&self->stack);
uint32_t byte_offset = last_entry.byte_offset + ts_tree_total_bytes(last_entry.tree);
if (last_entry.tree->has_external_tokens) {
self->last_external_token = ts_tree_last_external_token(last_entry.tree);
}
Tree *tree;
uint32_t next_index;
do {
StackEntry popped_entry = array_pop(&self->stack);
next_index = popped_entry.child_index + 1;
tree = array_back(&self->stack)->tree;
} while (tree->children.size <= next_index);
array_push(&self->stack, ((StackEntry) {
.tree = tree->children.contents[next_index],
.child_index = next_index,
.byte_offset = byte_offset,
}));
}
static inline bool reusable_node_descend(ReusableNode *self) {
StackEntry last_entry = *array_back(&self->stack);
if (last_entry.tree->children.size > 0) {
array_push(&self->stack, ((StackEntry) {
.tree = last_entry.tree->children.contents[0],
.child_index = 0,
.byte_offset = last_entry.byte_offset,
}));
return true;
} else {
return false;
}
}
static inline void reusable_node_advance_past_leaf(ReusableNode *self) {
while (reusable_node_descend(self)) {}
reusable_node_advance(self);
}

View file

@ -169,7 +169,9 @@ Tree *ts_tree_make_copy(TreePool *pool, Tree *self) {
return result;
}
static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language) {
static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language, TreeArray *stack) {
unsigned initial_stack_size = stack->size;
Tree *tree = self;
for (unsigned i = 0; i < count; i++) {
if (tree->ref_count > 1 || tree->children.size != 2) break;
@ -189,22 +191,14 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang
) break;
tree->children.contents[0] = grandchild;
grandchild->context.parent = tree;
grandchild->context.index = -1;
child->children.contents[0] = grandchild->children.contents[1];
child->children.contents[0]->context.parent = child;
child->children.contents[0]->context.index = -1;
grandchild->children.contents[1] = child;
grandchild->children.contents[1]->context.parent = grandchild;
grandchild->children.contents[1]->context.index = -1;
array_push(stack, tree);
tree = grandchild;
}
while (tree != self) {
tree = tree->context.parent;
while (stack->size > initial_stack_size) {
tree = array_pop(stack);
Tree *child = tree->children.contents[0];
Tree *grandchild = child->children.contents[1];
ts_tree_set_children(grandchild, &grandchild->children, language);
@ -213,50 +207,30 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang
}
}
void ts_tree__balance(Tree *self, const TSLanguage *language) {
if (self->children.contents[0]->repeat_depth > self->children.contents[1]->repeat_depth) {
unsigned n = self->children.contents[0]->repeat_depth - self->children.contents[1]->repeat_depth;
for (unsigned i = n / 2; i > 0; i /= 2) {
ts_tree__compress(self, i, language);
n -= i;
}
}
}
void ts_tree_assign_parents(Tree *self, TreePool *pool, const TSLanguage *language) {
self->context.parent = NULL;
array_clear(&pool->tree_stack);
array_push(&pool->tree_stack, self);
while (pool->tree_stack.size > 0) {
Tree *tree = array_pop(&pool->tree_stack);
if (tree->repeat_depth > 0) {
ts_tree__balance(tree, language);
if (tree->children.contents[0]->repeat_depth > tree->children.contents[1]->repeat_depth) {
unsigned n = (
tree->children.contents[0]->repeat_depth -
tree->children.contents[1]->repeat_depth
);
for (unsigned i = n / 2; i > 0; i /= 2) {
ts_tree__compress(tree, i, language, &pool->tree_stack);
n -= i;
}
}
}
Length offset = length_zero();
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, tree->alias_sequence_id);
uint32_t non_extra_index = 0;
bool earlier_child_was_changed = false;
for (uint32_t i = 0; i < tree->children.size; i++) {
Tree *child = tree->children.contents[i];
if (earlier_child_was_changed || child->context.parent != tree || child->context.index != i) {
earlier_child_was_changed = true;
child->context.parent = tree;
child->context.index = i;
child->context.offset = offset;
if (!child->extra && alias_sequence && alias_sequence[non_extra_index] != 0) {
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, alias_sequence[non_extra_index]);
child->context.alias_symbol = alias_sequence[non_extra_index];
child->context.alias_is_named = metadata.named;
} else {
child->context.alias_symbol = 0;
child->context.alias_is_named = false;
}
if (child->ref_count == 1) {
array_push(&pool->tree_stack, child);
}
offset = length_add(offset, ts_tree_total_size(child));
if (!child->extra) non_extra_index++;
}
}
}
@ -407,25 +381,6 @@ void ts_tree_release(TreePool *pool, Tree *self) {
}
}
uint32_t ts_tree_start_column(const Tree *self) {
uint32_t column = self->padding.extent.column;
if (self->padding.extent.row > 0)
return column;
for (const Tree *tree = self; tree != NULL; tree = tree->context.parent) {
column += tree->context.offset.extent.column;
if (tree->context.offset.extent.row > 0)
break;
}
return column;
}
uint32_t ts_tree_end_column(const Tree *self) {
uint32_t result = self->size.extent.column;
if (self->size.extent.row == 0)
result += ts_tree_start_column(self);
return result;
}
bool ts_tree_eq(const Tree *self, const Tree *other) {
if (self) {
if (!other) return false;
@ -577,7 +532,6 @@ void ts_tree_edit(Tree *self, const TSInputEdit *edit) {
}
child_right = length_add(child_left, ts_tree_total_size(child));
child->context.offset = child_left;
}
}
@ -612,9 +566,10 @@ static size_t ts_tree__write_char_to_string(char *s, size_t n, int32_t c) {
return snprintf(s, n, "%d", c);
}
static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *language,
char *string, size_t limit, bool is_root,
bool include_all) {
static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t limit,
const TSLanguage *language, bool is_root,
bool include_all, TSSymbol alias_symbol,
bool alias_is_named) {
if (!self) return snprintf(string, limit, "(NULL)");
char *cursor = string;
@ -624,7 +579,7 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu
is_root ||
self->is_missing ||
(self->visible && self->named) ||
self->context.alias_is_named;
alias_is_named;
if (visible && !is_root) {
cursor += snprintf(*writer, limit, " ");
@ -637,15 +592,35 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu
} else if (self->is_missing) {
cursor += snprintf(*writer, limit, "(MISSING");
} else {
TSSymbol symbol = self->context.alias_symbol ? self->context.alias_symbol : self->symbol;
TSSymbol symbol = alias_symbol ? alias_symbol : self->symbol;
const char *symbol_name = ts_language_symbol_name(language, symbol);
cursor += snprintf(*writer, limit, "(%s", symbol_name);
}
}
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < self->children.size; i++) {
Tree *child = self->children.contents[i];
cursor += ts_tree__write_to_string(child, language, *writer, limit, false, include_all);
if (child->extra) {
cursor += ts_tree__write_to_string(
child, *writer, limit,
language, false, include_all,
0, false
);
} else {
cursor += ts_tree__write_to_string(
child, *writer, limit,
language, false, include_all,
alias_sequence
? alias_sequence[structural_child_index]
: 0,
alias_sequence
? ts_language_symbol_metadata(language, alias_sequence[structural_child_index]).named
: false
);
structural_child_index++;
}
}
if (visible) cursor += snprintf(*writer, limit, ")");
@ -655,15 +630,19 @@ static size_t ts_tree__write_to_string(const Tree *self, const TSLanguage *langu
char *ts_tree_string(const Tree *self, const TSLanguage *language, bool include_all) {
char scratch_string[1];
size_t size = ts_tree__write_to_string(self, language, scratch_string, 0, true, include_all) + 1;
size_t size = ts_tree__write_to_string(
self, scratch_string, 0,
language, true,
include_all, 0, false
) + 1;
char *result = ts_malloc(size * sizeof(char));
ts_tree__write_to_string(self, language, result, size, true, include_all);
ts_tree__write_to_string(self, result, size, language, true, include_all, 0, false);
return result;
}
void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
const TSLanguage *language, FILE *f) {
TSSymbol symbol = self->context.alias_symbol ? self->context.alias_symbol : self->symbol;
const TSLanguage *language, TSSymbol alias_symbol, FILE *f) {
TSSymbol symbol = alias_symbol ? alias_symbol : self->symbol;
fprintf(f, "tree_%p [label=\"%s\"", self, ts_language_symbol_name(language, symbol));
if (self->children.size == 0)
@ -674,9 +653,18 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
fprintf(f, ", tooltip=\"address:%p\nrange:%u - %u\nstate:%d\nerror-cost:%u\nrepeat-depth:%u\"]\n",
self, byte_offset, byte_offset + ts_tree_total_bytes(self), self->parse_state,
self->error_cost, self->repeat_depth);
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < self->children.size; i++) {
const Tree *child = self->children.contents[i];
ts_tree__print_dot_graph(child, byte_offset, language, f);
if (child->extra) {
ts_tree__print_dot_graph(child, byte_offset, language, 0, f);
} else {
TSSymbol alias_symbol = alias_sequence ? alias_sequence[structural_child_index] : 0;
ts_tree__print_dot_graph(child, byte_offset, language, alias_symbol, f);
structural_child_index++;
}
fprintf(f, "tree_%p -> tree_%p [tooltip=%u]\n", self, child, i);
byte_offset += ts_tree_total_bytes(child);
}
@ -685,7 +673,7 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
void ts_tree_print_dot_graph(const Tree *self, const TSLanguage *language, FILE *f) {
fprintf(f, "digraph tree {\n");
fprintf(f, "edge [arrowhead=none]\n");
ts_tree__print_dot_graph(self, 0, language, f);
ts_tree__print_dot_graph(self, 0, language, 0, f);
fprintf(f, "}\n");
}

View file

@ -27,14 +27,6 @@ typedef struct Tree Tree;
typedef Array(Tree *) TreeArray;
struct Tree {
struct {
struct Tree *parent;
uint32_t index;
Length offset;
TSSymbol alias_symbol : 15;
bool alias_is_named : 1;
} context;
Length padding;
Length size;
uint32_t ref_count;
@ -106,8 +98,6 @@ void ts_tree_retain(Tree *tree);
void ts_tree_release(TreePool *, Tree *tree);
bool ts_tree_eq(const Tree *tree1, const Tree *tree2);
int ts_tree_compare(const Tree *tree1, const Tree *tree2);
uint32_t ts_tree_start_column(const Tree *self);
uint32_t ts_tree_end_column(const Tree *self);
void ts_tree_set_children(Tree *, TreeArray *, const TSLanguage *);
void ts_tree_assign_parents(Tree *, TreePool *, const TSLanguage *);
void ts_tree_edit(Tree *, const TSInputEdit *edit);
@ -120,6 +110,10 @@ static inline uint32_t ts_tree_total_bytes(const Tree *self) {
return self->padding.bytes + self->size.bytes;
}
static inline uint32_t ts_tree_total_rows(const Tree *self) {
return self->padding.extent.row + self->size.extent.row;
}
static inline Length ts_tree_total_size(const Tree *self) {
return length_add(self->padding, self->size);
}