[ruby/prism] Fix up find and array patterns with multiple rests

https://github.com/ruby/prism/commit/035890a839
This commit is contained in:
Kevin Newton 2024-07-01 10:59:51 -04:00 коммит произвёл git
Родитель 8fb2227205
Коммит 0ac9c6dc10
3 изменённых файлов: 25 добавлений и 13 удалений

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

@ -208,6 +208,7 @@ errors:
- PARAMETER_UNEXPECTED_FWD - PARAMETER_UNEXPECTED_FWD
- PARAMETER_UNEXPECTED_NO_KW - PARAMETER_UNEXPECTED_NO_KW
- PARAMETER_WILD_LOOSE_COMMA - PARAMETER_WILD_LOOSE_COMMA
- PATTERN_ARRAY_MULTIPLE_RESTS
- PATTERN_CAPTURE_DUPLICATE - PATTERN_CAPTURE_DUPLICATE
- PATTERN_EXPRESSION_AFTER_BRACKET - PATTERN_EXPRESSION_AFTER_BRACKET
- PATTERN_EXPRESSION_AFTER_COMMA - PATTERN_EXPRESSION_AFTER_COMMA
@ -219,6 +220,7 @@ errors:
- PATTERN_EXPRESSION_AFTER_PIPE - PATTERN_EXPRESSION_AFTER_PIPE
- PATTERN_EXPRESSION_AFTER_RANGE - PATTERN_EXPRESSION_AFTER_RANGE
- PATTERN_EXPRESSION_AFTER_REST - PATTERN_EXPRESSION_AFTER_REST
- PATTERN_FIND_MISSING_INNER
- PATTERN_HASH_IMPLICIT - PATTERN_HASH_IMPLICIT
- PATTERN_HASH_KEY - PATTERN_HASH_KEY
- PATTERN_HASH_KEY_DUPLICATE - PATTERN_HASH_KEY_DUPLICATE

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

@ -17049,9 +17049,9 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
} }
if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) { if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) {
// If we have a comma, then we are now parsing either an array pattern or a // If we have a comma, then we are now parsing either an array pattern
// find pattern. We need to parse all of the patterns, put them into a big // or a find pattern. We need to parse all of the patterns, put them
// list, and then determine which type of node we have. // into a big list, and then determine which type of node we have.
pm_node_list_t nodes = { 0 }; pm_node_list_t nodes = { 0 };
pm_node_list_append(&nodes, node); pm_node_list_append(&nodes, node);
@ -17067,9 +17067,9 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
if (accept1(parser, PM_TOKEN_USTAR)) { if (accept1(parser, PM_TOKEN_USTAR)) {
node = (pm_node_t *) parse_pattern_rest(parser, captures); node = (pm_node_t *) parse_pattern_rest(parser, captures);
// If we have already parsed a splat pattern, then this is an error. We // If we have already parsed a splat pattern, then this is an
// will continue to parse the rest of the patterns, but we will indicate // error. We will continue to parse the rest of the patterns,
// it as an error. // but we will indicate it as an error.
if (trailing_rest) { if (trailing_rest) {
pm_parser_err_previous(parser, PM_ERR_PATTERN_REST); pm_parser_err_previous(parser, PM_ERR_PATTERN_REST);
} }
@ -17082,20 +17082,28 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
pm_node_list_append(&nodes, node); pm_node_list_append(&nodes, node);
} }
// If the first pattern and the last pattern are rest patterns, then we will // If the first pattern and the last pattern are rest patterns, then we
// call this a find pattern, regardless of how many rest patterns are in // will call this a find pattern, regardless of how many rest patterns
// between because we know we already added the appropriate errors. // are in between because we know we already added the appropriate
// Otherwise we will create an array pattern. // errors. Otherwise we will create an array pattern.
if (PM_NODE_TYPE_P(nodes.nodes[0], PM_SPLAT_NODE) && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) { if (leading_rest && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes); node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes);
if (nodes.size == 2) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER);
}
} else { } else {
node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes); node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes);
if (leading_rest && trailing_rest) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS);
}
} }
xfree(nodes.nodes); xfree(nodes.nodes);
} else if (leading_rest) { } else if (leading_rest) {
// Otherwise, if we parsed a single splat pattern, then we know we have an // Otherwise, if we parsed a single splat pattern, then we know we have
// array pattern, so we can go ahead and create that node. // an array pattern, so we can go ahead and create that node.
node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node); node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node);
} }

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

@ -290,6 +290,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS] = { "unexpected multiple '*' rest patterns in an array pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_SYNTAX },
@ -301,6 +302,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_FIND_MISSING_INNER] = { "find patterns need at least one required inner pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX },