aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prism/prism.c27
-rw-r--r--test/prism/fixtures/regex.txt3
-rw-r--r--test/prism/snapshots/regex.txt92
3 files changed, 86 insertions, 36 deletions
diff --git a/prism/prism.c b/prism/prism.c
index 234f617803..dc413965c5 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -5117,10 +5117,11 @@ pm_parser_local_add_token(pm_parser_t *parser, pm_token_t *token) {
}
// Add a local variable from an owned string to the current scope.
-static inline void
+static pm_constant_id_t
pm_parser_local_add_owned(pm_parser_t *parser, const uint8_t *start, size_t length) {
pm_constant_id_t constant_id = pm_parser_constant_id_owned(parser, start, length);
if (constant_id != 0) pm_parser_local_add(parser, constant_id);
+ return constant_id;
}
// Add a parameter name to the current scope and check whether the name of the
@@ -15016,15 +15017,31 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_string_list_t named_captures;
pm_string_list_init(&named_captures);
- const pm_location_t *content_loc = &((pm_regular_expression_node_t *) node)->content_loc;
- if (pm_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures, parser->encoding_changed, &parser->encoding) && (named_captures.length > 0)) {
+ const pm_string_t *unescaped = &((pm_regular_expression_node_t *) node)->unescaped;
+ if (pm_regexp_named_capture_group_names(pm_string_source(unescaped), pm_string_length(unescaped), &named_captures, parser->encoding_changed, &parser->encoding) && (named_captures.length > 0)) {
pm_match_write_node_t *match = pm_match_write_node_create(parser, call);
for (size_t index = 0; index < named_captures.length; index++) {
pm_string_t *name = &named_captures.strings[index];
- assert(name->type == PM_STRING_SHARED);
+ pm_constant_id_t local;
+
+ if (unescaped->type == PM_STRING_SHARED) {
+ // If the unescaped string is a slice of the source,
+ // then we can copy the names directly. The pointers
+ // will line up.
+ local = pm_parser_local_add_location(parser, name->source, name->source + name->length);
+ } else {
+ // Otherwise, the name is a slice of the malloc-ed
+ // owned string, in which case we need to copy it
+ // out into a new string.
+ size_t length = pm_string_length(name);
+
+ void *memory = malloc(length);
+ memcpy(memory, pm_string_source(name), length);
+
+ local = pm_parser_local_add_owned(parser, (const uint8_t *) memory, length);
+ }
- pm_constant_id_t local = pm_parser_local_add_location(parser, name->source, name->source + name->length);
pm_constant_id_list_append(&match->locals, local);
}
diff --git a/test/prism/fixtures/regex.txt b/test/prism/fixtures/regex.txt
index 1e917e7de7..1f33b810ac 100644
--- a/test/prism/fixtures/regex.txt
+++ b/test/prism/fixtures/regex.txt
@@ -28,3 +28,6 @@ foo /bar/
%r#pound#
/aaa #{bbb}/o
+
+/(?<a\
+b>)/ =~ ""; ab
diff --git a/test/prism/snapshots/regex.txt b/test/prism/snapshots/regex.txt
index 5fa07265a3..dfc1e47040 100644
--- a/test/prism/snapshots/regex.txt
+++ b/test/prism/snapshots/regex.txt
@@ -1,8 +1,8 @@
-@ ProgramNode (location: (1,0)-(30,13))
-├── locals: [:foo]
+@ ProgramNode (location: (1,0)-(33,14))
+├── locals: [:foo, :ab]
└── statements:
- @ StatementsNode (location: (1,0)-(30,13))
- └── body: (length: 14)
+ @ StatementsNode (location: (1,0)-(33,14))
+ └── body: (length: 16)
├── @ CallNode (location: (1,0)-(1,9))
│ ├── receiver: ∅
│ ├── call_operator_loc: ∅
@@ -180,30 +180,60 @@
│ ├── closing_loc: (28,8)-(28,9) = "#"
│ ├── unescaped: "pound"
│ └── flags: ∅
- └── @ InterpolatedRegularExpressionNode (location: (30,0)-(30,13))
- ├── opening_loc: (30,0)-(30,1) = "/"
- ├── parts: (length: 2)
- │ ├── @ StringNode (location: (30,1)-(30,5))
- │ │ ├── flags: ∅
- │ │ ├── opening_loc: ∅
- │ │ ├── content_loc: (30,1)-(30,5) = "aaa "
- │ │ ├── closing_loc: ∅
- │ │ └── unescaped: "aaa "
- │ └── @ EmbeddedStatementsNode (location: (30,5)-(30,11))
- │ ├── opening_loc: (30,5)-(30,7) = "\#{"
- │ ├── statements:
- │ │ @ StatementsNode (location: (30,7)-(30,10))
- │ │ └── body: (length: 1)
- │ │ └── @ CallNode (location: (30,7)-(30,10))
- │ │ ├── receiver: ∅
- │ │ ├── call_operator_loc: ∅
- │ │ ├── message_loc: (30,7)-(30,10) = "bbb"
- │ │ ├── opening_loc: ∅
- │ │ ├── arguments: ∅
- │ │ ├── closing_loc: ∅
- │ │ ├── block: ∅
- │ │ ├── flags: variable_call
- │ │ └── name: :bbb
- │ └── closing_loc: (30,10)-(30,11) = "}"
- ├── closing_loc: (30,11)-(30,13) = "/o"
- └── flags: once
+ ├── @ InterpolatedRegularExpressionNode (location: (30,0)-(30,13))
+ │ ├── opening_loc: (30,0)-(30,1) = "/"
+ │ ├── parts: (length: 2)
+ │ │ ├── @ StringNode (location: (30,1)-(30,5))
+ │ │ │ ├── flags: ∅
+ │ │ │ ├── opening_loc: ∅
+ │ │ │ ├── content_loc: (30,1)-(30,5) = "aaa "
+ │ │ │ ├── closing_loc: ∅
+ │ │ │ └── unescaped: "aaa "
+ │ │ └── @ EmbeddedStatementsNode (location: (30,5)-(30,11))
+ │ │ ├── opening_loc: (30,5)-(30,7) = "\#{"
+ │ │ ├── statements:
+ │ │ │ @ StatementsNode (location: (30,7)-(30,10))
+ │ │ │ └── body: (length: 1)
+ │ │ │ └── @ CallNode (location: (30,7)-(30,10))
+ │ │ │ ├── receiver: ∅
+ │ │ │ ├── call_operator_loc: ∅
+ │ │ │ ├── message_loc: (30,7)-(30,10) = "bbb"
+ │ │ │ ├── opening_loc: ∅
+ │ │ │ ├── arguments: ∅
+ │ │ │ ├── closing_loc: ∅
+ │ │ │ ├── block: ∅
+ │ │ │ ├── flags: variable_call
+ │ │ │ └── name: :bbb
+ │ │ └── closing_loc: (30,10)-(30,11) = "}"
+ │ ├── closing_loc: (30,11)-(30,13) = "/o"
+ │ └── flags: once
+ ├── @ MatchWriteNode (location: (32,0)-(33,10))
+ │ ├── call:
+ │ │ @ CallNode (location: (32,0)-(33,10))
+ │ │ ├── receiver:
+ │ │ │ @ RegularExpressionNode (location: (32,0)-(33,4))
+ │ │ │ ├── opening_loc: (32,0)-(32,1) = "/"
+ │ │ │ ├── content_loc: (32,1)-(33,3) = "(?<a\\\nb>)"
+ │ │ │ ├── closing_loc: (33,3)-(33,4) = "/"
+ │ │ │ ├── unescaped: "(?<ab>)"
+ │ │ │ └── flags: ∅
+ │ │ ├── call_operator_loc: ∅
+ │ │ ├── message_loc: (33,5)-(33,7) = "=~"
+ │ │ ├── opening_loc: ∅
+ │ │ ├── arguments:
+ │ │ │ @ ArgumentsNode (location: (33,8)-(33,10))
+ │ │ │ └── arguments: (length: 1)
+ │ │ │ └── @ StringNode (location: (33,8)-(33,10))
+ │ │ │ ├── flags: ∅
+ │ │ │ ├── opening_loc: (33,8)-(33,9) = "\""
+ │ │ │ ├── content_loc: (33,9)-(33,9) = ""
+ │ │ │ ├── closing_loc: (33,9)-(33,10) = "\""
+ │ │ │ └── unescaped: ""
+ │ │ ├── closing_loc: ∅
+ │ │ ├── block: ∅
+ │ │ ├── flags: ∅
+ │ │ └── name: :=~
+ │ └── locals: [:ab]
+ └── @ LocalVariableReadNode (location: (33,12)-(33,14))
+ ├── name: :ab
+ └── depth: 0