diff --git a/prism/prism.c b/prism/prism.c index 1cfcf704bb..db71a9c3f4 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -18107,9 +18107,6 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const uint8_t *sourc cursor += width; } - // Finally, validate that the identifier is not a keywor. - if (pm_local_is_keyword((const char *) source, length)) return false; - return cursor == source + length; } @@ -18170,16 +18167,19 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t * if (pm_constant_id_list_includes(&names, name)) continue; pm_constant_id_list_append(&names, name); + int depth; + if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { + // If the identifier is not already a local, then we'll add + // it to the local table unless it's a keyword. + if (pm_local_is_keyword((const char *) source, length)) continue; + + pm_parser_local_add(parser, name); + } + // Here we lazily create the MatchWriteNode since we know we're // about to add a target. if (match == NULL) match = pm_match_write_node_create(parser, call); - // First, find the depth of the local that is being assigned. - int depth; - if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { - pm_parser_local_add(parser, name); - } - // Next, create the local variable target and add it to the // list of targets for the match. pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create_values(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth); diff --git a/test/prism/fixtures/regex.txt b/test/prism/fixtures/regex.txt index 1010ffedc3..18200e5cbd 100644 --- a/test/prism/fixtures/regex.txt +++ b/test/prism/fixtures/regex.txt @@ -41,4 +41,6 @@ tap { /(?)/ =~ to_s } /(?)/ =~ "" /(?)/ =~ "" + /(?)/ =~ "" +def foo(nil:) = /(?)/ =~ "" diff --git a/test/prism/snapshots/regex.txt b/test/prism/snapshots/regex.txt index 44657260c5..ef576b8bc0 100644 --- a/test/prism/snapshots/regex.txt +++ b/test/prism/snapshots/regex.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(44,16)) +@ ProgramNode (location: (1,0)-(46,32)) ├── locals: [:foo, :ab, :abc, :a] └── statements: - @ StatementsNode (location: (1,0)-(44,16)) - └── body: (length: 24) + @ StatementsNode (location: (1,0)-(46,32)) + └── body: (length: 25) ├── @ CallNode (location: (1,0)-(1,9)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ @@ -425,28 +425,86 @@ │ │ └── unescaped: "" │ ├── closing_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (44,0)-(44,16)) - ├── flags: ∅ - ├── receiver: - │ @ RegularExpressionNode (location: (44,0)-(44,10)) - │ ├── flags: forced_us_ascii_encoding - │ ├── opening_loc: (44,0)-(44,1) = "/" - │ ├── content_loc: (44,1)-(44,9) = "(?)" - │ ├── closing_loc: (44,9)-(44,10) = "/" - │ └── unescaped: "(?)" - ├── call_operator_loc: ∅ - ├── name: :=~ - ├── message_loc: (44,11)-(44,13) = "=~" - ├── opening_loc: ∅ - ├── arguments: - │ @ ArgumentsNode (location: (44,14)-(44,16)) - │ ├── flags: ∅ - │ └── arguments: (length: 1) - │ └── @ StringNode (location: (44,14)-(44,16)) - │ ├── flags: ∅ - │ ├── opening_loc: (44,14)-(44,15) = "\"" - │ ├── content_loc: (44,15)-(44,15) = "" - │ ├── closing_loc: (44,15)-(44,16) = "\"" - │ └── unescaped: "" - ├── closing_loc: ∅ - └── block: ∅ + ├── @ CallNode (location: (45,0)-(45,16)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RegularExpressionNode (location: (45,0)-(45,10)) + │ │ ├── flags: forced_us_ascii_encoding + │ │ ├── opening_loc: (45,0)-(45,1) = "/" + │ │ ├── content_loc: (45,1)-(45,9) = "(?)" + │ │ ├── closing_loc: (45,9)-(45,10) = "/" + │ │ └── unescaped: "(?)" + │ ├── call_operator_loc: ∅ + │ ├── name: :=~ + │ ├── message_loc: (45,11)-(45,13) = "=~" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (45,14)-(45,16)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ StringNode (location: (45,14)-(45,16)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (45,14)-(45,15) = "\"" + │ │ ├── content_loc: (45,15)-(45,15) = "" + │ │ ├── closing_loc: (45,15)-(45,16) = "\"" + │ │ └── unescaped: "" + │ ├── closing_loc: ∅ + │ └── block: ∅ + └── @ DefNode (location: (46,0)-(46,32)) + ├── name: :foo + ├── name_loc: (46,4)-(46,7) = "foo" + ├── receiver: ∅ + ├── parameters: + │ @ ParametersNode (location: (46,8)-(46,12)) + │ ├── requireds: (length: 0) + │ ├── optionals: (length: 0) + │ ├── rest: ∅ + │ ├── posts: (length: 0) + │ ├── keywords: (length: 1) + │ │ └── @ RequiredKeywordParameterNode (location: (46,8)-(46,12)) + │ │ ├── flags: ∅ + │ │ ├── name: :nil + │ │ └── name_loc: (46,8)-(46,12) = "nil:" + │ ├── keyword_rest: ∅ + │ └── block: ∅ + ├── body: + │ @ StatementsNode (location: (46,16)-(46,32)) + │ └── body: (length: 1) + │ └── @ MatchWriteNode (location: (46,16)-(46,32)) + │ ├── call: + │ │ @ CallNode (location: (46,16)-(46,32)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ RegularExpressionNode (location: (46,16)-(46,26)) + │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ ├── opening_loc: (46,16)-(46,17) = "/" + │ │ │ ├── content_loc: (46,17)-(46,25) = "(?)" + │ │ │ ├── closing_loc: (46,25)-(46,26) = "/" + │ │ │ └── unescaped: "(?)" + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :=~ + │ │ ├── message_loc: (46,27)-(46,29) = "=~" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (46,30)-(46,32)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ StringNode (location: (46,30)-(46,32)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (46,30)-(46,31) = "\"" + │ │ │ ├── content_loc: (46,31)-(46,31) = "" + │ │ │ ├── closing_loc: (46,31)-(46,32) = "\"" + │ │ │ └── unescaped: "" + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ └── targets: (length: 1) + │ └── @ LocalVariableTargetNode (location: (46,20)-(46,23)) + │ ├── name: :nil + │ └── depth: 0 + ├── locals: [:nil] + ├── def_keyword_loc: (46,0)-(46,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: (46,7)-(46,8) = "(" + ├── rparen_loc: (46,12)-(46,13) = ")" + ├── equal_loc: (46,14)-(46,15) = "=" + └── end_keyword_loc: ∅