diff --git a/src/fish_indent.cpp b/src/fish_indent.cpp index 593c93bef..3b6ba0e6a 100644 --- a/src/fish_indent.cpp +++ b/src/fish_indent.cpp @@ -255,7 +255,8 @@ void prettifier_t::prettify_node(const parse_node_tree_t &tree, node_offset_t no if (last_was_semicolon) { // We keep the semicolon for `; and` and `; or`, // others we turn into newlines. - if (node.keyword != parse_keyword_and && node.keyword != parse_keyword_or) { + if (node.keyword != parse_keyword_t::kw_and && + node.keyword != parse_keyword_t::kw_or) { append_newline(); } else { output.push_back(L';'); diff --git a/src/parse_constants.h b/src/parse_constants.h index 1d03ce1b7..6e654a7f6 100644 --- a/src/parse_constants.h +++ b/src/parse_constants.h @@ -100,47 +100,49 @@ const enum_map token_enum_map[] = { // array below. // // IMPORTANT: These enums must start at zero. -enum parse_keyword_t : uint8_t { - parse_keyword_and, - parse_keyword_begin, - parse_keyword_builtin, - parse_keyword_case, - parse_keyword_command, - parse_keyword_else, - parse_keyword_end, - parse_keyword_exclam, - parse_keyword_exec, - parse_keyword_for, - parse_keyword_function, - parse_keyword_if, - parse_keyword_in, - parse_keyword_none, - parse_keyword_not, - parse_keyword_or, - parse_keyword_switch, - parse_keyword_time, - parse_keyword_while, +enum class parse_keyword_t : uint8_t { + // 'none' is not a keyword, it is a sentinel indicating nothing. + none, + + kw_and, + kw_begin, + kw_builtin, + kw_case, + kw_command, + kw_else, + kw_end, + kw_exclam, + kw_exec, + kw_for, + kw_function, + kw_if, + kw_in, + kw_not, + kw_or, + kw_switch, + kw_time, + kw_while, }; -const enum_map keyword_enum_map[] = {{parse_keyword_exclam, L"!"}, - {parse_keyword_and, L"and"}, - {parse_keyword_begin, L"begin"}, - {parse_keyword_builtin, L"builtin"}, - {parse_keyword_case, L"case"}, - {parse_keyword_command, L"command"}, - {parse_keyword_else, L"else"}, - {parse_keyword_end, L"end"}, - {parse_keyword_exec, L"exec"}, - {parse_keyword_for, L"for"}, - {parse_keyword_function, L"function"}, - {parse_keyword_if, L"if"}, - {parse_keyword_in, L"in"}, - {parse_keyword_not, L"not"}, - {parse_keyword_or, L"or"}, - {parse_keyword_switch, L"switch"}, - {parse_keyword_time, L"time"}, - {parse_keyword_while, L"while"}, - {parse_keyword_none, nullptr}}; +const enum_map keyword_enum_map[] = {{parse_keyword_t::kw_exclam, L"!"}, + {parse_keyword_t::kw_and, L"and"}, + {parse_keyword_t::kw_begin, L"begin"}, + {parse_keyword_t::kw_builtin, L"builtin"}, + {parse_keyword_t::kw_case, L"case"}, + {parse_keyword_t::kw_command, L"command"}, + {parse_keyword_t::kw_else, L"else"}, + {parse_keyword_t::kw_end, L"end"}, + {parse_keyword_t::kw_exec, L"exec"}, + {parse_keyword_t::kw_for, L"for"}, + {parse_keyword_t::kw_function, L"function"}, + {parse_keyword_t::kw_if, L"if"}, + {parse_keyword_t::kw_in, L"in"}, + {parse_keyword_t::kw_not, L"not"}, + {parse_keyword_t::kw_or, L"or"}, + {parse_keyword_t::kw_switch, L"switch"}, + {parse_keyword_t::kw_time, L"time"}, + {parse_keyword_t::kw_while, L"while"}, + {parse_keyword_t::none, nullptr}}; #define keyword_enum_map_len (sizeof keyword_enum_map / sizeof *keyword_enum_map) // Node tag values. diff --git a/src/parse_grammar.h b/src/parse_grammar.h index 0373e6ece..d5e9e6710 100644 --- a/src/parse_grammar.h +++ b/src/parse_grammar.h @@ -46,7 +46,7 @@ struct keyword { static constexpr parse_token_type_t token = parse_token_type_string; static constexpr production_element_t element() { // Convert a parse_keyword_t enum to a production_element_t enum. - return Keyword + LAST_TOKEN_OR_SYMBOL + 1; + return static_cast(Keyword) + LAST_TOKEN_OR_SYMBOL + 1; } }; @@ -208,8 +208,8 @@ DEF_ALT(job_list) { // Job decorators are 'and' and 'or'. These apply to the whole job. DEF_ALT(job_decorator) { - using ands = single>; - using ors = single>; + using ands = single>; + using ors = single>; using empty = grammar::empty; ALT_BODY(job_decorator, ands, ors, empty); }; @@ -227,7 +227,7 @@ DEF_ALT(job_conjunction_continuation) { /// The time builtin. DEF_ALT(optional_time) { using empty = grammar::empty; - using time = single>; + using time = single>; ALT_BODY(optional_time, empty, time); }; @@ -271,12 +271,12 @@ produces_sequence, job_conjunction, tok_end, andor_job_list, job_list>{ - BODY(if_clause)}; +produces_sequence, job_conjunction, tok_end, andor_job_list, + job_list>{BODY(if_clause)}; DEF_ALT(else_clause) { using empty = grammar::empty; - using else_cont = seq, else_continuation>; + using else_cont = seq, else_continuation>; ALT_BODY(else_clause, empty, else_cont); }; @@ -287,8 +287,8 @@ DEF_ALT(else_continuation) { }; DEF(switch_statement) -produces_sequence, argument, tok_end, case_item_list, end_command, - arguments_or_redirections_list>{BODY(switch_statement)}; +produces_sequence, argument, tok_end, case_item_list, + end_command, arguments_or_redirections_list>{BODY(switch_statement)}; DEF_ALT(case_item_list) { using empty = grammar::empty; @@ -298,7 +298,8 @@ DEF_ALT(case_item_list) { }; DEF(case_item) -produces_sequence, argument_list, tok_end, job_list>{BODY(case_item)}; +produces_sequence, argument_list, tok_end, job_list>{ + BODY(case_item)}; DEF(block_statement) produces_sequence{ @@ -313,24 +314,25 @@ DEF_ALT(block_header) { }; DEF(for_header) -produces_sequence, tok_string, keyword, argument_list, - tok_end>{BODY(for_header)}; +produces_sequence, tok_string, keyword, + argument_list, tok_end>{BODY(for_header)}; DEF(while_header) -produces_sequence, job_conjunction, tok_end, andor_job_list>{ +produces_sequence, job_conjunction, tok_end, andor_job_list>{ BODY(while_header)}; -DEF(begin_header) produces_single>{BODY(begin_header)}; +DEF(begin_header) produces_single>{BODY(begin_header)}; // Functions take arguments, and require at least one (the name). No redirections allowed. DEF(function_header) -produces_sequence, argument, argument_list, tok_end>{ +produces_sequence, argument, argument_list, tok_end>{ BODY(function_header)}; DEF_ALT(not_statement) { - using nots = seq, variable_assignments, optional_time, statement>; + using nots = + seq, variable_assignments, optional_time, statement>; using exclams = - seq, variable_assignments, optional_time, statement>; + seq, variable_assignments, optional_time, statement>; ALT_BODY(not_statement, nots, exclams); }; @@ -347,9 +349,9 @@ DEF_ALT(andor_job_list) { // "builtin" or "command" or "exec" DEF_ALT(decorated_statement) { using plains = single; - using cmds = seq, plain_statement>; - using builtins = seq, plain_statement>; - using execs = seq, plain_statement>; + using cmds = seq, plain_statement>; + using builtins = seq, plain_statement>; + using execs = seq, plain_statement>; ALT_BODY(decorated_statement, plains, cmds, builtins, execs); }; @@ -378,7 +380,7 @@ DEF_ALT(optional_background) { ALT_BODY(optional_background, empty, background); }; -DEF(end_command) produces_single>{BODY(end_command)}; +DEF(end_command) produces_single>{BODY(end_command)}; // Note optional_newlines only allows newline-style tok_end, not semicolons. DEF_ALT(optional_newlines) { diff --git a/src/parse_productions.cpp b/src/parse_productions.cpp index 6622ebd82..dee4a7ac9 100644 --- a/src/parse_productions.cpp +++ b/src/parse_productions.cpp @@ -38,9 +38,9 @@ RESOLVE(job_list) { case parse_token_type_string: { // Some keywords are special. switch (token1.keyword) { - case parse_keyword_end: - case parse_keyword_else: - case parse_keyword_case: { + case parse_keyword_t::kw_end: + case parse_keyword_t::kw_else: + case parse_keyword_t::kw_case: { return production_for(); // end this job list } default: { @@ -74,11 +74,11 @@ RESOLVE(job_decorator) { } switch (token1.keyword) { - case parse_keyword_and: { + case parse_keyword_t::kw_and: { *out_tag = parse_job_decoration_and; return production_for(); } - case parse_keyword_or: { + case parse_keyword_t::kw_or: { *out_tag = parse_job_decoration_or; return production_for(); } @@ -132,16 +132,16 @@ RESOLVE(statement) { if (token1.type == parse_token_type_string) { // If we are a function, then look for help arguments. Otherwise, if the next token looks // like an option (starts with a dash), then parse it as a decorated statement. - if (token1.keyword == parse_keyword_function && token2.is_help_argument) { + if (token1.keyword == parse_keyword_t::kw_function && token2.is_help_argument) { return production_for(); - } else if (token1.keyword != parse_keyword_function && token2.has_dash_prefix) { + } else if (token1.keyword != parse_keyword_t::kw_function && token2.has_dash_prefix) { return production_for(); } // Likewise if the next token doesn't look like an argument at all. This corresponds to e.g. // a "naked if". - bool naked_invocation_invokes_help = - (token1.keyword != parse_keyword_begin && token1.keyword != parse_keyword_end); + bool naked_invocation_invokes_help = (token1.keyword != parse_keyword_t::kw_begin && + token1.keyword != parse_keyword_t::kw_end); if (naked_invocation_invokes_help && (token2.type == parse_token_type_end || token2.type == parse_token_type_terminate)) { return production_for(); @@ -151,26 +151,26 @@ RESOLVE(statement) { switch (token1.type) { case parse_token_type_string: { switch (token1.keyword) { - case parse_keyword_not: - case parse_keyword_exclam: { + case parse_keyword_t::kw_not: + case parse_keyword_t::kw_exclam: { return production_for(); } - case parse_keyword_for: - case parse_keyword_while: - case parse_keyword_function: - case parse_keyword_begin: { + case parse_keyword_t::kw_for: + case parse_keyword_t::kw_while: + case parse_keyword_t::kw_function: + case parse_keyword_t::kw_begin: { return production_for(); } - case parse_keyword_if: { + case parse_keyword_t::kw_if: { return production_for(); } - case parse_keyword_else: { + case parse_keyword_t::kw_else: { return NO_PRODUCTION; } - case parse_keyword_switch: { + case parse_keyword_t::kw_switch: { return production_for(); } - case parse_keyword_end: { + case parse_keyword_t::kw_end: { return NO_PRODUCTION; } // All other keywords fall through to decorated statement. @@ -196,7 +196,7 @@ RESOLVE(else_clause) { UNUSED(out_tag); switch (token1.keyword) { - case parse_keyword_else: { + case parse_keyword_t::kw_else: { return production_for(); } default: { @@ -210,7 +210,7 @@ RESOLVE(else_continuation) { UNUSED(out_tag); switch (token1.keyword) { - case parse_keyword_if: { + case parse_keyword_t::kw_if: { return production_for(); } default: { @@ -223,7 +223,7 @@ RESOLVE(case_item_list) { UNUSED(token2); UNUSED(out_tag); - if (token1.keyword == parse_keyword_case) + if (token1.keyword == parse_keyword_t::kw_case) return production_for(); else if (token1.type == parse_token_type_end) return production_for(); @@ -235,9 +235,9 @@ RESOLVE(not_statement) { UNUSED(token2); UNUSED(out_tag); switch (token1.keyword) { - case parse_keyword_not: + case parse_keyword_t::kw_not: return production_for(); - case parse_keyword_exclam: + case parse_keyword_t::kw_exclam: return production_for(); default: return NO_PRODUCTION; @@ -249,7 +249,8 @@ RESOLVE(andor_job_list) { if (token1.type == parse_token_type_end) { return production_for(); - } else if (token1.keyword == parse_keyword_and || token1.keyword == parse_keyword_or) { + } else if (token1.keyword == parse_keyword_t::kw_and || + token1.keyword == parse_keyword_t::kw_or) { // Check that the argument to and/or is a string that's not help. Otherwise it's either 'and // --help' or a naked 'and', and not part of this list. if (token2.type == parse_token_type_string && !token2.is_help_argument) { @@ -295,16 +296,16 @@ RESOLVE(block_header) { UNUSED(out_tag); switch (token1.keyword) { - case parse_keyword_for: { + case parse_keyword_t::kw_for: { return production_for(); } - case parse_keyword_while: { + case parse_keyword_t::kw_while: { return production_for(); } - case parse_keyword_function: { + case parse_keyword_t::kw_function: { return production_for(); } - case parse_keyword_begin: { + case parse_keyword_t::kw_begin: { return production_for(); } default: { @@ -327,7 +328,7 @@ RESOLVE(decorated_statement) { // and/or are typically parsed in job_conjunction at the beginning of a job // However they may be reached here through e.g. true && and false. // Refuse to parse them as a command except for --help. See #6089. - if ((token1.keyword == parse_keyword_and || token1.keyword == parse_keyword_or) && + if ((token1.keyword == parse_keyword_t::kw_and || token1.keyword == parse_keyword_t::kw_or) && !token2.is_help_argument) { return NO_PRODUCTION; } @@ -340,15 +341,15 @@ RESOLVE(decorated_statement) { } switch (token1.keyword) { - case parse_keyword_command: { + case parse_keyword_t::kw_command: { *out_tag = parse_statement_decoration_command; return production_for(); } - case parse_keyword_builtin: { + case parse_keyword_t::kw_builtin: { *out_tag = parse_statement_decoration_builtin; return production_for(); } - case parse_keyword_exec: { + case parse_keyword_t::kw_exec: { *out_tag = parse_statement_decoration_exec; return production_for(); } @@ -396,7 +397,7 @@ RESOLVE(optional_background) { } RESOLVE(optional_time) { - if (token1.keyword == parse_keyword_time && !token2.is_help_argument) { + if (token1.keyword == parse_keyword_t::kw_time && !token2.is_help_argument) { *out_tag = parse_optional_time_time; return production_for