Skip to content

Commit

Permalink
Merge pull request #3124 from ruby/beginless-ranges
Browse files Browse the repository at this point in the history
Fix up beginless ranges in method definitions
  • Loading branch information
kddnewton authored Oct 2, 2024
2 parents 3eacea4 + ab9d809 commit 7ea42f6
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 10 deletions.
29 changes: 19 additions & 10 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -11452,10 +11452,7 @@ parser_lex(pm_parser_t *parser) {
if (match(parser, '.')) {
if (match(parser, '.')) {
// If we're _not_ inside a range within default parameters
if (
!context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) &&
context_p(parser, PM_CONTEXT_DEF_PARAMS)
) {
if (!context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) && context_p(parser, PM_CONTEXT_DEF_PARAMS)) {
if (lex_state_p(parser, PM_LEX_STATE_END)) {
lex_state_set(parser, PM_LEX_STATE_BEG);
} else {
Expand Down Expand Up @@ -14572,9 +14569,10 @@ parse_parameters(
bool repeated = pm_parser_parameter_name_check(parser, &name);
pm_parser_local_add_token(parser, &name, 1);

if (accept1(parser, PM_TOKEN_EQUAL)) {
pm_token_t operator = parser->previous;
if (match1(parser, PM_TOKEN_EQUAL)) {
pm_token_t operator = parser->current;
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
parser_lex(parser);

pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &name);
uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
Expand Down Expand Up @@ -14625,6 +14623,8 @@ parse_parameters(
case PM_TOKEN_LABEL: {
if (!uses_parentheses) parser->in_keyword_arg = true;
update_parameter_state(parser, &parser->current, &order);

context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
parser_lex(parser);

pm_token_t name = parser->previous;
Expand All @@ -14644,15 +14644,20 @@ parse_parameters(
case PM_TOKEN_COMMA:
case PM_TOKEN_PARENTHESIS_RIGHT:
case PM_TOKEN_PIPE: {
context_pop(parser);

pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}

pm_parameters_node_keywords_append(params, param);
break;
}
case PM_TOKEN_SEMICOLON:
case PM_TOKEN_NEWLINE: {
context_pop(parser);

if (uses_parentheses) {
looping = false;
break;
Expand All @@ -14662,15 +14667,14 @@ parse_parameters(
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}

pm_parameters_node_keywords_append(params, param);
break;
}
default: {
pm_node_t *param;

if (token_begins_expression_p(parser->current.type)) {
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);

pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &local);
uint32_t reads = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;

Expand All @@ -14682,7 +14686,6 @@ parse_parameters(
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_PARAMETER_CIRCULAR);
}

context_pop(parser);
param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
}
else {
Expand All @@ -14692,6 +14695,8 @@ parse_parameters(
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}

context_pop(parser);
pm_parameters_node_keywords_append(params, param);

// If parsing the value of the parameter resulted in error recovery,
Expand Down Expand Up @@ -19247,6 +19252,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
lex_state_set(parser, PM_LEX_STATE_BEG);
parser->command_start = true;

context_pop(parser);
if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_type_human(parser->current.type));
parser->previous.start = parser->previous.end;
Expand All @@ -19266,17 +19272,20 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
lparen = not_provided(parser);
rparen = not_provided(parser);
params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, (uint16_t) (depth + 1));

context_pop(parser);
break;
}
default: {
lparen = not_provided(parser);
rparen = not_provided(parser);
params = NULL;

context_pop(parser);
break;
}
}

context_pop(parser);
pm_node_t *statements = NULL;
pm_token_t equal;
pm_token_t end_keyword;
Expand Down
5 changes: 5 additions & 0 deletions test/prism/fixtures/range_beginless.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def f(x = ...?a); end

def f(x: ...?a); end

def f() ...:a; end
114 changes: 114 additions & 0 deletions test/prism/snapshots/range_beginless.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7ea42f6

Please sign in to comment.