Skip to content

Commit 035890a

Browse files
committed
Fix up find and array patterns with multiple rests
1 parent bedc458 commit 035890a

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

config.yml

+2
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ errors:
208208
- PARAMETER_UNEXPECTED_FWD
209209
- PARAMETER_UNEXPECTED_NO_KW
210210
- PARAMETER_WILD_LOOSE_COMMA
211+
- PATTERN_ARRAY_MULTIPLE_RESTS
211212
- PATTERN_CAPTURE_DUPLICATE
212213
- PATTERN_EXPRESSION_AFTER_BRACKET
213214
- PATTERN_EXPRESSION_AFTER_COMMA
@@ -219,6 +220,7 @@ errors:
219220
- PATTERN_EXPRESSION_AFTER_PIPE
220221
- PATTERN_EXPRESSION_AFTER_RANGE
221222
- PATTERN_EXPRESSION_AFTER_REST
223+
- PATTERN_FIND_MISSING_INNER
222224
- PATTERN_HASH_IMPLICIT
223225
- PATTERN_HASH_KEY
224226
- PATTERN_HASH_KEY_DUPLICATE

src/prism.c

+21-13
Original file line numberDiff line numberDiff line change
@@ -17049,9 +17049,9 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
1704917049
}
1705017050

1705117051
if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) {
17052-
// If we have a comma, then we are now parsing either an array pattern or a
17053-
// find pattern. We need to parse all of the patterns, put them into a big
17054-
// list, and then determine which type of node we have.
17052+
// If we have a comma, then we are now parsing either an array pattern
17053+
// or a find pattern. We need to parse all of the patterns, put them
17054+
// into a big list, and then determine which type of node we have.
1705517055
pm_node_list_t nodes = { 0 };
1705617056
pm_node_list_append(&nodes, node);
1705717057

@@ -17067,9 +17067,9 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
1706717067
if (accept1(parser, PM_TOKEN_USTAR)) {
1706817068
node = (pm_node_t *) parse_pattern_rest(parser, captures);
1706917069

17070-
// If we have already parsed a splat pattern, then this is an error. We
17071-
// will continue to parse the rest of the patterns, but we will indicate
17072-
// it as an error.
17070+
// If we have already parsed a splat pattern, then this is an
17071+
// error. We will continue to parse the rest of the patterns,
17072+
// but we will indicate it as an error.
1707317073
if (trailing_rest) {
1707417074
pm_parser_err_previous(parser, PM_ERR_PATTERN_REST);
1707517075
}
@@ -17082,20 +17082,28 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
1708217082
pm_node_list_append(&nodes, node);
1708317083
}
1708417084

17085-
// If the first pattern and the last pattern are rest patterns, then we will
17086-
// call this a find pattern, regardless of how many rest patterns are in
17087-
// between because we know we already added the appropriate errors.
17088-
// Otherwise we will create an array pattern.
17089-
if (PM_NODE_TYPE_P(nodes.nodes[0], PM_SPLAT_NODE) && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
17085+
// If the first pattern and the last pattern are rest patterns, then we
17086+
// will call this a find pattern, regardless of how many rest patterns
17087+
// are in between because we know we already added the appropriate
17088+
// errors. Otherwise we will create an array pattern.
17089+
if (leading_rest && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
1709017090
node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes);
17091+
17092+
if (nodes.size == 2) {
17093+
pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER);
17094+
}
1709117095
} else {
1709217096
node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes);
17097+
17098+
if (leading_rest && trailing_rest) {
17099+
pm_parser_err_node(parser, node, PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS);
17100+
}
1709317101
}
1709417102

1709517103
xfree(nodes.nodes);
1709617104
} else if (leading_rest) {
17097-
// Otherwise, if we parsed a single splat pattern, then we know we have an
17098-
// array pattern, so we can go ahead and create that node.
17105+
// Otherwise, if we parsed a single splat pattern, then we know we have
17106+
// an array pattern, so we can go ahead and create that node.
1709917107
node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node);
1710017108
}
1710117109

templates/src/diagnostic.c.erb

+2
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
290290
[PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_SYNTAX },
291291
[PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_SYNTAX },
292292
[PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX },
293+
[PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS] = { "unexpected multiple '*' rest patterns in an array pattern", PM_ERROR_LEVEL_SYNTAX },
293294
[PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX },
294295
[PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX },
295296
[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] = {
301302
[PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX },
302303
[PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX },
303304
[PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX },
305+
[PM_ERR_PATTERN_FIND_MISSING_INNER] = { "find patterns need at least one required inner pattern", PM_ERROR_LEVEL_SYNTAX },
304306
[PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX },
305307
[PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX },
306308
[PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX },

0 commit comments

Comments
 (0)