diff options
author | Earlopain <[email protected]> | 2025-01-08 21:17:21 +0100 |
---|---|---|
committer | Kevin Newton <[email protected]> | 2025-03-18 13:36:53 -0400 |
commit | 0fcb7fc21d1923a61ffe4d127e6e72cc55560972 (patch) | |
tree | ca0315aeb0e3fc7344197d7a7ac55520c79136bf | |
parent | acf404e20e3d7bc18cbb8abd2b16c62f9c1f996f (diff) |
[ruby/prism] Better handle all kinds of multiline strings in the parser translator
This is a followup to #3373, where the implementation
was extracted
https://github.com/ruby/prism/commit/2637007929
-rw-r--r-- | lib/prism/translation/parser/compiler.rb | 35 | ||||
-rw-r--r-- | test/prism/fixtures/dstring.txt | 6 | ||||
-rw-r--r-- | test/prism/fixtures/strings.txt | 3 | ||||
-rw-r--r-- | test/prism/fixtures/xstring.txt | 6 | ||||
-rw-r--r-- | test/prism/snapshots/dstring.txt | 36 | ||||
-rw-r--r-- | test/prism/snapshots/strings.txt | 595 | ||||
-rw-r--r-- | test/prism/snapshots/symbols.txt | 510 | ||||
-rw-r--r-- | test/prism/snapshots/xstring.txt | 20 |
8 files changed, 1197 insertions, 14 deletions
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 9fd39ca4a2..91995efc43 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -1118,6 +1118,7 @@ module Prism end <<<<<<< HEAD +<<<<<<< HEAD ======= parts = if node.parts.one? { |part| part.type == :string_node } node.parts.flat_map do |node| @@ -1134,6 +1135,15 @@ module Prism else visit(node) end +======= + parts = node.parts.flat_map do |part| + # When the content of a string node is split across multiple lines, the + # parser gem creates individual string nodes for each line the content is part of. + if part.type == :string_node && part.content.include?("\n") && part.opening_loc.nil? + string_nodes_from_line_continuations(part.unescaped, part.content, part.content_loc.start_offset, node.opening) + else + visit(part) +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) end else visit_all(node.parts) @@ -1724,6 +1734,7 @@ module Prism string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening) else <<<<<<< HEAD +<<<<<<< HEAD [builder.string_internal([node.unescaped, srange(node.content_loc)])] ======= start_offset = node.content_loc.start_offset @@ -1736,6 +1747,9 @@ module Prism builder.string_internal([unescaped_line, offsets]) end >>>>>>> a651126458 (Fix an incompatibility with the parser translator) +======= + [builder.string_internal([node.unescaped, srange(node.content_loc)])] +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) end builder.string_compose( @@ -1780,6 +1794,9 @@ module Prism end else <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) parts = if node.value == "" [] @@ -1787,6 +1804,7 @@ module Prism string_nodes_from_line_continuations(node.unescaped, node.value, node.value_loc.start_offset, node.opening) else [builder.string_internal([node.unescaped, srange(node.value_loc)])] +<<<<<<< HEAD ======= parts = if node.value.lines.one? [builder.string_internal([node.unescaped, srange(node.value_loc)])] @@ -1800,6 +1818,8 @@ module Prism builder.string_internal([line, offsets]) >>>>>>> a651126458 (Fix an incompatibility with the parser translator) +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) end builder.symbol_compose( @@ -1939,6 +1959,7 @@ module Prism string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening) else <<<<<<< HEAD +<<<<<<< HEAD [builder.string_internal([node.unescaped, srange(node.content_loc)])] ======= start_offset = node.content_loc.start_offset @@ -1951,6 +1972,9 @@ module Prism builder.string_internal([line, offsets]) end >>>>>>> a651126458 (Fix an incompatibility with the parser translator) +======= + [builder.string_internal([node.unescaped, srange(node.content_loc)])] +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) end builder.xstring_compose( @@ -2189,13 +2213,17 @@ module Prism def string_nodes_from_line_continuations(unescaped, escaped, start_offset, opening) unescaped = unescaped.lines escaped = escaped.lines +<<<<<<< HEAD percent_array = opening&.start_with?("%w", "%W", "%i", "%I") +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) # Non-interpolating strings if opening&.end_with?("'") || opening&.start_with?("%q", "%s", "%w", "%i") current_length = 0 current_line = +"" +<<<<<<< HEAD escaped.filter_map.with_index do |escaped_line, index| unescaped_line = unescaped.fetch(index, "") current_length += escaped_line.bytesize @@ -2210,6 +2238,13 @@ module Prism current_line = +"" current_length = 0 s +======= + if opening&.end_with?("'") + escaped.each do |line| + escaped_lengths << line.bytesize + normalized_lengths << chomped_bytesize(line) + do_next_tokens << true +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) end else escaped_lengths = [] diff --git a/test/prism/fixtures/dstring.txt b/test/prism/fixtures/dstring.txt index d972b3f71d..bf13d004a1 100644 --- a/test/prism/fixtures/dstring.txt +++ b/test/prism/fixtures/dstring.txt @@ -30,12 +30,18 @@ foo\\\\\ " <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) foo\ b\nar #{} " " +<<<<<<< HEAD ======= >>>>>>> a651126458 (Fix an incompatibility with the parser translator) +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) ’" diff --git a/test/prism/fixtures/strings.txt b/test/prism/fixtures/strings.txt index 0787152786..482f41a7db 100644 --- a/test/prism/fixtures/strings.txt +++ b/test/prism/fixtures/strings.txt @@ -45,10 +45,13 @@ foo\ b\nar " +<<<<<<< HEAD "foo \nbar\n\n a\nb\n\nc\n" +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) %q{abc} %s[abc] diff --git a/test/prism/fixtures/xstring.txt b/test/prism/fixtures/xstring.txt index 1d1bba8e3a..cdac033865 100644 --- a/test/prism/fixtures/xstring.txt +++ b/test/prism/fixtures/xstring.txt @@ -14,11 +14,17 @@ ` <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) foo\ b\nar ` ` +<<<<<<< HEAD ======= >>>>>>> a651126458 (Fix an incompatibility with the parser translator) +======= +>>>>>>> 2637007929 (Better handle all kinds of multiline strings in the parser translator) ’` diff --git a/test/prism/snapshots/dstring.txt b/test/prism/snapshots/dstring.txt index 7c9692fc18..6bcdd8fab3 100644 --- a/test/prism/snapshots/dstring.txt +++ b/test/prism/snapshots/dstring.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(32,4)) +@ ProgramNode (location: (1,0)-(38,4)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(32,4)) + @ StatementsNode (location: (1,0)-(38,4)) ├── flags: ∅ - └── body: (length: 9) + └── body: (length: 10) ├── @ StringNode (location: (1,0)-(2,6)) │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,1) = "\"" @@ -87,9 +87,31 @@ │ ├── content_loc: (27,1)-(29,0) = "\nfoo\\\\\\\\\\\n" │ ├── closing_loc: (29,0)-(29,1) = "\"" │ └── unescaped: "\nfoo\\\\" - └── @ StringNode (location: (31,0)-(32,4)) + ├── @ InterpolatedStringNode (location: (31,0)-(35,1)) + │ ├── flags: newline + │ ├── opening_loc: (31,0)-(31,1) = "\"" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (31,1)-(34,0)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (31,1)-(34,0) = "\nfoo\\\nb\\nar\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\nfoob\nar\n" + │ │ ├── @ EmbeddedStatementsNode (location: (34,0)-(34,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (34,0)-(34,2) = "\#{" + │ │ │ ├── statements: ∅ + │ │ │ └── closing_loc: (34,2)-(34,3) = "}" + │ │ └── @ StringNode (location: (34,3)-(35,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (34,3)-(35,0) = "\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\n" + │ └── closing_loc: (35,0)-(35,1) = "\"" + └── @ StringNode (location: (37,0)-(38,4)) ├── flags: newline - ├── opening_loc: (31,0)-(31,1) = "\"" - ├── content_loc: (31,1)-(32,3) = "\n’" - ├── closing_loc: (32,3)-(32,4) = "\"" + ├── opening_loc: (37,0)-(37,1) = "\"" + ├── content_loc: (37,1)-(38,3) = "\n’" + ├── closing_loc: (38,3)-(38,4) = "\"" └── unescaped: "\n’" diff --git a/test/prism/snapshots/strings.txt b/test/prism/snapshots/strings.txt new file mode 100644 index 0000000000..8f13c79b00 --- /dev/null +++ b/test/prism/snapshots/strings.txt @@ -0,0 +1,595 @@ +@ ProgramNode (location: (1,0)-(112,15)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(112,15)) + ├── flags: ∅ + └── body: (length: 52) + ├── @ StringNode (location: (1,0)-(1,6)) + │ ├── flags: newline + │ ├── opening_loc: (1,0)-(1,2) = "%%" + │ ├── content_loc: (1,2)-(1,5) = "abc" + │ ├── closing_loc: (1,5)-(1,6) = "%" + │ └── unescaped: "abc" + ├── @ StringNode (location: (3,0)-(3,6)) + │ ├── flags: newline + │ ├── opening_loc: (3,0)-(3,2) = "%^" + │ ├── content_loc: (3,2)-(3,5) = "abc" + │ ├── closing_loc: (3,5)-(3,6) = "^" + │ └── unescaped: "abc" + ├── @ StringNode (location: (5,0)-(5,6)) + │ ├── flags: newline + │ ├── opening_loc: (5,0)-(5,2) = "%&" + │ ├── content_loc: (5,2)-(5,5) = "abc" + │ ├── closing_loc: (5,5)-(5,6) = "&" + │ └── unescaped: "abc" + ├── @ StringNode (location: (7,0)-(7,6)) + │ ├── flags: newline + │ ├── opening_loc: (7,0)-(7,2) = "%*" + │ ├── content_loc: (7,2)-(7,5) = "abc" + │ ├── closing_loc: (7,5)-(7,6) = "*" + │ └── unescaped: "abc" + ├── @ StringNode (location: (9,0)-(9,6)) + │ ├── flags: newline + │ ├── opening_loc: (9,0)-(9,2) = "%_" + │ ├── content_loc: (9,2)-(9,5) = "abc" + │ ├── closing_loc: (9,5)-(9,6) = "_" + │ └── unescaped: "abc" + ├── @ StringNode (location: (11,0)-(11,6)) + │ ├── flags: newline + │ ├── opening_loc: (11,0)-(11,2) = "%+" + │ ├── content_loc: (11,2)-(11,5) = "abc" + │ ├── closing_loc: (11,5)-(11,6) = "+" + │ └── unescaped: "abc" + ├── @ StringNode (location: (13,0)-(13,6)) + │ ├── flags: newline + │ ├── opening_loc: (13,0)-(13,2) = "%-" + │ ├── content_loc: (13,2)-(13,5) = "abc" + │ ├── closing_loc: (13,5)-(13,6) = "-" + │ └── unescaped: "abc" + ├── @ StringNode (location: (15,0)-(15,6)) + │ ├── flags: newline + │ ├── opening_loc: (15,0)-(15,2) = "%:" + │ ├── content_loc: (15,2)-(15,5) = "abc" + │ ├── closing_loc: (15,5)-(15,6) = ":" + │ └── unescaped: "abc" + ├── @ StringNode (location: (17,0)-(17,6)) + │ ├── flags: newline + │ ├── opening_loc: (17,0)-(17,2) = "%;" + │ ├── content_loc: (17,2)-(17,5) = "abc" + │ ├── closing_loc: (17,5)-(17,6) = ";" + │ └── unescaped: "abc" + ├── @ StringNode (location: (19,0)-(19,6)) + │ ├── flags: newline + │ ├── opening_loc: (19,0)-(19,2) = "%'" + │ ├── content_loc: (19,2)-(19,5) = "abc" + │ ├── closing_loc: (19,5)-(19,6) = "'" + │ └── unescaped: "abc" + ├── @ StringNode (location: (21,0)-(21,6)) + │ ├── flags: newline + │ ├── opening_loc: (21,0)-(21,2) = "%~" + │ ├── content_loc: (21,2)-(21,5) = "abc" + │ ├── closing_loc: (21,5)-(21,6) = "~" + │ └── unescaped: "abc" + ├── @ StringNode (location: (23,0)-(23,6)) + │ ├── flags: newline + │ ├── opening_loc: (23,0)-(23,2) = "%?" + │ ├── content_loc: (23,2)-(23,5) = "abc" + │ ├── closing_loc: (23,5)-(23,6) = "?" + │ └── unescaped: "abc" + ├── @ ArrayNode (location: (25,0)-(25,8)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 0) + │ ├── opening_loc: (25,0)-(25,3) = "%w{" + │ └── closing_loc: (25,7)-(25,8) = "}" + ├── @ StringNode (location: (27,0)-(27,6)) + │ ├── flags: newline + │ ├── opening_loc: (27,0)-(27,2) = "%/" + │ ├── content_loc: (27,2)-(27,5) = "abc" + │ ├── closing_loc: (27,5)-(27,6) = "/" + │ └── unescaped: "abc" + ├── @ StringNode (location: (29,0)-(29,6)) + │ ├── flags: newline + │ ├── opening_loc: (29,0)-(29,2) = "%`" + │ ├── content_loc: (29,2)-(29,5) = "abc" + │ ├── closing_loc: (29,5)-(29,6) = "`" + │ └── unescaped: "abc" + ├── @ InterpolatedStringNode (location: (31,0)-(31,8)) + │ ├── flags: newline + │ ├── opening_loc: (31,0)-(31,1) = "\"" + │ ├── parts: (length: 1) + │ │ └── @ EmbeddedVariableNode (location: (31,1)-(31,7)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (31,1)-(31,2) = "#" + │ │ └── variable: + │ │ @ ClassVariableReadNode (location: (31,2)-(31,7)) + │ │ ├── flags: ∅ + │ │ └── name: :@@foo + │ └── closing_loc: (31,7)-(31,8) = "\"" + ├── @ StringNode (location: (33,0)-(33,6)) + │ ├── flags: newline + │ ├── opening_loc: (33,0)-(33,2) = "%\\" + │ ├── content_loc: (33,2)-(33,5) = "abc" + │ ├── closing_loc: (33,5)-(33,6) = "\\" + │ └── unescaped: "abc" + ├── @ InterpolatedStringNode (location: (35,0)-(35,17)) + │ ├── flags: newline + │ ├── opening_loc: (35,0)-(35,2) = "%{" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (35,2)-(35,6)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (35,2)-(35,6) = "aaa " + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "aaa " + │ │ ├── @ EmbeddedStatementsNode (location: (35,6)-(35,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (35,6)-(35,8) = "\#{" + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (35,8)-(35,11)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ CallNode (location: (35,8)-(35,11)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :bbb + │ │ │ │ ├── message_loc: (35,8)-(35,11) = "bbb" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ └── closing_loc: (35,11)-(35,12) = "}" + │ │ └── @ StringNode (location: (35,12)-(35,16)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (35,12)-(35,16) = " ccc" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " ccc" + │ └── closing_loc: (35,16)-(35,17) = "}" + ├── @ StringNode (location: (37,0)-(37,8)) + │ ├── flags: newline + │ ├── opening_loc: (37,0)-(37,2) = "%[" + │ ├── content_loc: (37,2)-(37,7) = "foo[]" + │ ├── closing_loc: (37,7)-(37,8) = "]" + │ └── unescaped: "foo[]" + ├── @ CallNode (location: (39,0)-(41,5)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ StringNode (location: (39,0)-(39,5)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (39,0)-(39,1) = "\"" + │ │ ├── content_loc: (39,1)-(39,4) = "foo" + │ │ ├── closing_loc: (39,4)-(39,5) = "\"" + │ │ └── unescaped: "foo" + │ ├── call_operator_loc: ∅ + │ ├── name: :+ + │ ├── message_loc: (39,6)-(39,7) = "+" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (41,0)-(41,5)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ StringNode (location: (41,0)-(41,5)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (41,0)-(41,1) = "\"" + │ │ ├── content_loc: (41,1)-(41,4) = "bar" + │ │ ├── closing_loc: (41,4)-(41,5) = "\"" + │ │ └── unescaped: "bar" + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ StringNode (location: (43,0)-(46,1)) + │ ├── flags: newline + │ ├── opening_loc: (43,0)-(43,1) = "\"" + │ ├── content_loc: (43,1)-(46,0) = "\nfoo\\\nb\\nar\n" + │ ├── closing_loc: (46,0)-(46,1) = "\"" + │ └── unescaped: "\nfoob\nar\n" + ├── @ StringNode (location: (48,0)-(48,7)) + │ ├── flags: newline + │ ├── opening_loc: (48,0)-(48,3) = "%q{" + │ ├── content_loc: (48,3)-(48,6) = "abc" + │ ├── closing_loc: (48,6)-(48,7) = "}" + │ └── unescaped: "abc" + ├── @ SymbolNode (location: (50,0)-(50,7)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (50,0)-(50,3) = "%s[" + │ ├── value_loc: (50,3)-(50,6) = "abc" + │ ├── closing_loc: (50,6)-(50,7) = "]" + │ └── unescaped: "abc" + ├── @ StringNode (location: (52,0)-(52,6)) + │ ├── flags: newline + │ ├── opening_loc: (52,0)-(52,2) = "%{" + │ ├── content_loc: (52,2)-(52,5) = "abc" + │ ├── closing_loc: (52,5)-(52,6) = "}" + │ └── unescaped: "abc" + ├── @ StringNode (location: (54,0)-(54,2)) + │ ├── flags: newline + │ ├── opening_loc: (54,0)-(54,1) = "'" + │ ├── content_loc: (54,1)-(54,1) = "" + │ ├── closing_loc: (54,1)-(54,2) = "'" + │ └── unescaped: "" + ├── @ StringNode (location: (56,0)-(56,5)) + │ ├── flags: newline + │ ├── opening_loc: (56,0)-(56,1) = "\"" + │ ├── content_loc: (56,1)-(56,4) = "abc" + │ ├── closing_loc: (56,4)-(56,5) = "\"" + │ └── unescaped: "abc" + ├── @ StringNode (location: (58,0)-(58,7)) + │ ├── flags: newline + │ ├── opening_loc: (58,0)-(58,1) = "\"" + │ ├── content_loc: (58,1)-(58,6) = "\#@---" + │ ├── closing_loc: (58,6)-(58,7) = "\"" + │ └── unescaped: "\#@---" + ├── @ InterpolatedStringNode (location: (60,0)-(60,16)) + │ ├── flags: newline + │ ├── opening_loc: (60,0)-(60,1) = "\"" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (60,1)-(60,5)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (60,1)-(60,5) = "aaa " + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "aaa " + │ │ ├── @ EmbeddedStatementsNode (location: (60,5)-(60,11)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (60,5)-(60,7) = "\#{" + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (60,7)-(60,10)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ CallNode (location: (60,7)-(60,10)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :bbb + │ │ │ │ ├── message_loc: (60,7)-(60,10) = "bbb" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ └── closing_loc: (60,10)-(60,11) = "}" + │ │ └── @ StringNode (location: (60,11)-(60,15)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (60,11)-(60,15) = " ccc" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: " ccc" + │ └── closing_loc: (60,15)-(60,16) = "\"" + ├── @ StringNode (location: (62,0)-(62,5)) + │ ├── flags: newline + │ ├── opening_loc: (62,0)-(62,1) = "'" + │ ├── content_loc: (62,1)-(62,4) = "abc" + │ ├── closing_loc: (62,4)-(62,5) = "'" + │ └── unescaped: "abc" + ├── @ ArrayNode (location: (64,0)-(64,9)) + │ ├── flags: newline + │ ├── elements: (length: 3) + │ │ ├── @ StringNode (location: (64,3)-(64,4)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (64,3)-(64,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ StringNode (location: (64,5)-(64,6)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (64,5)-(64,6) = "b" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b" + │ │ └── @ StringNode (location: (64,7)-(64,8)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (64,7)-(64,8) = "c" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "c" + │ ├── opening_loc: (64,0)-(64,3) = "%w[" + │ └── closing_loc: (64,8)-(64,9) = "]" + ├── @ ArrayNode (location: (66,0)-(66,17)) + │ ├── flags: newline + │ ├── elements: (length: 3) + │ │ ├── @ StringNode (location: (66,3)-(66,6)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (66,3)-(66,6) = "a[]" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a[]" + │ │ ├── @ StringNode (location: (66,7)-(66,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (66,7)-(66,12) = "b[[]]" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b[[]]" + │ │ └── @ StringNode (location: (66,13)-(66,16)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (66,13)-(66,16) = "c[]" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "c[]" + │ ├── opening_loc: (66,0)-(66,3) = "%w[" + │ └── closing_loc: (66,16)-(66,17) = "]" + ├── @ ArrayNode (location: (68,0)-(68,18)) + │ ├── flags: newline + │ ├── elements: (length: 2) + │ │ ├── @ StringNode (location: (68,3)-(68,11)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (68,3)-(68,11) = "foo\\ bar" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo bar" + │ │ └── @ StringNode (location: (68,12)-(68,17)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (68,12)-(68,17) = "\\\#{1}" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\\\#{1}" + │ ├── opening_loc: (68,0)-(68,3) = "%w[" + │ └── closing_loc: (68,17)-(68,18) = "]" + ├── @ ArrayNode (location: (70,0)-(70,16)) + │ ├── flags: newline + │ ├── elements: (length: 2) + │ │ ├── @ StringNode (location: (70,3)-(70,11)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (70,3)-(70,11) = "foo\\ bar" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "foo bar" + │ │ └── @ StringNode (location: (70,12)-(70,15)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (70,12)-(70,15) = "baz" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "baz" + │ ├── opening_loc: (70,0)-(70,3) = "%w[" + │ └── closing_loc: (70,15)-(70,16) = "]" + ├── @ ArrayNode (location: (72,0)-(72,14)) + │ ├── flags: newline + │ ├── elements: (length: 3) + │ │ ├── @ StringNode (location: (72,3)-(72,4)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (72,3)-(72,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ InterpolatedStringNode (location: (72,5)-(72,11)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── parts: (length: 3) + │ │ │ │ ├── @ StringNode (location: (72,5)-(72,6)) + │ │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── content_loc: (72,5)-(72,6) = "b" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "b" + │ │ │ │ ├── @ EmbeddedStatementsNode (location: (72,6)-(72,10)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: (72,6)-(72,8) = "\#{" + │ │ │ │ │ ├── statements: + │ │ │ │ │ │ @ StatementsNode (location: (72,8)-(72,9)) + │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ │ └── @ CallNode (location: (72,8)-(72,9)) + │ │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ │ ├── name: :c + │ │ │ │ │ │ ├── message_loc: (72,8)-(72,9) = "c" + │ │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ │ └── block: ∅ + │ │ │ │ │ └── closing_loc: (72,9)-(72,10) = "}" + │ │ │ │ └── @ StringNode (location: (72,10)-(72,11)) + │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (72,10)-(72,11) = "d" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "d" + │ │ │ └── closing_loc: ∅ + │ │ └── @ StringNode (location: (72,12)-(72,13)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (72,12)-(72,13) = "e" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "e" + │ ├── opening_loc: (72,0)-(72,3) = "%W[" + │ └── closing_loc: (72,13)-(72,14) = "]" + ├── @ ArrayNode (location: (74,0)-(74,9)) + │ ├── flags: newline + │ ├── elements: (length: 3) + │ │ ├── @ StringNode (location: (74,3)-(74,4)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (74,3)-(74,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ StringNode (location: (74,5)-(74,6)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (74,5)-(74,6) = "b" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b" + │ │ └── @ StringNode (location: (74,7)-(74,8)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (74,7)-(74,8) = "c" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "c" + │ ├── opening_loc: (74,0)-(74,3) = "%W[" + │ └── closing_loc: (74,8)-(74,9) = "]" + ├── @ ArrayNode (location: (76,0)-(80,1)) + │ ├── flags: newline + │ ├── elements: (length: 3) + │ │ ├── @ StringNode (location: (77,2)-(77,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (77,2)-(77,3) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ StringNode (location: (78,2)-(78,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (78,2)-(78,3) = "b" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b" + │ │ └── @ StringNode (location: (79,2)-(79,3)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (79,2)-(79,3) = "c" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "c" + │ ├── opening_loc: (76,0)-(76,3) = "%w[" + │ └── closing_loc: (80,0)-(80,1) = "]" + ├── @ StringNode (location: (82,0)-(82,15)) + │ ├── flags: newline + │ ├── opening_loc: (82,0)-(82,1) = "'" + │ ├── content_loc: (82,1)-(82,14) = "\\' foo \\' bar" + │ ├── closing_loc: (82,14)-(82,15) = "'" + │ └── unescaped: "' foo ' bar" + ├── @ StringNode (location: (84,0)-(84,15)) + │ ├── flags: newline + │ ├── opening_loc: (84,0)-(84,1) = "'" + │ ├── content_loc: (84,1)-(84,14) = "\\\\ foo \\\\ bar" + │ ├── closing_loc: (84,14)-(84,15) = "'" + │ └── unescaped: "\\ foo \\ bar" + ├── @ InterpolatedStringNode (location: (86,0)-(86,7)) + │ ├── flags: newline + │ ├── opening_loc: (86,0)-(86,1) = "\"" + │ ├── parts: (length: 1) + │ │ └── @ EmbeddedVariableNode (location: (86,1)-(86,6)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (86,1)-(86,2) = "#" + │ │ └── variable: + │ │ @ GlobalVariableReadNode (location: (86,2)-(86,6)) + │ │ ├── flags: ∅ + │ │ └── name: :$foo + │ └── closing_loc: (86,6)-(86,7) = "\"" + ├── @ InterpolatedStringNode (location: (88,0)-(88,7)) + │ ├── flags: newline + │ ├── opening_loc: (88,0)-(88,1) = "\"" + │ ├── parts: (length: 1) + │ │ └── @ EmbeddedVariableNode (location: (88,1)-(88,6)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (88,1)-(88,2) = "#" + │ │ └── variable: + │ │ @ InstanceVariableReadNode (location: (88,2)-(88,6)) + │ │ ├── flags: ∅ + │ │ └── name: :@foo + │ └── closing_loc: (88,6)-(88,7) = "\"" + ├── @ StringNode (location: (90,0)-(90,15)) + │ ├── flags: newline + │ ├── opening_loc: (90,0)-(90,1) = "\"" + │ ├── content_loc: (90,1)-(90,14) = "\\x7 \\x23 \\x61" + │ ├── closing_loc: (90,14)-(90,15) = "\"" + │ └── unescaped: "\a # a" + ├── @ StringNode (location: (92,0)-(92,13)) + │ ├── flags: newline + │ ├── opening_loc: (92,0)-(92,1) = "\"" + │ ├── content_loc: (92,1)-(92,12) = "\\7 \\43 \\141" + │ ├── closing_loc: (92,12)-(92,13) = "\"" + │ └── unescaped: "\a # a" + ├── @ StringNode (location: (94,0)-(94,6)) + │ ├── flags: newline + │ ├── opening_loc: (94,0)-(94,2) = "%[" + │ ├── content_loc: (94,2)-(94,5) = "abc" + │ ├── closing_loc: (94,5)-(94,6) = "]" + │ └── unescaped: "abc" + ├── @ StringNode (location: (96,0)-(96,6)) + │ ├── flags: newline + │ ├── opening_loc: (96,0)-(96,2) = "%(" + │ ├── content_loc: (96,2)-(96,5) = "abc" + │ ├── closing_loc: (96,5)-(96,6) = ")" + │ └── unescaped: "abc" + ├── @ StringNode (location: (98,0)-(98,6)) + │ ├── flags: newline + │ ├── opening_loc: (98,0)-(98,2) = "%@" + │ ├── content_loc: (98,2)-(98,5) = "abc" + │ ├── closing_loc: (98,5)-(98,6) = "@" + │ └── unescaped: "abc" + ├── @ StringNode (location: (100,0)-(100,6)) + │ ├── flags: newline + │ ├── opening_loc: (100,0)-(100,2) = "%$" + │ ├── content_loc: (100,2)-(100,5) = "abc" + │ ├── closing_loc: (100,5)-(100,6) = "$" + │ └── unescaped: "abc" + ├── @ StringNode (location: (102,0)-(102,2)) + │ ├── flags: newline + │ ├── opening_loc: (102,0)-(102,1) = "?" + │ ├── content_loc: (102,1)-(102,2) = "a" + │ ├── closing_loc: ∅ + │ └── unescaped: "a" + ├── @ InterpolatedStringNode (location: (104,0)-(104,6)) + │ ├── flags: newline, static_literal + │ ├── opening_loc: ∅ + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (104,0)-(104,2)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: (104,0)-(104,1) = "?" + │ │ │ ├── content_loc: (104,1)-(104,2) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ └── @ StringNode (location: (104,3)-(104,6)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: (104,3)-(104,4) = "\"" + │ │ ├── content_loc: (104,4)-(104,5) = "a" + │ │ ├── closing_loc: (104,5)-(104,6) = "\"" + │ │ └── unescaped: "a" + │ └── closing_loc: ∅ + ├── @ StringNode (location: (106,0)-(106,7)) + │ ├── flags: newline + │ ├── opening_loc: (106,0)-(106,3) = "%Q{" + │ ├── content_loc: (106,3)-(106,6) = "abc" + │ ├── closing_loc: (106,6)-(106,7) = "}" + │ └── unescaped: "abc" + ├── @ StringNode (location: (108,0)-(108,5)) + │ ├── flags: newline + │ ├── opening_loc: (108,0)-(108,2) = "%^" + │ ├── content_loc: (108,2)-(108,4) = "\#$" + │ ├── closing_loc: (108,4)-(108,5) = "^" + │ └── unescaped: "\#$" + ├── @ StringNode (location: (110,0)-(110,4)) + │ ├── flags: newline + │ ├── opening_loc: (110,0)-(110,2) = "%@" + │ ├── content_loc: (110,2)-(110,3) = "#" + │ ├── closing_loc: (110,3)-(110,4) = "@" + │ └── unescaped: "#" + └── @ InterpolatedStringNode (location: (112,0)-(112,15)) + ├── flags: newline + ├── opening_loc: (112,0)-(112,1) = "\"" + ├── parts: (length: 2) + │ ├── @ EmbeddedStatementsNode (location: (112,1)-(112,12)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (112,1)-(112,3) = "\#{" + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (112,3)-(112,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ InterpolatedStringNode (location: (112,3)-(112,11)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (112,3)-(112,4) = "\"" + │ │ │ ├── parts: (length: 2) + │ │ │ │ ├── @ EmbeddedStatementsNode (location: (112,4)-(112,8)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: (112,4)-(112,6) = "\#{" + │ │ │ │ │ ├── statements: + │ │ │ │ │ │ @ StatementsNode (location: (112,6)-(112,7)) + │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ │ └── @ ConstantReadNode (location: (112,6)-(112,7)) + │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ └── name: :B + │ │ │ │ │ └── closing_loc: (112,7)-(112,8) = "}" + │ │ │ │ └── @ StringNode (location: (112,8)-(112,10)) + │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (112,8)-(112,10) = " C" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: " C" + │ │ │ └── closing_loc: (112,10)-(112,11) = "\"" + │ │ └── closing_loc: (112,11)-(112,12) = "}" + │ └── @ StringNode (location: (112,12)-(112,14)) + │ ├── flags: static_literal, frozen + │ ├── opening_loc: ∅ + │ ├── content_loc: (112,12)-(112,14) = " D" + │ ├── closing_loc: ∅ + │ └── unescaped: " D" + └── closing_loc: (112,14)-(112,15) = "\"" diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt new file mode 100644 index 0000000000..d273876437 --- /dev/null +++ b/test/prism/snapshots/symbols.txt @@ -0,0 +1,510 @@ +@ ProgramNode (location: (1,0)-(104,13)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(104,13)) + ├── flags: ∅ + └── body: (length: 49) + ├── @ SymbolNode (location: (1,0)-(1,6)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (1,0)-(1,2) = ":'" + │ ├── value_loc: (1,2)-(1,5) = "abc" + │ ├── closing_loc: (1,5)-(1,6) = "'" + │ └── unescaped: "abc" + ├── @ InterpolatedSymbolNode (location: (3,0)-(3,9)) + │ ├── flags: newline + │ ├── opening_loc: (3,0)-(3,2) = ":\"" + │ ├── parts: (length: 1) + │ │ └── @ EmbeddedStatementsNode (location: (3,2)-(3,8)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (3,2)-(3,4) = "\#{" + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (3,4)-(3,7)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (3,4)-(3,7)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :var + │ │ │ ├── message_loc: (3,4)-(3,7) = "var" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ └── block: ∅ + │ │ └── closing_loc: (3,7)-(3,8) = "}" + │ └── closing_loc: (3,8)-(3,9) = "\"" + ├── @ InterpolatedSymbolNode (location: (5,0)-(5,10)) + │ ├── flags: newline + │ ├── opening_loc: (5,0)-(5,2) = ":\"" + │ ├── parts: (length: 2) + │ │ ├── @ StringNode (location: (5,2)-(5,5)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (5,2)-(5,5) = "abc" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "abc" + │ │ └── @ EmbeddedStatementsNode (location: (5,5)-(5,9)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (5,5)-(5,7) = "\#{" + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (5,7)-(5,8)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ IntegerNode (location: (5,7)-(5,8)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 1 + │ │ └── closing_loc: (5,8)-(5,9) = "}" + │ └── closing_loc: (5,9)-(5,10) = "\"" + ├── @ StringNode (location: (7,0)-(10,1)) + │ ├── flags: newline + │ ├── opening_loc: (7,0)-(7,1) = "\"" + │ ├── content_loc: (7,1)-(10,0) = "\nfoo\\\nb\\nar\n" + │ ├── closing_loc: (10,0)-(10,1) = "\"" + │ └── unescaped: "\nfoob\nar\n" + ├── @ InterpolatedStringNode (location: (12,0)-(16,1)) + │ ├── flags: newline + │ ├── opening_loc: (12,0)-(12,1) = "\"" + │ ├── parts: (length: 3) + │ │ ├── @ StringNode (location: (12,1)-(15,0)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (12,1)-(15,0) = "\nfoo\\\nb\\nar\n" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\nfoob\nar\n" + │ │ ├── @ EmbeddedStatementsNode (location: (15,0)-(15,3)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (15,0)-(15,2) = "\#{" + │ │ │ ├── statements: ∅ + │ │ │ └── closing_loc: (15,2)-(15,3) = "}" + │ │ └── @ StringNode (location: (15,3)-(16,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (15,3)-(16,0) = "\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "\n" + │ └── closing_loc: (16,0)-(16,1) = "\"" + ├── @ ArrayNode (location: (18,0)-(18,20)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 4) + │ │ ├── @ SymbolNode (location: (18,1)-(18,4)) + │ │ │ ├── flags: static_literal + │ │ │ ├── opening_loc: (18,1)-(18,2) = ":" + │ │ │ ├── value_loc: (18,2)-(18,4) = "Υ" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "Υ" + │ │ ├── @ SymbolNode (location: (18,6)-(18,9)) + │ │ │ ├── flags: static_literal + │ │ │ ├── opening_loc: (18,6)-(18,7) = ":" + │ │ │ ├── value_loc: (18,7)-(18,9) = "ά" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "ά" + │ │ ├── @ SymbolNode (location: (18,11)-(18,14)) + │ │ │ ├── flags: static_literal + │ │ │ ├── opening_loc: (18,11)-(18,12) = ":" + │ │ │ ├── value_loc: (18,12)-(18,14) = "ŗ" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "ŗ" + │ │ └── @ SymbolNode (location: (18,16)-(18,19)) + │ │ ├── flags: static_literal + │ │ ├── opening_loc: (18,16)-(18,17) = ":" + │ │ ├── value_loc: (18,17)-(18,19) = "ρ" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "ρ" + │ ├── opening_loc: (18,0)-(18,1) = "[" + │ └── closing_loc: (18,19)-(18,20) = "]" + ├── @ SymbolNode (location: (20,0)-(20,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (20,0)-(20,1) = ":" + │ ├── value_loc: (20,1)-(20,3) = "-@" + │ ├── closing_loc: ∅ + │ └── unescaped: "-@" + ├── @ SymbolNode (location: (22,0)-(22,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (22,0)-(22,1) = ":" + │ ├── value_loc: (22,1)-(22,2) = "-" + │ ├── closing_loc: ∅ + │ └── unescaped: "-" + ├── @ SymbolNode (location: (24,0)-(24,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (24,0)-(24,1) = ":" + │ ├── value_loc: (24,1)-(24,2) = "%" + │ ├── closing_loc: ∅ + │ └── unescaped: "%" + ├── @ SymbolNode (location: (26,0)-(26,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (26,0)-(26,1) = ":" + │ ├── value_loc: (26,1)-(26,2) = "|" + │ ├── closing_loc: ∅ + │ └── unescaped: "|" + ├── @ SymbolNode (location: (28,0)-(28,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (28,0)-(28,1) = ":" + │ ├── value_loc: (28,1)-(28,3) = "+@" + │ ├── closing_loc: ∅ + │ └── unescaped: "+@" + ├── @ SymbolNode (location: (30,0)-(30,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (30,0)-(30,1) = ":" + │ ├── value_loc: (30,1)-(30,2) = "+" + │ ├── closing_loc: ∅ + │ └── unescaped: "+" + ├── @ SymbolNode (location: (32,0)-(32,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (32,0)-(32,1) = ":" + │ ├── value_loc: (32,1)-(32,2) = "/" + │ ├── closing_loc: ∅ + │ └── unescaped: "/" + ├── @ SymbolNode (location: (34,0)-(34,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (34,0)-(34,1) = ":" + │ ├── value_loc: (34,1)-(34,3) = "**" + │ ├── closing_loc: ∅ + │ └── unescaped: "**" + ├── @ SymbolNode (location: (36,0)-(36,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (36,0)-(36,1) = ":" + │ ├── value_loc: (36,1)-(36,2) = "*" + │ ├── closing_loc: ∅ + │ └── unescaped: "*" + ├── @ SymbolNode (location: (38,0)-(38,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (38,0)-(38,1) = ":" + │ ├── value_loc: (38,1)-(38,3) = "~@" + │ ├── closing_loc: ∅ + │ └── unescaped: "~" + ├── @ ArrayNode (location: (40,0)-(40,16)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 4) + │ │ ├── @ IntegerNode (location: (40,1)-(40,2)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 1 + │ │ ├── @ FloatNode (location: (40,4)-(40,7)) + │ │ │ ├── flags: static_literal + │ │ │ └── value: 1.0 + │ │ ├── @ RationalNode (location: (40,9)-(40,11)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ ├── numerator: 1 + │ │ │ └── denominator: 1 + │ │ └── @ ImaginaryNode (location: (40,13)-(40,15)) + │ │ ├── flags: static_literal + │ │ └── numeric: + │ │ @ IntegerNode (location: (40,13)-(40,14)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 1 + │ ├── opening_loc: (40,0)-(40,1) = "[" + │ └── closing_loc: (40,15)-(40,16) = "]" + ├── @ SymbolNode (location: (42,0)-(42,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (42,0)-(42,1) = ":" + │ ├── value_loc: (42,1)-(42,2) = "~" + │ ├── closing_loc: ∅ + │ └── unescaped: "~" + ├── @ SymbolNode (location: (44,0)-(44,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (44,0)-(44,1) = ":" + │ ├── value_loc: (44,1)-(44,2) = "a" + │ ├── closing_loc: ∅ + │ └── unescaped: "a" + ├── @ ArrayNode (location: (46,0)-(46,9)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 3) + │ │ ├── @ SymbolNode (location: (46,3)-(46,4)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (46,3)-(46,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ SymbolNode (location: (46,5)-(46,6)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (46,5)-(46,6) = "b" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b" + │ │ └── @ SymbolNode (location: (46,7)-(46,8)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: ∅ + │ │ ├── value_loc: (46,7)-(46,8) = "c" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "c" + │ ├── opening_loc: (46,0)-(46,3) = "%i[" + │ └── closing_loc: (46,8)-(46,9) = "]" + ├── @ ArrayNode (location: (48,0)-(48,24)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 4) + │ │ ├── @ SymbolNode (location: (48,3)-(48,4)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (48,3)-(48,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ SymbolNode (location: (48,5)-(48,10)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (48,5)-(48,10) = "b\#{1}" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "b\#{1}" + │ │ ├── @ SymbolNode (location: (48,11)-(48,16)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (48,11)-(48,16) = "\#{2}c" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "\#{2}c" + │ │ └── @ SymbolNode (location: (48,17)-(48,23)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: ∅ + │ │ ├── value_loc: (48,17)-(48,23) = "d\#{3}f" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "d\#{3}f" + │ ├── opening_loc: (48,0)-(48,3) = "%i[" + │ └── closing_loc: (48,23)-(48,24) = "]" + ├── @ ArrayNode (location: (50,0)-(50,24)) + │ ├── flags: newline + │ ├── elements: (length: 4) + │ │ ├── @ SymbolNode (location: (50,3)-(50,4)) + │ │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── value_loc: (50,3)-(50,4) = "a" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "a" + │ │ ├── @ InterpolatedSymbolNode (location: (50,5)-(50,10)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── parts: (length: 2) + │ │ │ │ ├── @ StringNode (location: (50,5)-(50,6)) + │ │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── content_loc: (50,5)-(50,6) = "b" + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── unescaped: "b" + │ │ │ │ └── @ EmbeddedStatementsNode (location: (50,6)-(50,10)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (50,6)-(50,8) = "\#{" + │ │ │ │ ├── statements: + │ │ │ │ │ @ StatementsNode (location: (50,8)-(50,9)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ └── @ IntegerNode (location: (50,8)-(50,9)) + │ │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ │ └── value: 1 + │ │ │ │ └── closing_loc: (50,9)-(50,10) = "}" + │ │ │ └── closing_loc: ∅ + │ │ ├── @ InterpolatedSymbolNode (location: (50,11)-(50,16)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── parts: (length: 2) + │ │ │ │ ├── @ EmbeddedStatementsNode (location: (50,11)-(50,15)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: (50,11)-(50,13) = "\#{" + │ │ │ │ │ ├── statements: + │ │ │ │ │ │ @ StatementsNode (location: (50,13)-(50,14)) + │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ │ └── @ IntegerNode (location: (50,13)-(50,14)) + │ │ │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ │ │ └── value: 2 + │ │ │ │ │ └── closing_loc: (50,14)-(50,15) = "}" + │ │ │ │ └── @ StringNode (location: (50,15)-(50,16)) + │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (50,15)-(50,16) = "c" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "c" + │ │ │ └── closing_loc: ∅ + │ │ └── @ InterpolatedSymbolNode (location: (50,17)-(50,23)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── parts: (length: 3) + │ │ │ ├── @ StringNode (location: (50,17)-(50,18)) + │ │ │ │ ├── flags: static_literal, frozen + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (50,17)-(50,18) = "d" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "d" + │ │ │ ├── @ EmbeddedStatementsNode (location: (50,18)-(50,22)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (50,18)-(50,20) = "\#{" + │ │ │ │ ├── statements: + │ │ │ │ │ @ StatementsNode (location: (50,20)-(50,21)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── body: (length: 1) + │ │ │ │ │ └── @ IntegerNode (location: (50,20)-(50,21)) + │ │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ │ └── value: 3 + │ │ │ │ └── closing_loc: (50,21)-(50,22) = "}" + │ │ │ └── @ StringNode (location: (50,22)-(50,23)) + │ │ │ ├── flags: static_literal, frozen + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── content_loc: (50,22)-(50,23) = "f" + │ │ │ ├── closing_loc: ∅ + │ │ │ └── unescaped: "f" + │ │ └── closing_loc: ∅ + │ ├── opening_loc: (50,0)-(50,3) = "%I[" + │ └── closing_loc: (50,23)-(50,24) = "]" + ├── @ SymbolNode (location: (52,0)-(52,4)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (52,0)-(52,1) = ":" + │ ├── value_loc: (52,1)-(52,4) = "@@a" + │ ├── closing_loc: ∅ + │ └── unescaped: "@@a" + ├── @ SymbolNode (location: (54,0)-(54,5)) + │ ├── flags: newline, static_literal + │ ├── opening_loc: (54,0)-(54,1) = ":" + │ ├── value_loc: (54,1)-(54,5) = "👍" + │ ├── closing_loc: ∅ + │ └── unescaped: "👍" + ├── @ ArrayNode (location: (56,0)-(56,7)) + │ ├── flags: newline, static_literal + │ ├── elements: (length: 1) + │ │ └── @ SymbolNode (location: (56,3)-(56,6)) + │ │ ├── flags: static_literal, forced_us_ascii_encoding + │ │ ├── opening_loc: ∅ + │ │ ├── value_loc: (56,3)-(56,6) = "a\\b" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "a\\b" + │ ├── opening_loc: (56,0)-(56,3) = "%i[" + │ └── closing_loc: (56,6)-(56,7) = "]" + ├── @ SymbolNode (location: (58,0)-(58,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (58,0)-(58,1) = ":" + │ ├── value_loc: (58,1)-(58,3) = "$a" + │ ├── closing_loc: ∅ + │ └── unescaped: "$a" + ├── @ SymbolNode (location: (60,0)-(60,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (60,0)-(60,1) = ":" + │ ├── value_loc: (60,1)-(60,3) = "@a" + │ ├── closing_loc: ∅ + │ └── unescaped: "@a" + ├── @ SymbolNode (location: (62,0)-(62,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (62,0)-(62,1) = ":" + │ ├── value_loc: (62,1)-(62,3) = "do" + │ ├── closing_loc: ∅ + │ └── unescaped: "do" + ├── @ SymbolNode (location: (64,0)-(64,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (64,0)-(64,1) = ":" + │ ├── value_loc: (64,1)-(64,2) = "&" + │ ├── closing_loc: ∅ + │ └── unescaped: "&" + ├── @ SymbolNode (location: (66,0)-(66,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (66,0)-(66,1) = ":" + │ ├── value_loc: (66,1)-(66,2) = "`" + │ ├── closing_loc: ∅ + │ └── unescaped: "`" + ├── @ SymbolNode (location: (68,0)-(68,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (68,0)-(68,1) = ":" + │ ├── value_loc: (68,1)-(68,3) = "!@" + │ ├── closing_loc: ∅ + │ └── unescaped: "!" + ├── @ SymbolNode (location: (70,0)-(70,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (70,0)-(70,1) = ":" + │ ├── value_loc: (70,1)-(70,3) = "!~" + │ ├── closing_loc: ∅ + │ └── unescaped: "!~" + ├── @ SymbolNode (location: (72,0)-(72,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (72,0)-(72,1) = ":" + │ ├── value_loc: (72,1)-(72,2) = "!" + │ ├── closing_loc: ∅ + │ └── unescaped: "!" + ├── @ SymbolNode (location: (74,0)-(74,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (74,0)-(74,1) = ":" + │ ├── value_loc: (74,1)-(74,3) = "[]" + │ ├── closing_loc: ∅ + │ └── unescaped: "[]" + ├── @ SymbolNode (location: (76,0)-(76,4)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (76,0)-(76,1) = ":" + │ ├── value_loc: (76,1)-(76,4) = "[]=" + │ ├── closing_loc: ∅ + │ └── unescaped: "[]=" + ├── @ SymbolNode (location: (78,0)-(78,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (78,0)-(78,1) = ":" + │ ├── value_loc: (78,1)-(78,2) = "^" + │ ├── closing_loc: ∅ + │ └── unescaped: "^" + ├── @ SymbolNode (location: (80,0)-(80,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (80,0)-(80,1) = ":" + │ ├── value_loc: (80,1)-(80,3) = "==" + │ ├── closing_loc: ∅ + │ └── unescaped: "==" + ├── @ SymbolNode (location: (82,0)-(82,4)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (82,0)-(82,1) = ":" + │ ├── value_loc: (82,1)-(82,4) = "===" + │ ├── closing_loc: ∅ + │ └── unescaped: "===" + ├── @ SymbolNode (location: (84,0)-(84,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (84,0)-(84,1) = ":" + │ ├── value_loc: (84,1)-(84,3) = "=~" + │ ├── closing_loc: ∅ + │ └── unescaped: "=~" + ├── @ SymbolNode (location: (86,0)-(86,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (86,0)-(86,1) = ":" + │ ├── value_loc: (86,1)-(86,3) = ">=" + │ ├── closing_loc: ∅ + │ └── unescaped: ">=" + ├── @ SymbolNode (location: (88,0)-(88,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (88,0)-(88,1) = ":" + │ ├── value_loc: (88,1)-(88,3) = ">>" + │ ├── closing_loc: ∅ + │ └── unescaped: ">>" + ├── @ SymbolNode (location: (90,0)-(90,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (90,0)-(90,1) = ":" + │ ├── value_loc: (90,1)-(90,2) = ">" + │ ├── closing_loc: ∅ + │ └── unescaped: ">" + ├── @ SymbolNode (location: (92,0)-(92,4)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (92,0)-(92,1) = ":" + │ ├── value_loc: (92,1)-(92,4) = "<=>" + │ ├── closing_loc: ∅ + │ └── unescaped: "<=>" + ├── @ SymbolNode (location: (94,0)-(94,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (94,0)-(94,1) = ":" + │ ├── value_loc: (94,1)-(94,3) = "<=" + │ ├── closing_loc: ∅ + │ └── unescaped: "<=" + ├── @ SymbolNode (location: (96,0)-(96,3)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (96,0)-(96,1) = ":" + │ ├── value_loc: (96,1)-(96,3) = "<<" + │ ├── closing_loc: ∅ + │ └── unescaped: "<<" + ├── @ SymbolNode (location: (98,0)-(98,2)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (98,0)-(98,1) = ":" + │ ├── value_loc: (98,1)-(98,2) = "<" + │ ├── closing_loc: ∅ + │ └── unescaped: "<" + ├── @ SymbolNode (location: (100,0)-(100,9)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (100,0)-(100,1) = ":" + │ ├── value_loc: (100,1)-(100,9) = "__LINE__" + │ ├── closing_loc: ∅ + │ └── unescaped: "__LINE__" + ├── @ SymbolNode (location: (102,0)-(102,9)) + │ ├── flags: newline, static_literal, forced_us_ascii_encoding + │ ├── opening_loc: (102,0)-(102,1) = ":" + │ ├── value_loc: (102,1)-(102,9) = "__FILE__" + │ ├── closing_loc: ∅ + │ └── unescaped: "__FILE__" + └── @ SymbolNode (location: (104,0)-(104,13)) + ├── flags: newline, static_literal, forced_us_ascii_encoding + ├── opening_loc: (104,0)-(104,1) = ":" + ├── value_loc: (104,1)-(104,13) = "__ENCODING__" + ├── closing_loc: ∅ + └── unescaped: "__ENCODING__" diff --git a/test/prism/snapshots/xstring.txt b/test/prism/snapshots/xstring.txt index b3a3cb801b..530066fd45 100644 --- a/test/prism/snapshots/xstring.txt +++ b/test/prism/snapshots/xstring.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(16,4)) +@ ProgramNode (location: (1,0)-(21,4)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(16,4)) + @ StatementsNode (location: (1,0)-(21,4)) ├── flags: ∅ - └── body: (length: 7) + └── body: (length: 8) ├── @ XStringNode (location: (1,0)-(1,7)) │ ├── flags: newline │ ├── opening_loc: (1,0)-(1,3) = "%x[" @@ -70,9 +70,15 @@ │ ├── content_loc: (13,3)-(13,3) = "" │ ├── closing_loc: (13,3)-(13,4) = "}" │ └── unescaped: "" - └── @ XStringNode (location: (15,0)-(16,4)) + ├── @ XStringNode (location: (15,0)-(18,1)) + │ ├── flags: newline + │ ├── opening_loc: (15,0)-(15,1) = "`" + │ ├── content_loc: (15,1)-(18,0) = "\nfoo\\\nb\\nar\n" + │ ├── closing_loc: (18,0)-(18,1) = "`" + │ └── unescaped: "\nfoob\nar\n" + └── @ XStringNode (location: (20,0)-(21,4)) ├── flags: newline - ├── opening_loc: (15,0)-(15,1) = "`" - ├── content_loc: (15,1)-(16,3) = "\n’" - ├── closing_loc: (16,3)-(16,4) = "`" + ├── opening_loc: (20,0)-(20,1) = "`" + ├── content_loc: (20,1)-(21,3) = "\n’" + ├── closing_loc: (21,3)-(21,4) = "`" └── unescaped: "\n’" |