[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_NO_KW
- PARAMETER_WILD_LOOSE_COMMA
- PATTERN_ARRAY_MULTIPLE_RESTS
- PATTERN_CAPTURE_DUPLICATE
- PATTERN_EXPRESSION_AFTER_BRACKET
- PATTERN_EXPRESSION_AFTER_COMMA
@ -219,6 +220,7 @@ errors:
- PATTERN_EXPRESSION_AFTER_PIPE
- PATTERN_EXPRESSION_AFTER_RANGE
- PATTERN_EXPRESSION_AFTER_REST
- PATTERN_FIND_MISSING_INNER
- PATTERN_HASH_IMPLICIT
- PATTERN_HASH_KEY
- 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 we have a comma, then we are now parsing either an array pattern or a
// find pattern. We need to parse all of the patterns, put them into a big
// list, and then determine which type of node we have.
// If we have a comma, then we are now parsing either an array pattern
// or a find pattern. We need to parse all of the patterns, put them
// into a big list, and then determine which type of node we have.
pm_node_list_t nodes = { 0 };
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)) {
node = (pm_node_t *) parse_pattern_rest(parser, captures);
// If we have already parsed a splat pattern, then this is an error. We
// will continue to parse the rest of the patterns, but we will indicate
// it as an error.
// If we have already parsed a splat pattern, then this is an
// error. We will continue to parse the rest of the patterns,
// but we will indicate it as an error.
if (trailing_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);
}
// If the first pattern and the last pattern are rest patterns, then we will
// call this a find pattern, regardless of how many rest patterns are in
// between because we know we already added the appropriate 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 the first pattern and the last pattern are rest patterns, then we
// will call this a find pattern, regardless of how many rest patterns
// are in between because we know we already added the appropriate
// errors. Otherwise we will create an array pattern.
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);
if (nodes.size == 2) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER);
}
} else {
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);
} else if (leading_rest) {
// Otherwise, if we parsed a single splat pattern, then we know we have an
// array pattern, so we can go ahead and create that node.
// Otherwise, if we parsed a single splat pattern, then we know we have
// an array pattern, so we can go ahead and create that 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_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_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_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 },
@ -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_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_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_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 },