diff options
-rw-r--r-- | prism/prism.c | 27 | ||||
-rw-r--r-- | test/prism/fixtures/regex.txt | 3 | ||||
-rw-r--r-- | test/prism/snapshots/regex.txt | 92 |
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 |