Convert parse_error_code_t to a scoped enum

This will make the Rust port's diff smaller.
This commit is contained in:
Johannes Altmanninger 2023-02-07 23:51:47 +01:00
parent 8fd1db06ed
commit 9ca160eac2
7 changed files with 68 additions and 61 deletions

View file

@ -682,7 +682,7 @@ struct populator_t {
"Should not attempt to consume terminate token");
auto tok = consume_any_token();
if (tok.type != type) {
parse_error(tok, parse_error_generic, _(L"Expected %ls, but found %ls"),
parse_error(tok, parse_error_code_t::generic, _(L"Expected %ls, but found %ls"),
token_type_user_presentable_description(type).c_str(),
tok.user_presentable_description().c_str());
return source_range_t{0, 0};
@ -703,7 +703,7 @@ struct populator_t {
// complete -c foo -a "'abc"
if (this->top_type_ == type_t::freestanding_argument_list) {
this->parse_error(
tok, parse_error_generic, _(L"Expected %ls, but found %ls"),
tok, parse_error_code_t::generic, _(L"Expected %ls, but found %ls"),
token_type_user_presentable_description(parse_token_type_t::string).c_str(),
tok.user_presentable_description().c_str());
return;
@ -715,15 +715,15 @@ struct populator_t {
// There are three keywords which end a job list.
switch (tok.keyword) {
case parse_keyword_t::kw_end:
this->parse_error(tok, parse_error_unbalancing_end,
this->parse_error(tok, parse_error_code_t::unbalancing_end,
_(L"'end' outside of a block"));
break;
case parse_keyword_t::kw_else:
this->parse_error(tok, parse_error_unbalancing_else,
this->parse_error(tok, parse_error_code_t::unbalancing_else,
_(L"'else' builtin not inside of if block"));
break;
case parse_keyword_t::kw_case:
this->parse_error(tok, parse_error_unbalancing_case,
this->parse_error(tok, parse_error_code_t::unbalancing_case,
_(L"'case' builtin not inside of switch block"));
break;
default:
@ -738,7 +738,8 @@ struct populator_t {
case parse_token_type_t::background:
case parse_token_type_t::andand:
case parse_token_type_t::oror:
parse_error(tok, parse_error_generic, _(L"Expected a string, but found %ls"),
parse_error(tok, parse_error_code_t::generic,
_(L"Expected a string, but found %ls"),
tok.user_presentable_description().c_str());
break;
@ -968,14 +969,15 @@ struct populator_t {
} else if (token1.type != parse_token_type_t::string) {
// We may be unwinding already; do not produce another error.
// For example in `true | and`.
parse_error(token1, parse_error_generic, _(L"Expected a command, but found %ls"),
parse_error(token1, parse_error_code_t::generic,
_(L"Expected a command, but found %ls"),
token1.user_presentable_description().c_str());
return got_error();
} else if (token1.may_be_variable_assignment) {
// Here we have a variable assignment which we chose to not parse as a variable
// assignment because there was no string after it.
// Ensure we consume the token, so we don't get back here again at the same place.
parse_error(consume_any_token(), parse_error_bare_variable_assignment, L"");
parse_error(consume_any_token(), parse_error_code_t::bare_variable_assignment, L"");
return got_error();
}
@ -1025,7 +1027,8 @@ struct populator_t {
// For example, `if end` or `while end` will produce this error.
// We still have to descend into the decorated statement because
// we can't leave our pointer as null.
parse_error(token1, parse_error_generic, _(L"Expected a command, but found %ls"),
parse_error(token1, parse_error_code_t::generic,
_(L"Expected a command, but found %ls"),
token1.user_presentable_description().c_str());
return got_error();
@ -1083,7 +1086,8 @@ struct populator_t {
const auto &tok = peek_token(1);
if (tok.keyword == parse_keyword_t::kw_and || tok.keyword == parse_keyword_t::kw_or) {
const wchar_t *cmdname = (tok.keyword == parse_keyword_t::kw_and ? L"and" : L"or");
parse_error(tok, parse_error_andor_in_pipeline, INVALID_PIPELINE_CMD_ERR_MSG, cmdname);
parse_error(tok, parse_error_code_t::andor_in_pipeline, INVALID_PIPELINE_CMD_ERR_MSG,
cmdname);
}
node.accept(*this);
}
@ -1112,7 +1116,7 @@ struct populator_t {
return;
}
parse_error(peek, parse_error_generic, L"Expected %ls, but found %ls",
parse_error(peek, parse_error_code_t::generic, L"Expected %ls, but found %ls",
token_types_user_presentable_description({TokTypes...}).c_str(),
peek.user_presentable_description().c_str());
token.unsourced = true;
@ -1149,11 +1153,11 @@ struct populator_t {
source_range_t kw_range = p.first;
const wchar_t *kw_name = p.second;
if (kw_name) {
this->parse_error(kw_range, parse_error_generic,
this->parse_error(kw_range, parse_error_code_t::generic,
L"Missing end to balance this %ls", kw_name);
}
}
parse_error(peek, parse_error_generic, L"Expected %ls, but found %ls",
parse_error(peek, parse_error_code_t::generic, L"Expected %ls, but found %ls",
keywords_user_presentable_description({KWs...}).c_str(),
peek.user_presentable_description().c_str());
return;

View file

@ -71,7 +71,7 @@ static void append_syntax_error(parse_error_list_t *errors, size_t source_start,
parse_error_t error;
error.source_start = source_start;
error.source_length = 0;
error.code = parse_error_syntax;
error.code = parse_error_code_t::syntax;
va_list va;
va_start(va, fmt);
@ -91,7 +91,7 @@ static void append_cmdsub_error(parse_error_list_t *errors, size_t source_start,
parse_error_t error;
error.source_start = source_start;
error.source_length = source_end - source_start + 1;
error.code = parse_error_cmdsubst;
error.code = parse_error_code_t::cmdsubst;
va_list va;
va_start(va, fmt);
@ -112,7 +112,7 @@ static expand_result_t append_overflow_error(parse_error_list_t *errors,
parse_error_t error;
error.source_start = source_start;
error.source_length = 0;
error.code = parse_error_generic;
error.code = parse_error_code_t::generic;
error.text = _(L"Expansion produced too many results");
errors->push_back(std::move(error));
}

View file

@ -5137,15 +5137,18 @@ static void test_new_parser_ad_hoc() {
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);
do_test(errors.size() == 1 &&
errors.at(0).code == parse_error_code_t::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);
do_test(errors.size() == 1 &&
errors.at(0).code == parse_error_code_t::tokenizer_unterminated_subshell);
errors.clear();
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_quote);
do_test(errors.size() == 1 &&
errors.at(0).code == parse_error_code_t::tokenizer_unterminated_quote);
}
static void test_new_parser_errors() {
@ -5154,22 +5157,22 @@ static void test_new_parser_errors() {
const wchar_t *src;
parse_error_code_t code;
} tests[] = {
{L"echo 'abc", parse_error_tokenizer_unterminated_quote},
{L"'", parse_error_tokenizer_unterminated_quote},
{L"echo (abc", parse_error_tokenizer_unterminated_subshell},
{L"echo 'abc", parse_error_code_t::tokenizer_unterminated_quote},
{L"'", parse_error_code_t::tokenizer_unterminated_quote},
{L"echo (abc", parse_error_code_t::tokenizer_unterminated_subshell},
{L"end", parse_error_unbalancing_end},
{L"echo hi ; end", parse_error_unbalancing_end},
{L"end", parse_error_code_t::unbalancing_end},
{L"echo hi ; end", parse_error_code_t::unbalancing_end},
{L"else", parse_error_unbalancing_else},
{L"if true ; end ; else", parse_error_unbalancing_else},
{L"else", parse_error_code_t::unbalancing_else},
{L"if true ; end ; else", parse_error_code_t::unbalancing_else},
{L"case", parse_error_unbalancing_case},
{L"if true ; case ; end", parse_error_generic},
{L"case", parse_error_code_t::unbalancing_case},
{L"if true ; case ; end", parse_error_code_t::generic},
{L"true | and", parse_error_andor_in_pipeline},
{L"true | and", parse_error_code_t::andor_in_pipeline},
{L"a=", parse_error_bare_variable_assignment},
{L"a=", parse_error_code_t::bare_variable_assignment},
};
for (const auto &test : tests) {

View file

@ -131,27 +131,27 @@ enum class statement_decoration_t : uint8_t {
};
// Parse error code list.
enum parse_error_code_t : uint8_t {
parse_error_none,
enum class parse_error_code_t : uint8_t {
none,
// Matching values from enum parser_error.
parse_error_syntax,
parse_error_cmdsubst,
syntax,
cmdsubst,
parse_error_generic, // unclassified error types
generic, // unclassified error types
// Tokenizer errors.
parse_error_tokenizer_unterminated_quote,
parse_error_tokenizer_unterminated_subshell,
parse_error_tokenizer_unterminated_slice,
parse_error_tokenizer_unterminated_escape,
parse_error_tokenizer_other,
tokenizer_unterminated_quote,
tokenizer_unterminated_subshell,
tokenizer_unterminated_slice,
tokenizer_unterminated_escape,
tokenizer_other,
parse_error_unbalancing_end, // end outside of block
parse_error_unbalancing_else, // else outside of if
parse_error_unbalancing_case, // case outside of switch
parse_error_bare_variable_assignment, // a=b without command
parse_error_andor_in_pipeline, // "and" or "or" after a pipe
unbalancing_end, // end outside of block
unbalancing_else, // else outside of if
unbalancing_case, // case outside of switch
bare_variable_assignment, // a=b without command
andor_in_pipeline, // "and" or "or" after a pipe
};
enum {

View file

@ -669,7 +669,7 @@ end_execution_reason_t parse_execution_context_t::report_error(int status, const
parse_error_t *error = &error_list.at(0);
error->source_start = r.start;
error->source_length = r.length;
error->code = parse_error_syntax; // hackish
error->code = parse_error_code_t::syntax; // hackish
va_list va;
va_start(va, fmt);

View file

@ -20,17 +20,17 @@
parse_error_code_t parse_error_from_tokenizer_error(tokenizer_error_t err) {
switch (err) {
case tokenizer_error_t::none:
return parse_error_none;
return parse_error_code_t::none;
case tokenizer_error_t::unterminated_quote:
return parse_error_tokenizer_unterminated_quote;
return parse_error_code_t::tokenizer_unterminated_quote;
case tokenizer_error_t::unterminated_subshell:
return parse_error_tokenizer_unterminated_subshell;
return parse_error_code_t::tokenizer_unterminated_subshell;
case tokenizer_error_t::unterminated_slice:
return parse_error_tokenizer_unterminated_slice;
return parse_error_code_t::tokenizer_unterminated_slice;
case tokenizer_error_t::unterminated_escape:
return parse_error_tokenizer_unterminated_escape;
return parse_error_code_t::tokenizer_unterminated_escape;
default:
return parse_error_tokenizer_other;
return parse_error_code_t::tokenizer_other;
}
}
@ -45,11 +45,11 @@ wcstring parse_error_t::describe_with_prefix(const wcstring &src, const wcstring
if (skip_caret && this->text.empty()) return L"";
result.append(this->text);
break;
case parse_error_andor_in_pipeline:
case parse_error_code_t::andor_in_pipeline:
append_format(result, INVALID_PIPELINE_CMD_ERR_MSG,
src.substr(this->source_start, this->source_length).c_str());
break;
case parse_error_bare_variable_assignment: {
case parse_error_code_t::bare_variable_assignment: {
wcstring assignment_src = src.substr(this->source_start, this->source_length);
maybe_t<size_t> equals_pos = variable_assignment_equals_pos(assignment_src);
assert(equals_pos.has_value());

View file

@ -815,7 +815,7 @@ static bool append_syntax_error(parse_error_list_t *errors, size_t source_locati
parse_error_t error;
error.source_start = source_location;
error.source_length = source_length;
error.code = parse_error_syntax;
error.code = parse_error_code_t::syntax;
va_list va;
va_start(va, fmt);
@ -965,13 +965,13 @@ parser_test_error_bits_t parse_util_detect_errors_in_argument(const ast::argumen
if (out_errors) {
const wchar_t *fmt = L"Invalid token '%ls'";
if (arg_src.length() == 2 && arg_src[0] == L'\\' &&
(arg_src[1] == L'c' || towlower(arg_src[1]) == L'u'
|| towlower(arg_src[1]) == L'x')) {
(arg_src[1] == L'c' || towlower(arg_src[1]) == L'u' ||
towlower(arg_src[1]) == L'x')) {
fmt = L"Incomplete escape sequence '%ls'";
}
append_syntax_error(out_errors, source_start + begin, end - begin,
fmt, arg_src.c_str());
append_syntax_error(out_errors, source_start + begin, end - begin, fmt,
arg_src.c_str());
}
return 1;
}
@ -1359,8 +1359,8 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
// successfully.
size_t idx = parse_errors.size();
while (idx--) {
if (parse_errors.at(idx).code == parse_error_tokenizer_unterminated_quote ||
parse_errors.at(idx).code == parse_error_tokenizer_unterminated_subshell) {
if (parse_errors.at(idx).code == parse_error_code_t::tokenizer_unterminated_quote ||
parse_errors.at(idx).code == parse_error_code_t::tokenizer_unterminated_subshell) {
// Remove this error, since we don't consider it a real error.
has_unclosed_quote_or_subshell = true;
parse_errors.erase(parse_errors.begin() + idx);