Skip to content

Commit 96ca6e5

Browse files
committed
Correct errors for invalid retry
1 parent 892d0f9 commit 96ca6e5

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ errors:
138138
- INVALID_PRINTABLE_CHARACTER
139139
- INVALID_VARIABLE_GLOBAL
140140
- INVALID_VARIABLE_GLOBAL_3_3_0
141+
- INVALID_RETRY_AFTER_ELSE
142+
- INVALID_RETRY_AFTER_ENSURE
143+
- INVALID_RETRY_WITHOUT_RESCUE
141144
- IT_NOT_ALLOWED_NUMBERED
142145
- IT_NOT_ALLOWED_ORDINARY
143146
- LAMBDA_OPEN

src/prism.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15763,6 +15763,75 @@ parse_block_exit(pm_parser_t *parser, pm_token_t *token) {
1576315763
}
1576415764
}
1576515765

15766+
/**
15767+
* Ensures that the current retry token is valid in the current context.
15768+
*/
15769+
static void
15770+
parse_retry(pm_parser_t *parser, pm_token_t *token) {
15771+
pm_context_node_t *context_node = parser->current_context;
15772+
15773+
while (context_node != NULL) {
15774+
switch (context_node->context) {
15775+
case PM_CONTEXT_RESCUE:
15776+
case PM_CONTEXT_RESCUE_DEF:
15777+
// These are the good cases. We're allowed to have a retry here.
15778+
return;
15779+
case PM_CONTEXT_CLASS:
15780+
case PM_CONTEXT_DEF:
15781+
case PM_CONTEXT_DEF_PARAMS:
15782+
case PM_CONTEXT_MAIN:
15783+
case PM_CONTEXT_MODULE:
15784+
case PM_CONTEXT_PREEXE:
15785+
case PM_CONTEXT_SCLASS:
15786+
// These are the bad cases. We're not allowed to have a retry in
15787+
// these contexts.
15788+
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, *token, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE);
15789+
return;
15790+
case PM_CONTEXT_RESCUE_ELSE_DEF:
15791+
case PM_CONTEXT_RESCUE_ELSE:
15792+
// These are also bad cases, but with a more specific error
15793+
// message indicating the else.
15794+
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, *token, PM_ERR_INVALID_RETRY_AFTER_ELSE);
15795+
return;
15796+
case PM_CONTEXT_ENSURE:
15797+
case PM_CONTEXT_ENSURE_DEF:
15798+
// These are also bad cases, but with a more specific error
15799+
// message indicating the ensure.
15800+
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, *token, PM_ERR_INVALID_RETRY_AFTER_ENSURE);
15801+
return;
15802+
case PM_CONTEXT_NONE:
15803+
// This case should never happen.
15804+
assert(false && "unreachable");
15805+
break;
15806+
case PM_CONTEXT_BEGIN:
15807+
case PM_CONTEXT_BLOCK_BRACES:
15808+
case PM_CONTEXT_BLOCK_KEYWORDS:
15809+
case PM_CONTEXT_CASE_IN:
15810+
case PM_CONTEXT_CASE_WHEN:
15811+
case PM_CONTEXT_DEFAULT_PARAMS:
15812+
case PM_CONTEXT_ELSE:
15813+
case PM_CONTEXT_ELSIF:
15814+
case PM_CONTEXT_EMBEXPR:
15815+
case PM_CONTEXT_FOR_INDEX:
15816+
case PM_CONTEXT_FOR:
15817+
case PM_CONTEXT_IF:
15818+
case PM_CONTEXT_LAMBDA_BRACES:
15819+
case PM_CONTEXT_LAMBDA_DO_END:
15820+
case PM_CONTEXT_PARENS:
15821+
case PM_CONTEXT_POSTEXE:
15822+
case PM_CONTEXT_PREDICATE:
15823+
case PM_CONTEXT_UNLESS:
15824+
case PM_CONTEXT_UNTIL:
15825+
case PM_CONTEXT_WHILE:
15826+
// In these contexts we should continue walking up the list of
15827+
// contexts.
15828+
break;
15829+
}
15830+
15831+
context_node = context_node->prev;
15832+
}
15833+
}
15834+
1576615835
/**
1576715836
* Parse an expression that begins with the previous node that we just lexed.
1576815837
*/
@@ -17355,6 +17424,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1735517424
parser_lex(parser);
1735617425
return (pm_node_t *) pm_redo_node_create(parser, &parser->previous);
1735717426
case PM_TOKEN_KEYWORD_RETRY:
17427+
parse_retry(parser, &parser->current);
1735817428
parser_lex(parser);
1735917429
return (pm_node_t *) pm_retry_node_create(parser, &parser->previous);
1736017430
case PM_TOKEN_KEYWORD_SELF:

templates/src/diagnostic.c.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
219219
[PM_ERR_INVALID_MULTIBYTE_ESCAPE] = { "invalid multibyte escape: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
220220
[PM_ERR_INVALID_PRINTABLE_CHARACTER] = { "invalid character `%c`", PM_ERROR_LEVEL_SYNTAX },
221221
[PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_LEVEL_SYNTAX }, // TODO WHAT?
222+
[PM_ERR_INVALID_RETRY_AFTER_ELSE] = { "Invalid retry after else", PM_ERROR_LEVEL_SYNTAX },
223+
[PM_ERR_INVALID_RETRY_AFTER_ENSURE] = { "Invalid retry after ensure", PM_ERROR_LEVEL_SYNTAX },
224+
[PM_ERR_INVALID_RETRY_WITHOUT_RESCUE] = { "Invalid retry without rescue", PM_ERROR_LEVEL_SYNTAX },
222225
[PM_ERR_INVALID_VARIABLE_GLOBAL_3_3_0] = { "`%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX },
223226
[PM_ERR_INVALID_VARIABLE_GLOBAL] = { "'%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX },
224227
[PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "`it` is not allowed when an numbered parameter is defined", PM_ERROR_LEVEL_SYNTAX },

0 commit comments

Comments
 (0)