diff --git a/src/ast.cpp b/src/ast.cpp index 5b1c3fbd8..9609c1d85 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -1111,6 +1111,11 @@ class ast_t::populator_t { if (!token.allows_token(peek_token().type)) { const auto &peek = peek_token(); + if ((flags_ & parse_flag_leave_unterminated) && + peek.tok_error == tokenizer_error_t::unterminated_subshell) { + return; + } + parse_error(peek, parse_error_generic, L"Expected %ls, but found %ls", token_types_user_presentable_description({TokTypes...}).c_str(), peek.user_presentable_description().c_str()); @@ -1134,6 +1139,11 @@ class ast_t::populator_t { keyword.unsourced = true; const auto &peek = peek_token(); + if ((flags_ & parse_flag_leave_unterminated) && + peek.tok_error == tokenizer_error_t::unterminated_subshell) { + return; + } + // Special error reporting for keyword_t. std::array allowed = {{KWs...}}; if (allowed.size() == 1 && allowed[0] == parse_keyword_t::kw_end) { diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index a35aa1d9e..8acb995d1 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -4790,6 +4790,14 @@ static void test_new_parser_ad_hoc() { // because we don't want to color it as an error. ast = ast_t::parse(L"a=", parse_flag_leave_unterminated); do_test(!ast.errored()); + + parse_error_list_t errors; + ast = ast_t::parse(L"begin; echo (", parse_flag_leave_unterminated, &errors); + do_test(errors.size() == 1 && errors.at(0).code == parse_error_tokenizer_unterminated_subshell); + + errors.clear(); + ast = ast_t::parse(L"for x in (", parse_flag_leave_unterminated, &errors); + do_test(errors.size() == 1 && errors.at(0).code == parse_error_tokenizer_unterminated_subshell); } static void test_new_parser_errors() {