summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-03-28 15:48:44 -0400
committergit <svn-admin@ruby-lang.org>2024-03-28 20:39:03 +0000
commita8ec347ca2511bec811908e70923f96b4ddcda21 (patch)
tree7b1bd744a407bd696ebb9cbad4248b9a983d84a5
parent8780059c38319aa91452e726ca428ca1610e2d88 (diff)
[ruby/prism] Allow writing to keywords with named captures if they are already locals
https://github.com/ruby/prism/commit/418318e1c8
-rw-r--r--prism/prism.c16
-rw-r--r--test/prism/fixtures/regex.txt2
-rw-r--r--test/prism/snapshots/regex.txt114
3 files changed, 96 insertions, 36 deletions
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);
- // 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) {
+ // 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);
+
// 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 { /(?<a>)/ =~ to_s }
/(?<foo>)/ =~ ""
/(?<Foo>)/ =~ ""
+
/(?<nil>)/ =~ ""
+def foo(nil:) = /(?<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) = "(?<nil>)"
- │ ├── closing_loc: (44,9)-(44,10) = "/"
- │ └── unescaped: "(?<nil>)"
- ├── 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) = "(?<nil>)"
+ │ │ ├── closing_loc: (45,9)-(45,10) = "/"
+ │ │ └── unescaped: "(?<nil>)"
+ │ ├── 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) = "(?<nil>)"
+ │ │ │ ├── closing_loc: (46,25)-(46,26) = "/"
+ │ │ │ └── unescaped: "(?<nil>)"
+ │ │ ├── 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: ∅