From dafa897021b12a23bb55042c6ef3748f5e807b37 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 9 Jan 2018 17:08:36 -0800 Subject: [PATCH] Bail on error recovery if too many alternative parses have already completed --- src/runtime/parser.c | 11 ++++++++++- src/runtime/parser.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 3fec5510..81bed445 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -741,6 +741,7 @@ static void parser__start(Parser *self, TSInput input, Tree *previous_tree) { ts_stack_clear(self->stack); self->reusable_node = reusable_node_new(previous_tree); self->finished_tree = NULL; + self->accept_count = 0; } static void parser__accept(Parser *self, StackVersion version, @@ -770,6 +771,7 @@ static void parser__accept(Parser *self, StackVersion version, } assert(root && root->ref_count > 0); + self->accept_count++; if (self->finished_tree) { if (parser__select_tree(self, self->finished_tree, root)) { @@ -862,7 +864,14 @@ static bool parser__do_all_potential_reductions(Parser *self, StackVersion start } static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lookahead_symbol) { - // If there are other stack versions that are clearly better than this one, + // If enough parse versions have already completed, just halt this version. + if (self->accept_count > MAX_VERSION_COUNT) { + ts_stack_halt(self->stack, version); + LOG("bail_after_too_many_tries"); + return; + } + + // If there are other in-progress versions that are clearly better than this one, // just halt this version. unsigned new_cost = ts_stack_error_cost(self->stack, version) + ERROR_COST_PER_SKIPPED_TREE; if (parser__better_version_exists(self, version, true, new_cost)) { diff --git a/src/runtime/parser.h b/src/runtime/parser.h index a3b88eab..dab58dc9 100644 --- a/src/runtime/parser.h +++ b/src/runtime/parser.h @@ -31,6 +31,7 @@ typedef struct { void *external_scanner_payload; bool in_ambiguity; bool print_debugging_graphs; + unsigned accept_count; } Parser; bool parser_init(Parser *);