From e454cf22023c95e80689bb26ab1abd2775015fbf Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 2 Apr 2024 12:19:39 -0400 Subject: [ruby/prism] Update fixtures to be all valid Ruby https://github.com/ruby/prism/commit/a0b978d25b --- prism/config.yml | 5 ++- prism/prism.c | 75 +++++++++++++++++++++++++++++++++--- prism/templates/src/diagnostic.c.erb | 1 + 3 files changed, 73 insertions(+), 8 deletions(-) (limited to 'prism') diff --git a/prism/config.yml b/prism/config.yml index cb11e0cab0..df3a4714e6 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -136,11 +136,12 @@ errors: - INVALID_NUMBER_UNDERSCORE - INVALID_PERCENT - INVALID_PRINTABLE_CHARACTER - - INVALID_VARIABLE_GLOBAL - - INVALID_VARIABLE_GLOBAL_3_3_0 - INVALID_RETRY_AFTER_ELSE - INVALID_RETRY_AFTER_ENSURE - INVALID_RETRY_WITHOUT_RESCUE + - INVALID_VARIABLE_GLOBAL + - INVALID_VARIABLE_GLOBAL_3_3_0 + - INVALID_YIELD - IT_NOT_ALLOWED_NUMBERED - IT_NOT_ALLOWED_ORDINARY - LAMBDA_OPEN diff --git a/prism/prism.c b/prism/prism.c index 2a83826e07..88237c654d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -15705,7 +15705,7 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { * context. If it isn't, add an error to the parser. */ static void -parse_block_exit(pm_parser_t *parser, pm_token_t *token) { +parse_block_exit(pm_parser_t *parser, const pm_token_t *token) { pm_context_node_t *context_node = parser->current_context; while (context_node != NULL) { @@ -15721,9 +15721,12 @@ parse_block_exit(pm_parser_t *parser, pm_token_t *token) { case PM_CONTEXT_CLASS: case PM_CONTEXT_DEF: case PM_CONTEXT_DEF_PARAMS: + case PM_CONTEXT_ENSURE_DEF: case PM_CONTEXT_MAIN: case PM_CONTEXT_MODULE: case PM_CONTEXT_PREEXE: + case PM_CONTEXT_RESCUE_DEF: + case PM_CONTEXT_RESCUE_ELSE_DEF: case PM_CONTEXT_SCLASS: // These are the bad cases. We're not allowed to have a block // exit in these contexts. @@ -15741,16 +15744,13 @@ parse_block_exit(pm_parser_t *parser, pm_token_t *token) { case PM_CONTEXT_ELSIF: case PM_CONTEXT_EMBEXPR: case PM_CONTEXT_ENSURE: - case PM_CONTEXT_ENSURE_DEF: case PM_CONTEXT_FOR: case PM_CONTEXT_FOR_INDEX: case PM_CONTEXT_IF: case PM_CONTEXT_PARENS: case PM_CONTEXT_PREDICATE: case PM_CONTEXT_RESCUE_ELSE: - case PM_CONTEXT_RESCUE_ELSE_DEF: case PM_CONTEXT_RESCUE: - case PM_CONTEXT_RESCUE_DEF: case PM_CONTEXT_UNLESS: case PM_CONTEXT_UNTIL: case PM_CONTEXT_WHILE: @@ -15767,7 +15767,7 @@ parse_block_exit(pm_parser_t *parser, pm_token_t *token) { * Ensures that the current retry token is valid in the current context. */ static void -parse_retry(pm_parser_t *parser, pm_token_t *token) { +parse_retry(pm_parser_t *parser, const pm_token_t *token) { pm_context_node_t *context_node = parser->current_context; while (context_node != NULL) { @@ -15787,8 +15787,8 @@ parse_retry(pm_parser_t *parser, pm_token_t *token) { // these contexts. PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, *token, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE); return; - case PM_CONTEXT_RESCUE_ELSE_DEF: case PM_CONTEXT_RESCUE_ELSE: + case PM_CONTEXT_RESCUE_ELSE_DEF: // These are also bad cases, but with a more specific error // message indicating the else. PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, *token, PM_ERR_INVALID_RETRY_AFTER_ELSE); @@ -15832,6 +15832,68 @@ parse_retry(pm_parser_t *parser, pm_token_t *token) { } } +/** + * Ensures that the current yield token is valid in the current context. + */ +static void +parse_yield(pm_parser_t *parser, const pm_token_t *token) { + pm_context_node_t *context_node = parser->current_context; + + while (context_node != NULL) { + switch (context_node->context) { + case PM_CONTEXT_DEF: + case PM_CONTEXT_ENSURE_DEF: + case PM_CONTEXT_RESCUE_DEF: + case PM_CONTEXT_RESCUE_ELSE_DEF: + // These are the good cases. We're allowed to have a block exit + // in these contexts. + return; + case PM_CONTEXT_CLASS: + case PM_CONTEXT_MAIN: + case PM_CONTEXT_MODULE: + // These are the bad cases. We're not allowed to have a retry in + // these contexts. + pm_parser_err_token(parser, token, PM_ERR_INVALID_YIELD); + return; + case PM_CONTEXT_NONE: + // This case should never happen. + assert(false && "unreachable"); + break; + case PM_CONTEXT_BEGIN: + case PM_CONTEXT_BLOCK_BRACES: + case PM_CONTEXT_BLOCK_KEYWORDS: + case PM_CONTEXT_CASE_IN: + case PM_CONTEXT_CASE_WHEN: + case PM_CONTEXT_DEF_PARAMS: + case PM_CONTEXT_DEFAULT_PARAMS: + case PM_CONTEXT_ELSE: + case PM_CONTEXT_ELSIF: + case PM_CONTEXT_EMBEXPR: + case PM_CONTEXT_ENSURE: + case PM_CONTEXT_FOR_INDEX: + case PM_CONTEXT_FOR: + case PM_CONTEXT_IF: + case PM_CONTEXT_LAMBDA_BRACES: + case PM_CONTEXT_LAMBDA_DO_END: + case PM_CONTEXT_PARENS: + case PM_CONTEXT_POSTEXE: + case PM_CONTEXT_PREDICATE: + case PM_CONTEXT_PREEXE: + case PM_CONTEXT_RESCUE_ELSE: + case PM_CONTEXT_RESCUE: + case PM_CONTEXT_SCLASS: + case PM_CONTEXT_UNLESS: + case PM_CONTEXT_UNTIL: + case PM_CONTEXT_WHILE: + // In these contexts we should continue walking up the list of + // contexts. + break; + } + + context_node = context_node->prev; + } +} + /** * Parse an expression that begins with the previous node that we just lexed. */ @@ -16786,6 +16848,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b return (pm_node_t *) pm_super_node_create(parser, &keyword, &arguments); } case PM_TOKEN_KEYWORD_YIELD: { + parse_yield(parser, &parser->current); parser_lex(parser); pm_token_t keyword = parser->previous; diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 1cbe3c9a31..c7c5f1a625 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -224,6 +224,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_RETRY_WITHOUT_RESCUE] = { "Invalid retry without rescue", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_VARIABLE_GLOBAL_3_3_0] = { "`%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_VARIABLE_GLOBAL] = { "'%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_YIELD] = { "Invalid yield", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "`it` is not allowed when an numbered parameter is defined", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_IT_NOT_ALLOWED_ORDINARY] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_LEVEL_SYNTAX }, -- cgit v1.2.3