summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--prism/prism.c41
-rw-r--r--test/prism/snapshots/dos_endings.txt2
-rw-r--r--test/prism/snapshots/spanning_heredoc.txt2
-rw-r--r--test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt2
-rw-r--r--test/prism/unescape_test.rb6
5 files changed, 36 insertions, 17 deletions
diff --git a/prism/prism.c b/prism/prism.c
index 36d83db191..77a813138b 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -6387,6 +6387,13 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
pm_buffer_append_u8(buffer, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META));
return;
}
+ case '\r': {
+ if (peek_offset(parser, 1) == '\n') {
+ parser->current.end += 2;
+ pm_buffer_append_u8(buffer, '\n');
+ return;
+ }
+ }
default: {
if (parser->current.end < parser->end) {
pm_buffer_append_u8(buffer, *parser->current.end++);
@@ -7918,10 +7925,11 @@ parser_lex(pm_parser_t *parser) {
parser->current.end++;
break;
case '\r':
- pm_buffer_append_u8(&buffer, '\r');
parser->current.end++;
-
- if (peek(parser) != '\n') break;
+ if (peek(parser) != '\n') {
+ pm_buffer_append_u8(&buffer, '\r');
+ break;
+ }
/* fallthrough */
case '\n':
pm_buffer_append_u8(&buffer, '\n');
@@ -13438,25 +13446,34 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
// the first string content we've seen. In that case we're going
// to create a new string node and set that to the current.
parser_lex(parser);
- current = (pm_node_t *) pm_symbol_node_create_and_unescape(parser, &opening, &parser->previous, &closing, PM_UNESCAPE_ALL);
+
+ pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
+ symbol->unescaped = parser->current_string;
+
+ current = (pm_node_t *) symbol;
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
// If we hit string content and the current node is an
// interpolated string, then we need to append the string content
// to the list of child nodes.
- pm_node_t *part = parse_string_part(parser);
- pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part);
+ parser_lex(parser);
+
+ pm_string_node_t *string = pm_string_node_create(parser, &opening, &parser->previous, &closing);
+ string->unescaped = parser->current_string;
+
+ pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, (pm_node_t *) string);
} else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
// If we hit string content and the current node is a string node,
// then we need to convert the current node into an interpolated
// string and add the string content to the list of child nodes.
- pm_token_t opening = not_provided(parser);
- pm_token_t closing = not_provided(parser);
- pm_interpolated_symbol_node_t *interpolated =
- pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ parser_lex(parser);
+
+ pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
pm_interpolated_symbol_node_append(interpolated, current);
- pm_node_t *part = parse_string_part(parser);
- pm_interpolated_symbol_node_append(interpolated, part);
+ pm_string_node_t *string = pm_string_node_create(parser, &opening, &parser->previous, &closing);
+ string->unescaped = parser->current_string;
+
+ pm_interpolated_symbol_node_append(interpolated, (pm_node_t *) string);
current = (pm_node_t *) interpolated;
} else {
assert(false && "unreachable");
diff --git a/test/prism/snapshots/dos_endings.txt b/test/prism/snapshots/dos_endings.txt
index 73390ffad1..d01c5a7ac9 100644
--- a/test/prism/snapshots/dos_endings.txt
+++ b/test/prism/snapshots/dos_endings.txt
@@ -36,7 +36,7 @@
│ │ ├── opening_loc: ∅
│ │ ├── value_loc: (4,3)-(5,1) = "a\\\r\nb"
│ │ ├── closing_loc: ∅
- │ │ └── unescaped: "ab"
+ │ │ └── unescaped: "a\nb"
│ ├── opening_loc: (4,0)-(4,3) = "%I{"
│ └── closing_loc: (5,1)-(5,2) = "}"
├── @ StringNode (location: (7,0)-(7,4))
diff --git a/test/prism/snapshots/spanning_heredoc.txt b/test/prism/snapshots/spanning_heredoc.txt
index cb99a343ab..884028f054 100644
--- a/test/prism/snapshots/spanning_heredoc.txt
+++ b/test/prism/snapshots/spanning_heredoc.txt
@@ -285,7 +285,7 @@
│ │ │ │ ├── opening_loc: ∅
│ │ │ │ ├── value_loc: (48,12)-(48,14) = "p\\"
│ │ │ │ ├── closing_loc: ∅
- │ │ │ │ └── unescaped: "p\\"
+ │ │ │ │ └── unescaped: "p"
│ │ │ └── @ StringNode (location: (51,0)-(51,1))
│ │ │ ├── flags: ∅
│ │ │ ├── opening_loc: ∅
diff --git a/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt b/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt
index 2de7dd439c..20496c3cfc 100644
--- a/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt
+++ b/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt
@@ -15,7 +15,7 @@
│ │ ├── opening_loc: ∅
│ │ ├── value_loc: (4,3)-(5,1) = "a\\\nb"
│ │ ├── closing_loc: ∅
- │ │ └── unescaped: "ab"
+ │ │ └── unescaped: "a\nb"
│ ├── opening_loc: (4,0)-(4,3) = "%I{"
│ └── closing_loc: (5,1)-(5,2) = "}"
├── @ StringNode (location: (7,0)-(8,2))
diff --git a/test/prism/unescape_test.rb b/test/prism/unescape_test.rb
index 4104b051dd..0053fdd364 100644
--- a/test/prism/unescape_test.rb
+++ b/test/prism/unescape_test.rb
@@ -75,6 +75,7 @@ module Prism
ascii = (0...128).map(&:chr)
ascii8 = (128...256).map(&:chr)
+ newlines = ["\r\n"]
octal = [*("0".."7")]
octal = octal.product(octal).map(&:join).concat(octal.product(octal).product(octal).map(&:join))
@@ -90,7 +91,8 @@ module Prism
ctrls = (ascii.grep(/[[:print:]]/) - ["\\"]).flat_map { |c| ["C-#{c}", "c#{c}", "M-#{c}", "M-\\C-#{c}", "M-\\c#{c}", "c\\M-#{c}"] }
- escapes = [*ascii, *ascii8, *octal, *hex2, *hex4, *hex6, *ctrls]
+ escapes = [*ascii, *ascii8, *newlines, *octal, *hex2, *hex4, *hex6, *ctrls]
+
contexts = [
[Context::String.new("?", ""), escapes],
# [Context::String.new("'", "'"), escapes],
@@ -106,7 +108,7 @@ module Prism
[Context::List.new("%w[", "]"), escapes],
[Context::List.new("%W[", "]"), escapes],
[Context::List.new("%i[", "]"), escapes],
- # [Context::List.new("%I[", "]"), escapes],
+ [Context::List.new("%I[", "]"), escapes],
# [Context::Symbol.new("%s[", "]"), escapes],
# [Context::Symbol.new(":'", "'"), escapes],
# [Context::Symbol.new(":\"", "\""), escapes],