From a96110f7ef2a8f2a15bc35275201cee4ae4bcaee Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 13 Feb 2024 15:11:17 -0500 Subject: [PATCH] [ruby/prism] Convert more error messages to match specs https://github.com/ruby/prism/commit/7987b7aa20 --- prism/diagnostic.c | 7 ++----- prism/diagnostic.h | 5 +---- prism/prism.c | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 957cc47d7c..80805c9b3e 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -184,7 +184,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_LEVEL_FATAL }, [PM_ERR_FOR_TERM] = { "expected an `end` to close the `for` loop", PM_ERROR_LEVEL_FATAL }, [PM_ERR_HASH_EXPRESSION_AFTER_LABEL] = { "expected an expression after the label in a hash", PM_ERROR_LEVEL_FATAL }, - [PM_ERR_HASH_KEY] = { "expected a key in the hash literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_KEY] = { "unexpected %s, expecting '}' or a key in the hash literal", PM_ERROR_LEVEL_FATAL }, [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_LEVEL_FATAL }, [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_LEVEL_FATAL }, [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_LEVEL_FATAL }, @@ -284,12 +284,9 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_LEVEL_FATAL }, [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_FATAL }, [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_FATAL }, - [PM_ERR_UNARY_RECEIVER_BANG] = { "expected a receiver for unary `!`", PM_ERROR_LEVEL_FATAL }, - [PM_ERR_UNARY_RECEIVER_MINUS] = { "expected a receiver for unary `-`", PM_ERROR_LEVEL_FATAL }, - [PM_ERR_UNARY_RECEIVER_PLUS] = { "expected a receiver for unary `+`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNARY_RECEIVER] = { "unexpected %s, expected a receiver for unary `%c`", PM_ERROR_LEVEL_FATAL }, [PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_FATAL }, [PM_ERR_UNEXPECTED_TOKEN_IGNORE] = { "unexpected %s, ignoring it", PM_ERROR_LEVEL_FATAL }, - [PM_ERR_UNARY_RECEIVER_TILDE] = { "expected a receiver for unary `~`", PM_ERROR_LEVEL_FATAL }, [PM_ERR_UNTIL_TERM] = { "expected an `end` to close the `until` statement", PM_ERROR_LEVEL_FATAL }, [PM_ERR_VOID_EXPRESSION] = { "unexpected void value expression", PM_ERROR_LEVEL_FATAL }, [PM_ERR_WHILE_TERM] = { "expected an `end` to close the `while` statement", PM_ERROR_LEVEL_FATAL }, diff --git a/prism/diagnostic.h b/prism/diagnostic.h index ebd4a8bb7d..bf47e8dbca 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -281,10 +281,7 @@ typedef enum { PM_ERR_TERNARY_COLON, PM_ERR_TERNARY_EXPRESSION_FALSE, PM_ERR_TERNARY_EXPRESSION_TRUE, - PM_ERR_UNARY_RECEIVER_BANG, - PM_ERR_UNARY_RECEIVER_MINUS, - PM_ERR_UNARY_RECEIVER_PLUS, - PM_ERR_UNARY_RECEIVER_TILDE, + PM_ERR_UNARY_RECEIVER, PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT, PM_ERR_UNEXPECTED_TOKEN_IGNORE, PM_ERR_UNDEF_ARGUMENT, diff --git a/prism/prism.c b/prism/prism.c index 7e1fae5ed6..d0b4265190 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14367,6 +14367,29 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { return current; } +/** + * Append an error to the error list on the parser using the given diagnostic + * ID. This function is a specialization that handles formatting the specific + * kind of error that is being appended. + */ +static void +pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { + switch (diag_id) { + case PM_ERR_HASH_KEY: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, pm_token_type_human(parser->previous.type)); + break; + } + case PM_ERR_UNARY_RECEIVER: { + const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]); + break; + } + default: + pm_parser_err_previous(parser, diag_id); + break; + } +} + /** * Parse an expression that begins with the previous node that we just lexed. */ @@ -16494,7 +16517,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // context of a multiple assignment. We enforce that here. We'll // still lex past it though and create a missing node place. if (binding_power != PM_BINDING_POWER_STATEMENT) { - pm_parser_err_previous(parser, diag_id); + pm_parser_err_prefix(parser, diag_id); return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end); } @@ -16517,7 +16540,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER_BANG); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!"); pm_conditional_predicate(receiver); @@ -16527,7 +16550,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_TILDE); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~"); return (pm_node_t *) node; @@ -16536,7 +16559,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@"); return (pm_node_t *) node; @@ -16545,7 +16568,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS); + pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); if (accept1(parser, PM_TOKEN_STAR_STAR)) { pm_token_t exponent_operator = parser->previous; @@ -16661,7 +16684,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_PLUS); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@"); return (pm_node_t *) node; @@ -16684,7 +16707,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // here because it will provide more context in addition to the // recoverable error that we will also add. if (diag_id != PM_ERR_CANNOT_PARSE_EXPRESSION) { - pm_parser_err_previous(parser, diag_id); + pm_parser_err_prefix(parser, diag_id); } // If we get here, then we are assuming this token is closing a @@ -16697,7 +16720,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // have an unexpected token. PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, pm_token_type_human(parser->current.type)); } else { - pm_parser_err_previous(parser, diag_id); + pm_parser_err_prefix(parser, diag_id); } return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);