From b7e89d4b175a88be333134066b595d1e34c33fd3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 13 Dec 2023 21:35:42 -0500 Subject: [PATCH] [ruby/prism] Fix hash pattern rest https://github.com/ruby/prism/commit/43c4232cfc --- prism/diagnostic.c | 1 + prism/diagnostic.h | 1 + prism/prism.c | 21 +++++++--- .../seattlerb/case_in_hash_pat_rest.txt | 38 +++++++++---------- .../snapshots/seattlerb/parse_pattern_058.txt | 36 +++++++++--------- .../seattlerb/parse_pattern_058_2.txt | 28 +++++++------- .../snapshots/seattlerb/parse_pattern_076.txt | 34 ++++++++--------- 7 files changed, 85 insertions(+), 74 deletions(-) diff --git a/prism/diagnostic.c b/prism/diagnostic.c index eaf6112d18e197..1fc8c50cb51e39 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -219,6 +219,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_PATTERN_EXPRESSION_AFTER_PIN] = "expected a pattern expression after the `^` pin operator", [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = "expected a pattern expression after the `|` operator", [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = "expected a pattern expression after the range operator", + [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = "unexpected pattern expression after the `**` expression", [PM_ERR_PATTERN_HASH_KEY] = "expected a key in the hash pattern", [PM_ERR_PATTERN_HASH_KEY_LABEL] = "expected a label as the key in the hash pattern", // TODO // THIS // AND // ABOVE // IS WEIRD [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = "expected an identifier after the `=>` operator", diff --git a/prism/diagnostic.h b/prism/diagnostic.h index a1e0b6d0d82a98..fc1f0c2b4bb23a 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -211,6 +211,7 @@ typedef enum { PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, + PM_ERR_PATTERN_EXPRESSION_AFTER_REST, PM_ERR_PATTERN_HASH_KEY, PM_ERR_PATTERN_HASH_KEY_LABEL, PM_ERR_PATTERN_IDENT_AFTER_HROCKET, diff --git a/prism/prism.c b/prism/prism.c index 4b15f658590b4c..dfb1affa881ae6 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -13121,10 +13121,15 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { break; } - pm_node_t *assoc; - if (match1(parser, PM_TOKEN_USTAR_STAR)) { - assoc = parse_pattern_keyword_rest(parser); + pm_node_t *assoc = parse_pattern_keyword_rest(parser); + + if (rest == NULL) { + rest = assoc; + } else { + pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); + pm_node_list_append(&assocs, assoc); + } } else { expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA); pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); @@ -13138,10 +13143,14 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { } pm_token_t operator = not_provided(parser); - assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value); - } + pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value); + + if (rest != NULL) { + pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); + } - pm_node_list_append(&assocs, assoc); + pm_node_list_append(&assocs, assoc); + } } pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest); diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt index e218788cdc3ce5..bfdfa905059419 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt @@ -16,27 +16,27 @@ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,15)) │ │ ├── constant: ∅ - │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (2,3)-(2,7)) - │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" - │ │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" - │ │ │ │ │ └── unescaped: "b" - │ │ │ │ ├── value: - │ │ │ │ │ @ LocalVariableTargetNode (location: (2,6)-(2,7)) - │ │ │ │ │ ├── name: :c - │ │ │ │ │ └── depth: 0 - │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ AssocSplatNode (location: (2,9)-(2,15)) + │ │ ├── elements: (length: 1) + │ │ │ └── @ AssocNode (location: (2,3)-(2,7)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" + │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" + │ │ │ │ └── unescaped: "b" │ │ │ ├── value: - │ │ │ │ @ LocalVariableTargetNode (location: (2,11)-(2,15)) - │ │ │ │ ├── name: :rest + │ │ │ │ @ LocalVariableTargetNode (location: (2,6)-(2,7)) + │ │ │ │ ├── name: :c │ │ │ │ └── depth: 0 - │ │ │ └── operator_loc: (2,9)-(2,11) = "**" - │ │ ├── rest: ∅ + │ │ │ └── operator_loc: ∅ + │ │ ├── rest: + │ │ │ @ AssocSplatNode (location: (2,9)-(2,15)) + │ │ │ ├── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,11)-(2,15)) + │ │ │ │ ├── name: :rest + │ │ │ │ └── depth: 0 + │ │ │ └── operator_loc: (2,9)-(2,11) = "**" │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ ├── statements: diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058.txt b/test/prism/snapshots/seattlerb/parse_pattern_058.txt index b4a1b2650bf6c1..d372ece2d4021f 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058.txt @@ -26,24 +26,24 @@ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,15)) │ │ ├── constant: ∅ - │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (2,4)-(2,6)) - │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" - │ │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" - │ │ │ │ │ └── unescaped: "a" - │ │ │ │ ├── value: ∅ - │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ AssocSplatNode (location: (2,8)-(2,14)) - │ │ │ ├── value: - │ │ │ │ @ LocalVariableTargetNode (location: (2,10)-(2,14)) - │ │ │ │ ├── name: :rest - │ │ │ │ └── depth: 0 - │ │ │ └── operator_loc: (2,8)-(2,10) = "**" - │ │ ├── rest: ∅ + │ │ ├── elements: (length: 1) + │ │ │ └── @ AssocNode (location: (2,4)-(2,6)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" + │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" + │ │ │ │ └── unescaped: "a" + │ │ │ ├── value: ∅ + │ │ │ └── operator_loc: ∅ + │ │ ├── rest: + │ │ │ @ AssocSplatNode (location: (2,8)-(2,14)) + │ │ │ ├── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,10)-(2,14)) + │ │ │ │ ├── name: :rest + │ │ │ │ └── depth: 0 + │ │ │ └── operator_loc: (2,8)-(2,10) = "**" │ │ ├── opening_loc: (2,3)-(2,4) = "{" │ │ └── closing_loc: (2,14)-(2,15) = "}" │ ├── statements: diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt index f6625efc695a02..b75b198907a9e2 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt @@ -26,21 +26,21 @@ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,11)) │ │ ├── constant: ∅ - │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (2,4)-(2,6)) - │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" - │ │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" - │ │ │ │ │ └── unescaped: "a" - │ │ │ │ ├── value: ∅ - │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ AssocSplatNode (location: (2,8)-(2,10)) + │ │ ├── elements: (length: 1) + │ │ │ └── @ AssocNode (location: (2,4)-(2,6)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" + │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" + │ │ │ │ └── unescaped: "a" │ │ │ ├── value: ∅ - │ │ │ └── operator_loc: (2,8)-(2,10) = "**" - │ │ ├── rest: ∅ + │ │ │ └── operator_loc: ∅ + │ │ ├── rest: + │ │ │ @ AssocSplatNode (location: (2,8)-(2,10)) + │ │ │ ├── value: ∅ + │ │ │ └── operator_loc: (2,8)-(2,10) = "**" │ │ ├── opening_loc: (2,3)-(2,4) = "{" │ │ └── closing_loc: (2,10)-(2,11) = "}" │ ├── statements: diff --git a/test/prism/snapshots/seattlerb/parse_pattern_076.txt b/test/prism/snapshots/seattlerb/parse_pattern_076.txt index 7cf05ddad4c60b..8f4ef571c7c7bf 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_076.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_076.txt @@ -26,23 +26,23 @@ │ ├── pattern: │ │ @ HashPatternNode (location: (2,3)-(2,16)) │ │ ├── constant: ∅ - │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (2,4)-(2,8)) - │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" - │ │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" - │ │ │ │ │ └── unescaped: "a" - │ │ │ │ ├── value: - │ │ │ │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ │ │ │ └── flags: decimal - │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ NoKeywordsParameterNode (location: (2,10)-(2,15)) - │ │ │ ├── operator_loc: (2,10)-(2,12) = "**" - │ │ │ └── keyword_loc: (2,12)-(2,15) = "nil" - │ │ ├── rest: ∅ + │ │ ├── elements: (length: 1) + │ │ │ └── @ AssocNode (location: (2,4)-(2,8)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" + │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" + │ │ │ │ └── unescaped: "a" + │ │ │ ├── value: + │ │ │ │ @ IntegerNode (location: (2,7)-(2,8)) + │ │ │ │ └── flags: decimal + │ │ │ └── operator_loc: ∅ + │ │ ├── rest: + │ │ │ @ NoKeywordsParameterNode (location: (2,10)-(2,15)) + │ │ │ ├── operator_loc: (2,10)-(2,12) = "**" + │ │ │ └── keyword_loc: (2,12)-(2,15) = "nil" │ │ ├── opening_loc: (2,3)-(2,4) = "{" │ │ └── closing_loc: (2,15)-(2,16) = "}" │ ├── statements: