Allocate parent nodes together with their child array
This commit is contained in:
parent
b972a7158d
commit
d533d1f076
9 changed files with 240 additions and 157 deletions
110
lib/src/parser.c
110
lib/src/parser.c
|
|
@ -60,8 +60,9 @@ struct TSParser {
|
|||
const TSLanguage *language;
|
||||
ReduceActionSet reduce_actions;
|
||||
Subtree finished_tree;
|
||||
SubtreeHeapData scratch_tree_data;
|
||||
MutableSubtree scratch_tree;
|
||||
SubtreeArray trailing_extras;
|
||||
SubtreeArray trailing_extras2;
|
||||
SubtreeArray scratch_trees;
|
||||
TokenCache token_cache;
|
||||
ReusableNode reusable_node;
|
||||
void *external_scanner_payload;
|
||||
|
|
@ -155,7 +156,7 @@ static bool ts_parser__breakdown_top_of_stack(
|
|||
Subtree parent = *array_front(&slice.subtrees);
|
||||
|
||||
for (uint32_t j = 0, n = ts_subtree_child_count(parent); j < n; j++) {
|
||||
Subtree child = parent.ptr->children[j];
|
||||
Subtree child = ts_subtree_children(parent)[j];
|
||||
pending = ts_subtree_child_count(child) > 0;
|
||||
|
||||
if (ts_subtree_is_error(child)) {
|
||||
|
|
@ -717,6 +718,25 @@ static bool ts_parser__select_tree(TSParser *self, Subtree left, Subtree right)
|
|||
}
|
||||
}
|
||||
|
||||
static bool ts_parser__select_children(
|
||||
TSParser *self,
|
||||
Subtree left,
|
||||
const SubtreeArray *children
|
||||
) {
|
||||
array_assign(&self->scratch_trees, children);
|
||||
MutableSubtree scratch_tree = ts_subtree_new_node(
|
||||
ts_subtree_symbol(left),
|
||||
&self->scratch_trees,
|
||||
0,
|
||||
self->language
|
||||
);
|
||||
return ts_parser__select_tree(
|
||||
self,
|
||||
left,
|
||||
ts_subtree_from_mut(scratch_tree)
|
||||
);
|
||||
}
|
||||
|
||||
static void ts_parser__shift(
|
||||
TSParser *self,
|
||||
StackVersion version,
|
||||
|
|
@ -742,22 +762,6 @@ static void ts_parser__shift(
|
|||
}
|
||||
}
|
||||
|
||||
static bool ts_parser__replace_children(
|
||||
TSParser *self,
|
||||
MutableSubtree *tree,
|
||||
SubtreeArray *children
|
||||
) {
|
||||
*self->scratch_tree.ptr = *tree->ptr;
|
||||
self->scratch_tree.ptr->child_count = 0;
|
||||
ts_subtree_set_children(self->scratch_tree, children->contents, children->size, self->language);
|
||||
if (ts_parser__select_tree(self, ts_subtree_from_mut(*tree), ts_subtree_from_mut(self->scratch_tree))) {
|
||||
*tree->ptr = *self->scratch_tree.ptr;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static StackVersion ts_parser__reduce(
|
||||
TSParser *self,
|
||||
StackVersion version,
|
||||
|
|
@ -802,11 +806,9 @@ static StackVersion ts_parser__reduce(
|
|||
// node. They will be re-pushed onto the stack after the parent node is
|
||||
// created and pushed.
|
||||
SubtreeArray children = slice.subtrees;
|
||||
while (children.size > 0 && ts_subtree_extra(children.contents[children.size - 1])) {
|
||||
children.size--;
|
||||
}
|
||||
ts_subtree_array_remove_trailing_extras(&children, &self->trailing_extras);
|
||||
|
||||
MutableSubtree parent = ts_subtree_new_node(&self->tree_pool,
|
||||
MutableSubtree parent = ts_subtree_new_node(
|
||||
symbol, &children, production_id, self->language
|
||||
);
|
||||
|
||||
|
|
@ -820,14 +822,21 @@ static StackVersion ts_parser__reduce(
|
|||
i++;
|
||||
|
||||
SubtreeArray children = next_slice.subtrees;
|
||||
while (children.size > 0 && ts_subtree_extra(children.contents[children.size - 1])) {
|
||||
children.size--;
|
||||
}
|
||||
ts_subtree_array_remove_trailing_extras(&children, &self->trailing_extras2);
|
||||
|
||||
if (ts_parser__replace_children(self, &parent, &children)) {
|
||||
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
||||
slice = next_slice;
|
||||
if (ts_parser__select_children(
|
||||
self,
|
||||
ts_subtree_from_mut(parent),
|
||||
&children
|
||||
)) {
|
||||
ts_subtree_array_clear(&self->tree_pool, &self->trailing_extras);
|
||||
ts_subtree_release(&self->tree_pool, ts_subtree_from_mut(parent));
|
||||
array_swap(&self->trailing_extras, &self->trailing_extras2);
|
||||
parent = ts_subtree_new_node(
|
||||
symbol, &children, production_id, self->language
|
||||
);
|
||||
} else {
|
||||
array_clear(&self->trailing_extras2);
|
||||
ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees);
|
||||
}
|
||||
}
|
||||
|
|
@ -851,8 +860,8 @@ static StackVersion ts_parser__reduce(
|
|||
// Push the parent node onto the stack, along with any extra tokens that
|
||||
// were previously on top of the stack.
|
||||
ts_stack_push(self->stack, slice_version, ts_subtree_from_mut(parent), false, next_state);
|
||||
for (uint32_t j = parent.ptr->child_count; j < slice.subtrees.size; j++) {
|
||||
ts_stack_push(self->stack, slice_version, slice.subtrees.contents[j], false, next_state);
|
||||
for (uint32_t j = 0; j < self->trailing_extras.size; j++) {
|
||||
ts_stack_push(self->stack, slice_version, self->trailing_extras.contents[j], false, next_state);
|
||||
}
|
||||
|
||||
for (StackVersion j = 0; j < slice_version; j++) {
|
||||
|
|
@ -884,22 +893,22 @@ static void ts_parser__accept(
|
|||
|
||||
Subtree root = NULL_SUBTREE;
|
||||
for (uint32_t j = trees.size - 1; j + 1 > 0; j--) {
|
||||
Subtree child = trees.contents[j];
|
||||
if (!ts_subtree_extra(child)) {
|
||||
assert(!child.data.is_inline);
|
||||
uint32_t child_count = ts_subtree_child_count(child);
|
||||
Subtree tree = trees.contents[j];
|
||||
if (!ts_subtree_extra(tree)) {
|
||||
assert(!tree.data.is_inline);
|
||||
uint32_t child_count = ts_subtree_child_count(tree);
|
||||
const Subtree *children = ts_subtree_children(tree);
|
||||
for (uint32_t k = 0; k < child_count; k++) {
|
||||
ts_subtree_retain(child.ptr->children[k]);
|
||||
ts_subtree_retain(children[k]);
|
||||
}
|
||||
array_splice(&trees, j, 1, child_count, child.ptr->children);
|
||||
array_splice(&trees, j, 1, child_count, children);
|
||||
root = ts_subtree_from_mut(ts_subtree_new_node(
|
||||
&self->tree_pool,
|
||||
ts_subtree_symbol(child),
|
||||
ts_subtree_symbol(tree),
|
||||
&trees,
|
||||
child.ptr->production_id,
|
||||
tree.ptr->production_id,
|
||||
self->language
|
||||
));
|
||||
ts_subtree_release(&self->tree_pool, child);
|
||||
ts_subtree_release(&self->tree_pool, tree);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1125,7 +1134,7 @@ static bool ts_parser__recover_to_state(
|
|||
Subtree error_tree = error_trees.contents[0];
|
||||
uint32_t error_child_count = ts_subtree_child_count(error_tree);
|
||||
if (error_child_count > 0) {
|
||||
array_splice(&slice.subtrees, 0, 0, error_child_count, error_tree.ptr->children);
|
||||
array_splice(&slice.subtrees, 0, 0, error_child_count, ts_subtree_children(error_tree));
|
||||
for (unsigned j = 0; j < error_child_count; j++) {
|
||||
ts_subtree_retain(slice.subtrees.contents[j]);
|
||||
}
|
||||
|
|
@ -1133,22 +1142,21 @@ static bool ts_parser__recover_to_state(
|
|||
ts_subtree_array_delete(&self->tree_pool, &error_trees);
|
||||
}
|
||||
|
||||
SubtreeArray trailing_extras = ts_subtree_array_remove_trailing_extras(&slice.subtrees);
|
||||
ts_subtree_array_remove_trailing_extras(&slice.subtrees, &self->trailing_extras);
|
||||
|
||||
if (slice.subtrees.size > 0) {
|
||||
Subtree error = ts_subtree_new_error_node(&self->tree_pool, &slice.subtrees, true, self->language);
|
||||
Subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language);
|
||||
ts_stack_push(self->stack, slice.version, error, false, goal_state);
|
||||
} else {
|
||||
array_delete(&slice.subtrees);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < trailing_extras.size; j++) {
|
||||
Subtree tree = trailing_extras.contents[j];
|
||||
for (unsigned j = 0; j < self->trailing_extras.size; j++) {
|
||||
Subtree tree = self->trailing_extras.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
|
||||
}
|
||||
|
||||
previous_version = slice.version;
|
||||
array_delete(&trailing_extras);
|
||||
}
|
||||
|
||||
return previous_version != STACK_VERSION_NONE;
|
||||
|
|
@ -1245,7 +1253,7 @@ static void ts_parser__recover(
|
|||
if (ts_subtree_is_eof(lookahead)) {
|
||||
LOG("recover_eof");
|
||||
SubtreeArray children = array_new();
|
||||
Subtree parent = ts_subtree_new_error_node(&self->tree_pool, &children, false, self->language);
|
||||
Subtree parent = ts_subtree_new_error_node(&children, false, self->language);
|
||||
ts_stack_push(self->stack, version, parent, false, 1);
|
||||
ts_parser__accept(self, version, lookahead);
|
||||
return;
|
||||
|
|
@ -1278,7 +1286,6 @@ static void ts_parser__recover(
|
|||
array_reserve(&children, 1);
|
||||
array_push(&children, lookahead);
|
||||
MutableSubtree error_repeat = ts_subtree_new_node(
|
||||
&self->tree_pool,
|
||||
ts_builtin_sym_error_repeat,
|
||||
&children,
|
||||
0,
|
||||
|
|
@ -1307,7 +1314,6 @@ static void ts_parser__recover(
|
|||
ts_stack_renumber_version(self->stack, pop.contents[0].version, version);
|
||||
array_push(&pop.contents[0].subtrees, ts_subtree_from_mut(error_repeat));
|
||||
error_repeat = ts_subtree_new_node(
|
||||
&self->tree_pool,
|
||||
ts_builtin_sym_error_repeat,
|
||||
&pop.contents[0].subtrees,
|
||||
0,
|
||||
|
|
@ -1666,7 +1672,6 @@ TSParser *ts_parser_new(void) {
|
|||
self->end_clock = clock_null();
|
||||
self->operation_count = 0;
|
||||
self->old_tree = NULL_SUBTREE;
|
||||
self->scratch_tree.ptr = &self->scratch_tree_data;
|
||||
self->included_range_differences = (TSRangeArray) array_new();
|
||||
self->included_range_difference_index = 0;
|
||||
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
||||
|
|
@ -1692,6 +1697,9 @@ void ts_parser_delete(TSParser *self) {
|
|||
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
||||
ts_subtree_pool_delete(&self->tree_pool);
|
||||
reusable_node_delete(&self->reusable_node);
|
||||
array_delete(&self->trailing_extras);
|
||||
array_delete(&self->trailing_extras2);
|
||||
array_delete(&self->scratch_trees);
|
||||
ts_free(self);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue