[ruby/prism] Disallow dynamic patterns in labels at top level followed by pipes

https://github.com/ruby/prism/commit/ccc746f918
This commit is contained in:
Kevin Newton 2024-10-01 14:21:32 -04:00
Родитель e320da6097
Коммит 467ebbebd9
2 изменённых файлов: 30 добавлений и 6 удалений

Просмотреть файл

@ -17274,6 +17274,9 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
case PM_CASE_PRIMITIVE: {
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, diag_id, (uint16_t) (depth + 1));
// If we found a label, we need to immediately return to the caller.
if (pm_symbol_node_label_p(node)) return node;
// Now that we have a primitive, we need to check if it's part of a range.
if (accept2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) {
pm_token_t operator = parser->previous;
@ -17391,10 +17394,10 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
* assignment.
*/
static pm_node_t *
parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id, uint16_t depth) {
pm_node_t *node = NULL;
parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, pm_diagnostic_id_t diag_id, uint16_t depth) {
pm_node_t *node = first_node;
do {
while ((node == NULL) || accept1(parser, PM_TOKEN_PIPE)) {
pm_token_t operator = parser->previous;
switch (parser->current.type) {
@ -17447,7 +17450,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
break;
}
}
} while (accept1(parser, PM_TOKEN_PIPE));
}
// If we have an =>, then we are assigning this pattern to a variable.
// In this case we should create an assignment node.
@ -17508,6 +17511,24 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
return node;
}
case PM_TOKEN_STRING_BEGIN: {
// We need special handling for string beginnings because they could
// be dynamic symbols leading to hash patterns.
node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1));
if (pm_symbol_node_label_p(node)) {
node = (pm_node_t *) parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
}
return node;
}
node = parse_pattern_primitives(parser, captures, node, diag_id, (uint16_t) (depth + 1));
break;
}
case PM_TOKEN_USTAR: {
if (flags & (PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI)) {
parser_lex(parser);
@ -17518,7 +17539,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
}
/* fallthrough */
default:
node = parse_pattern_primitives(parser, captures, diag_id, (uint16_t) (depth + 1));
node = parse_pattern_primitives(parser, captures, NULL, diag_id, (uint16_t) (depth + 1));
break;
}
@ -17556,7 +17577,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
trailing_rest = true;
} else {
node = parse_pattern_primitives(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
node = parse_pattern_primitives(parser, captures, NULL, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
}
pm_node_list_append(&nodes, node);

Просмотреть файл

@ -0,0 +1,3 @@
:a => 'a': | 1
^ expected a pattern expression after the key