@@ -15763,6 +15763,75 @@ parse_block_exit(pm_parser_t *parser, pm_token_t *token) {
15763
15763
}
15764
15764
}
15765
15765
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
+
15766
15835
/**
15767
15836
* Parse an expression that begins with the previous node that we just lexed.
15768
15837
*/
@@ -17355,6 +17424,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
17355
17424
parser_lex(parser);
17356
17425
return (pm_node_t *) pm_redo_node_create(parser, &parser->previous);
17357
17426
case PM_TOKEN_KEYWORD_RETRY:
17427
+ parse_retry(parser, &parser->current);
17358
17428
parser_lex(parser);
17359
17429
return (pm_node_t *) pm_retry_node_create(parser, &parser->previous);
17360
17430
case PM_TOKEN_KEYWORD_SELF:
0 commit comments