diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 76bcb4b9..96f98cdf 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -845,7 +845,7 @@ static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lo } for (unsigned i = previous_version_count; i < version_count; i++) { - ts_stack_force_merge(self->stack, version, previous_version_count); + assert(ts_stack_merge(self->stack, version, previous_version_count)); } ts_stack_record_summary(self->stack, version, MAX_SUMMARY_DEPTH); @@ -1099,7 +1099,6 @@ static unsigned parser__condense_stack(Parser *self) { for (StackVersion j = 0; j < i; j++) { ErrorStatus status_j = parser__version_status(self, j); - bool can_merge = ts_stack_can_merge(self->stack, j, i); switch (parser__compare_versions(self, status_j, status_i)) { case ErrorComparisonTakeLeft: made_changes = true; @@ -1109,20 +1108,19 @@ static unsigned parser__condense_stack(Parser *self) { break; case ErrorComparisonPreferLeft: case ErrorComparisonNone: - if (can_merge) { + if (ts_stack_merge(self->stack, j, i)) { made_changes = true; - ts_stack_force_merge(self->stack, j, i); i--; j = i; } break; case ErrorComparisonPreferRight: made_changes = true; - ts_stack_swap_versions(self->stack, i, j); - if (can_merge) { - ts_stack_force_merge(self->stack, j, i); + if (ts_stack_merge(self->stack, j, i)) { i--; j = i; + } else { + ts_stack_swap_versions(self->stack, i, j); } break; case ErrorComparisonTakeRight: diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 17a301fe..9186397f 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -197,15 +197,15 @@ static void stack_node_add_link(StackNode *self, StackLink link) { } } - if (self->link_count < MAX_LINK_COUNT) { - stack_node_retain(link.node); - if (link.tree) ts_tree_retain(link.tree); - self->links[self->link_count++] = link; + if (self->link_count == MAX_LINK_COUNT) return; - unsigned node_count = link.node->node_count; - if (link.tree) node_count += link.tree->node_count; - if (node_count > self->node_count) self->node_count = node_count; - } + stack_node_retain(link.node); + if (link.tree) ts_tree_retain(link.tree); + self->links[self->link_count++] = link; + + unsigned node_count = link.node->node_count; + if (link.tree) node_count += link.tree->node_count; + if (node_count > self->node_count) self->node_count = node_count; } static void stack_head_delete(StackHead *self, StackNodeArray *pool, TreePool *tree_pool) { @@ -570,12 +570,17 @@ StackVersion ts_stack_copy_version(Stack *self, StackVersion version) { } bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2) { - if (ts_stack_can_merge(self, version1, version2)) { - ts_stack_force_merge(self, version1, version2); - return true; - } else { - return false; + if (!ts_stack_can_merge(self, version1, version2)) return false; + StackHead *head1 = &self->heads.contents[version1]; + StackHead *head2 = &self->heads.contents[version2]; + for (uint32_t i = 0; i < head2->node->link_count; i++) { + stack_node_add_link(head1->node, head2->node->links[i]); } + if (head2->node_count_at_last_error > head1->node_count_at_last_error) { + head1->node_count_at_last_error = head2->node_count_at_last_error; + } + ts_stack_remove_version(self, version2); + return true; } bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version2) { @@ -589,18 +594,6 @@ bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version ts_tree_external_token_state_eq(head1->last_external_token, head2->last_external_token); } -void ts_stack_force_merge(Stack *self, StackVersion version1, StackVersion version2) { - StackHead *head1 = &self->heads.contents[version1]; - StackHead *head2 = &self->heads.contents[version2]; - for (uint32_t i = 0; i < head2->node->link_count; i++) { - stack_node_add_link(head1->node, head2->node->links[i]); - } - if (head2->node_count_at_last_error > head1->node_count_at_last_error) { - head1->node_count_at_last_error = head2->node_count_at_last_error; - } - ts_stack_remove_version(self, version2); -} - void ts_stack_halt(Stack *self, StackVersion version) { array_get(&self->heads, version)->status = StackStatusHalted; } diff --git a/src/runtime/stack.h b/src/runtime/stack.h index 4704d90e..92a09b69 100644 --- a/src/runtime/stack.h +++ b/src/runtime/stack.h @@ -73,7 +73,8 @@ StackSliceArray ts_stack_pop_pending(Stack *, StackVersion); // Remove any all trees from the given version of the stack. StackSliceArray ts_stack_pop_all(Stack *, StackVersion); -// Get the number of tree nodes on the stack since the most recent error. +// Get the maximum number of tree nodes reachable from this version of the stack +// since the last error was detected. unsigned ts_stack_node_count_since_error(const Stack *, StackVersion); int ts_stack_dynamic_precedence(Stack *, StackVersion); @@ -86,14 +87,16 @@ void ts_stack_record_summary(Stack *, StackVersion, unsigned max_depth); // given version of the stack. StackSummary *ts_stack_get_summary(Stack *, StackVersion); +// Get the total cost of all errors on the given version of the stack. unsigned ts_stack_error_cost(const Stack *, StackVersion version); +// Determine whether the given two stack versions can be merged. bool ts_stack_merge(Stack *, StackVersion, StackVersion); +// Merge the given two stack versions if possible, returning true +// if they were successfully merged and false otherwise. bool ts_stack_can_merge(Stack *, StackVersion, StackVersion); -void ts_stack_force_merge(Stack *, StackVersion, StackVersion); - TSSymbol ts_stack_resume(Stack *, StackVersion); void ts_stack_pause(Stack *, StackVersion, TSSymbol);