From 121a6a66ec6a4482422634d0559c2f007ae07026 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 9 Oct 2017 15:51:22 -0700 Subject: [PATCH] Take total dynamic precedence into account in stack version sorting Signed-off-by: Josh Vera --- src/runtime/parser.c | 14 +++++++++++++- src/runtime/stack.c | 14 ++++++++++++-- src/runtime/stack.h | 2 ++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 5a7dff20..9265c30f 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -40,6 +40,7 @@ static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE; typedef struct { unsigned cost; unsigned push_count; + int dynamic_precedence; bool is_in_error; } ErrorStatus; @@ -167,6 +168,9 @@ static ErrorComparison parser__compare_versions(Parser *self, ErrorStatus a, Err } } + if (a.dynamic_precedence > b.dynamic_precedence) return ErrorComparisonPreferLeft; + if (b.dynamic_precedence > a.dynamic_precedence) return ErrorComparisonPreferRight; + return ErrorComparisonNone; } @@ -174,13 +178,19 @@ static bool parser__better_version_exists(Parser *self, StackVersion version, bool is_in_error, unsigned cost) { if (self->finished_tree && self->finished_tree->error_cost <= cost) return true; - ErrorStatus status = {.cost = cost, .is_in_error = is_in_error, .push_count = 0}; + ErrorStatus status = { + .cost = cost, + .is_in_error = is_in_error, + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, version), + .push_count = 0, + }; for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) { if (i == version || ts_stack_is_halted(self->stack, i)) continue; ErrorStatus status_i = { .cost = ts_stack_error_cost(self->stack, i), .is_in_error = ts_stack_top_state(self->stack, i) == ERROR_STATE, + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, i), .push_count = ts_stack_push_count(self->stack, i) }; switch (parser__compare_versions(self, status, status_i)) { @@ -210,6 +220,7 @@ static bool parser__condense_stack(Parser *self) { ErrorStatus status_i = { .cost = ts_stack_error_cost(self->stack, i), .push_count = ts_stack_push_count(self->stack, i), + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, i), .is_in_error = ts_stack_top_state(self->stack, i) == ERROR_STATE, }; if (!status_i.is_in_error) all_versions_have_error = false; @@ -219,6 +230,7 @@ static bool parser__condense_stack(Parser *self) { ErrorStatus status_j = { .cost = ts_stack_error_cost(self->stack, j), .push_count = ts_stack_push_count(self->stack, j), + .dynamic_precedence = ts_stack_dynamic_precedence(self->stack, j), .is_in_error = ts_stack_top_state(self->stack, j) == ERROR_STATE, }; diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 95657493..46dfe8d0 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -32,6 +32,7 @@ struct StackNode { uint32_t ref_count; unsigned error_cost; unsigned depth; + int dynamic_precedence; }; typedef struct { @@ -121,6 +122,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p node->position = previous_node->position; node->error_cost = previous_node->error_cost; + node->dynamic_precedence = previous_node->dynamic_precedence; if (tree) { node->depth = previous_node->depth; @@ -128,6 +130,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p ts_tree_retain(tree); node->error_cost += tree->error_cost; node->position = length_add(node->position, ts_tree_total_size(tree)); + node->dynamic_precedence += tree->dynamic_precedence; if (state == ERROR_STATE && !tree->extra) { node->error_cost += ERROR_COST_PER_SKIPPED_TREE * ((tree->visible || tree->child_count == 0) ? 1 : tree->visible_child_count) + @@ -517,6 +520,10 @@ unsigned ts_stack_depth_since_error(Stack *self, StackVersion version) { return array_get(&self->heads, version)->node->depth; } +int ts_stack_dynamic_precedence(Stack *self, StackVersion version) { + return array_get(&self->heads, version)->node->dynamic_precedence; +} + void ts_stack_remove_version(Stack *self, StackVersion version) { stack_head_delete(array_get(&self->heads, version), &self->node_pool); array_erase(&self->heads, version); @@ -658,8 +665,11 @@ bool ts_stack_print_dot_graph(Stack *self, const char **symbol_names, FILE *f) { fprintf( f, - " tooltip=\"position: %u,%u\nerror_cost: %u\"];\n", - node->position.extent.row, node->position.extent.column, node->error_cost + " tooltip=\"position: %u,%u\nerror_cost: %u\ndynamic_precedence: %d\"];\n", + node->position.extent.row, + node->position.extent.column, + node->error_cost, + node->dynamic_precedence ); for (int j = 0; j < node->link_count; j++) { diff --git a/src/runtime/stack.h b/src/runtime/stack.h index 6bb0b40b..0cb3a800 100644 --- a/src/runtime/stack.h +++ b/src/runtime/stack.h @@ -104,6 +104,8 @@ StackPopResult ts_stack_pop_all(Stack *, StackVersion); unsigned ts_stack_depth_since_error(Stack *, StackVersion); +int ts_stack_dynamic_precedence(Stack *, StackVersion); + void ts_stack_record_summary(Stack *, StackVersion, unsigned max_depth); StackSummary *ts_stack_get_summary(Stack *, StackVersion);