From 46dcd530900215deb3e26c85da3fd472cdb38a4a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 24 Jan 2018 14:04:55 -0800 Subject: [PATCH] Do not insert missing tokens if halt_on_error option is passed --- src/runtime/parser.c | 26 +++++++++++--------------- test/runtime/document_test.cc | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 81bed445..97098c98 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -208,10 +208,9 @@ static bool parser__better_version_exists(Parser *self, StackVersion version, return false; } -static bool parser__condense_stack(Parser *self) { +static unsigned parser__condense_stack(Parser *self) { bool made_changes = false; unsigned min_error_cost = UINT_MAX; - bool all_versions_have_error = true; for (StackVersion i = 0; i < ts_stack_version_count(self->stack); i++) { if (ts_stack_is_halted(self->stack, i)) { ts_stack_remove_version(self->stack, i); @@ -225,8 +224,9 @@ static bool parser__condense_stack(Parser *self) { .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; - if (status_i.cost < min_error_cost) min_error_cost = status_i.cost; + if (!status_i.is_in_error && status_i.cost < min_error_cost) { + min_error_cost = status_i.cost; + } for (StackVersion j = 0; j < i; j++) { ErrorStatus status_j = { @@ -291,9 +291,7 @@ static bool parser__condense_stack(Parser *self) { LOG_STACK(); } - return - (all_versions_have_error && ts_stack_version_count(self->stack) > 0) || - (self->finished_tree && self->finished_tree->error_cost < min_error_cost); + return min_error_cost; } static void parser__restore_external_scanner(Parser *self, Tree *external_token) { @@ -1239,14 +1237,12 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err self->reusable_node = reusable_node; - bool should_halt = parser__condense_stack(self); - if (should_halt) { - if (self->finished_tree) { - break; - } else if (halt_on_error) { - parser__halt_parse(self); - break; - } + unsigned min_error_cost = parser__condense_stack(self); + if (self->finished_tree && self->finished_tree->error_cost < min_error_cost) { + break; + } else if (halt_on_error && min_error_cost > 0) { + parser__halt_parse(self); + break; } self->in_ambiguity = version > 1; diff --git a/test/runtime/document_test.cc b/test/runtime/document_test.cc index 9cf5a14c..7c4bad6c 100644 --- a/test/runtime/document_test.cc +++ b/test/runtime/document_test.cc @@ -439,6 +439,33 @@ describe("Document", [&]() { AssertThat(ts_node_end_byte(root), Equals(input_string.size())); }); + it("does not insert missing tokens if the halt_on_error flag is set", [&]() { + string input_string = "[1, null, 3"; + ts_document_set_language(document, load_real_language("json")); + ts_document_set_input_string(document, input_string.c_str()); + + TSParseOptions options = {}; + options.changed_ranges = nullptr; + + options.halt_on_error = false; + ts_document_parse_with_options(document, options); + root = ts_document_root_node(document); + assert_node_string_equals( + root, + "(value (array (number) (null) (number) (MISSING)))"); + + ts_document_invalidate(document); + + options.halt_on_error = true; + ts_document_parse_with_options(document, options); + root = ts_document_root_node(document); + assert_node_string_equals( + root, + "(ERROR (number) (null) (number))"); + + AssertThat(ts_node_end_byte(root), Equals(input_string.size())); + }); + it("can parse valid code with the halt_on_error flag set", [&]() { string input_string = "[1, null, 3]"; ts_document_set_language(document, load_real_language("json"));