From d1eaa97ec3cdbe38605379fc87a55987d6802dc7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 13 Mar 2024 08:47:41 -0400 Subject: [ruby/prism] Track parentheses in patterns https://github.com/ruby/prism/commit/62db99f156 --- lib/prism/translation/ripper.rb | 20 ++++-- prism/prism.c | 14 ++-- test/prism/snapshots/seattlerb/case_in.txt | 106 +++++++++++++++++------------ 3 files changed, 88 insertions(+), 52 deletions(-) diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index 94156d4988..9f269f9eb8 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -583,13 +583,23 @@ module Prism # foo => bar | baz # ^^^^^^^^^ def visit_alternation_pattern_node(node) - left = visit(node.left) - right = visit(node.right) + left = visit_pattern_node(node.left) + right = visit_pattern_node(node.right) bounds(node.location) on_binary(left, :|, right) end + # Visit a pattern within a pattern match. This is used to bypass the + # parenthesis node that can be used to wrap patterns. + private def visit_pattern_node(node) + if node.is_a?(ParenthesesNode) + visit(node.body) + else + visit(node) + end + end + # a and b # ^^^^^^^ def visit_and_node(node) @@ -1952,7 +1962,7 @@ module Prism # This is a special case where we're not going to call on_in directly # because we don't have access to the consequent. Instead, we'll return # the component parts and let the parent node handle it. - pattern = visit(node.pattern) + pattern = visit_pattern_node(node.pattern) statements = if node.statements.nil? bounds(node.location) @@ -2389,7 +2399,7 @@ module Prism # ^^^^^^^^^^ def visit_match_predicate_node(node) value = visit(node.value) - pattern = on_in(visit(node.pattern), nil, nil) + pattern = on_in(visit_pattern_node(node.pattern), nil, nil) on_case(value, pattern) end @@ -2398,7 +2408,7 @@ module Prism # ^^^^^^^^^^ def visit_match_required_node(node) value = visit(node.value) - pattern = on_in(visit(node.pattern), nil, nil) + pattern = on_in(visit_pattern_node(node.pattern), nil, nil) on_case(value, pattern) end diff --git a/prism/prism.c b/prism/prism.c index 947d1a92bb..1d94ead82a 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14883,14 +14883,20 @@ parse_pattern_primitives(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { break; } case PM_TOKEN_PARENTHESIS_LEFT: { + pm_token_t opening = parser->current; parser_lex(parser); - if (node != NULL) { - pm_node_destroy(parser, node); - } - node = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); + pm_node_t *body = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); + pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous); + + if (node == NULL) { + node = right; + } else { + node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator); + } + break; } default: { diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index e7e291c63f..950d66647e 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -186,16 +186,20 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (22,0)-(22,9)) + │ │ └── @ InNode (location: (22,0)-(22,10)) │ │ ├── pattern: - │ │ │ @ RangeNode (location: (22,4)-(22,9)) - │ │ │ ├── flags: exclude_end - │ │ │ ├── left: ∅ - │ │ │ ├── right: - │ │ │ │ @ IntegerNode (location: (22,7)-(22,9)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 10 - │ │ │ └── operator_loc: (22,4)-(22,7) = "..." + │ │ │ @ ParenthesesNode (location: (22,3)-(22,10)) + │ │ │ ├── body: + │ │ │ │ @ RangeNode (location: (22,4)-(22,9)) + │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── left: ∅ + │ │ │ │ ├── right: + │ │ │ │ │ @ IntegerNode (location: (22,7)-(22,9)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 + │ │ │ │ └── operator_loc: (22,4)-(22,7) = "..." + │ │ │ ├── opening_loc: (22,3)-(22,4) = "(" + │ │ │ └── closing_loc: (22,9)-(22,10) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (22,0)-(22,2) = "in" │ │ └── then_loc: ∅ @@ -211,16 +215,20 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (26,0)-(26,8)) + │ │ └── @ InNode (location: (26,0)-(26,9)) │ │ ├── pattern: - │ │ │ @ RangeNode (location: (26,4)-(26,8)) - │ │ │ ├── flags: ∅ - │ │ │ ├── left: ∅ - │ │ │ ├── right: - │ │ │ │ @ IntegerNode (location: (26,6)-(26,8)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 10 - │ │ │ └── operator_loc: (26,4)-(26,6) = ".." + │ │ │ @ ParenthesesNode (location: (26,3)-(26,9)) + │ │ │ ├── body: + │ │ │ │ @ RangeNode (location: (26,4)-(26,8)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── left: ∅ + │ │ │ │ ├── right: + │ │ │ │ │ @ IntegerNode (location: (26,6)-(26,8)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 + │ │ │ │ └── operator_loc: (26,4)-(26,6) = ".." + │ │ │ ├── opening_loc: (26,3)-(26,4) = "(" + │ │ │ └── closing_loc: (26,8)-(26,9) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (26,0)-(26,2) = "in" │ │ └── then_loc: ∅ @@ -236,16 +244,20 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (30,0)-(30,8)) + │ │ └── @ InNode (location: (30,0)-(30,9)) │ │ ├── pattern: - │ │ │ @ RangeNode (location: (30,4)-(30,8)) - │ │ │ ├── flags: exclude_end - │ │ │ ├── left: - │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 1 - │ │ │ ├── right: ∅ - │ │ │ └── operator_loc: (30,5)-(30,8) = "..." + │ │ │ @ ParenthesesNode (location: (30,3)-(30,9)) + │ │ │ ├── body: + │ │ │ │ @ RangeNode (location: (30,4)-(30,8)) + │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── left: + │ │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 + │ │ │ │ ├── right: ∅ + │ │ │ │ └── operator_loc: (30,5)-(30,8) = "..." + │ │ │ ├── opening_loc: (30,3)-(30,4) = "(" + │ │ │ └── closing_loc: (30,8)-(30,9) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (30,0)-(30,2) = "in" │ │ └── then_loc: ∅ @@ -261,19 +273,23 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (34,0)-(34,9)) + │ │ └── @ InNode (location: (34,0)-(34,10)) │ │ ├── pattern: - │ │ │ @ RangeNode (location: (34,4)-(34,9)) - │ │ │ ├── flags: exclude_end - │ │ │ ├── left: - │ │ │ │ @ IntegerNode (location: (34,4)-(34,5)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 1 - │ │ │ ├── right: - │ │ │ │ @ IntegerNode (location: (34,8)-(34,9)) - │ │ │ │ ├── flags: decimal - │ │ │ │ └── value: 3 - │ │ │ └── operator_loc: (34,5)-(34,8) = "..." + │ │ │ @ ParenthesesNode (location: (34,3)-(34,10)) + │ │ │ ├── body: + │ │ │ │ @ RangeNode (location: (34,4)-(34,9)) + │ │ │ │ ├── flags: exclude_end + │ │ │ │ ├── left: + │ │ │ │ │ @ IntegerNode (location: (34,4)-(34,5)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 + │ │ │ │ ├── right: + │ │ │ │ │ @ IntegerNode (location: (34,8)-(34,9)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 3 + │ │ │ │ └── operator_loc: (34,5)-(34,8) = "..." + │ │ │ ├── opening_loc: (34,3)-(34,4) = "(" + │ │ │ └── closing_loc: (34,9)-(34,10) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (34,0)-(34,2) = "in" │ │ └── then_loc: ∅ @@ -289,11 +305,15 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (38,0)-(38,6)) + │ │ └── @ InNode (location: (38,0)-(38,7)) │ │ ├── pattern: - │ │ │ @ IntegerNode (location: (38,4)-(38,6)) - │ │ │ ├── flags: decimal - │ │ │ └── value: 42 + │ │ │ @ ParenthesesNode (location: (38,3)-(38,7)) + │ │ │ ├── body: + │ │ │ │ @ IntegerNode (location: (38,4)-(38,6)) + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 + │ │ │ ├── opening_loc: (38,3)-(38,4) = "(" + │ │ │ └── closing_loc: (38,6)-(38,7) = ")" │ │ ├── statements: ∅ │ │ ├── in_loc: (38,0)-(38,2) = "in" │ │ └── then_loc: ∅ -- cgit v1.2.3