Repository: ruby/yarp
Pull request #1331 (2023-08-25 18:27:12)

ignore state on embexpr_end
Ripper state can carry over from the previous node type making coparison less useful


Patch:
diff --git a/config.yml b/config.yml
index 3662c176..e4987013 100644
--- a/config.yml
+++ b/config.yml
@@ -731,8 +731,6 @@ nodes:
         type: node?
       - name: end_keyword_loc
         type: location
-      - name: name
-        type: string
     comment: |
       Represents a class declaration involving the `class` keyword.
 
@@ -1320,8 +1318,6 @@ nodes:
         type: node?
       - name: end_keyword_loc
         type: location
-      - name: name
-        type: string
     comment: |
       Represents a module declaration involving the `module` keyword.
 
diff --git a/lib/yarp/lex_compat.rb b/lib/yarp/lex_compat.rb
index 252e6bd3..3f3e4d7d 100644
--- a/lib/yarp/lex_compat.rb
+++ b/lib/yarp/lex_compat.rb
@@ -208,18 +208,9 @@ module YARP
       end
     end
 
-    # It is extremely non obvious which state the parser is in when comments get
-    # dispatched. Because of this we don't both comparing state when comparing
-    # against other comment tokens.
-    class CommentToken < Token
-      def ==(other)
-        self[0...-1] == other[0...-1]
-      end
-    end
-
-    # Heredoc end tokens are emitted in an odd order, so we don't compare the
-    # state on them.
-    class HeredocEndToken < Token
+    # Tokens where state should be ignored
+    # used for :on_comment, :on_heredoc_end, :on_embexpr_end
+    class IgnoreStateToken < Token
       def ==(other)
         self[0...-1] == other[0...-1]
       end
@@ -574,11 +565,6 @@ module YARP
       result = YARP.lex(source, @filepath)
       result_value = result.value
       previous_state = nil
-
-      # In previous versions of Ruby, Ripper wouldn't flush the bom before the
-      # first token, so we had to have a hack in place to account for that. This
-      # checks for that behavior.
-      bom_flushed = Ripper.lex("\xEF\xBB\xBF# test")[0][0][1] == 0
       bom = source.byteslice(0..2) == "\xEF\xBB\xBF"
 
       result_value.each_with_index do |(token, lex_state), index|
@@ -593,7 +579,7 @@ module YARP
         if bom && lineno == 1
           column -= 3
 
-          if index == 0 && column == 0 && !bom_flushed
+          if index == 0 && column == 0
             flushed =
               case token.type
               when :BACK_REFERENCE, :INSTANCE_VARIABLE, :CLASS_VARIABLE,
@@ -624,12 +610,12 @@ module YARP
           when :on___end__
             EndContentToken.new([[lineno, column], event, value, lex_state])
           when :on_comment
-            CommentToken.new([[lineno, column], event, value, lex_state])
+            IgnoreStateToken.new([[lineno, column], event, value, lex_state])
           when :on_heredoc_end
             # Heredoc end tokens can be emitted in an odd order, so we don't
             # want to bother comparing the state on them.
-            HeredocEndToken.new([[lineno, column], event, value, lex_state])
-          when :on_embexpr_end, :on_ident
+            IgnoreStateToken.new([[lineno, column], event, value, lex_state])
+          when :on_ident
             if lex_state == Ripper::EXPR_END
               # If we have an identifier that follows a method name like:
               #
@@ -649,6 +635,8 @@ module YARP
             else
               Token.new([[lineno, column], event, value, lex_state])
             end
+          when :on_embexpr_end
+            IgnoreStateToken.new([[lineno, column], event, value, lex_state])
           when :on_ignored_nl
             # Ignored newlines can occasionally have a LABEL state attached to
             # them which doesn't actually impact anything. We don't mirror that
diff --git a/src/yarp.c b/src/yarp.c
index fdcc303b..4de3338d 100644
--- a/src/yarp.c
+++ b/src/yarp.c
@@ -1553,7 +1553,7 @@ yp_case_node_end_keyword_loc_set(yp_case_node_t *node, const yp_token_t *end_key
 
 // Allocate a new ClassNode node.
 static yp_class_node_t *
-yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *name, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *body, const yp_token_t *end_keyword) {
+yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *body, const yp_token_t *end_keyword) {
     yp_class_node_t *node = YP_ALLOC_NODE(parser, yp_class_node_t);
 
     *node = (yp_class_node_t) {
@@ -1567,11 +1567,9 @@ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
         .inheritance_operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(inheritance_operator),
         .superclass = superclass,
         .body = body,
-        .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword),
-        .name = YP_EMPTY_STRING
+        .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
     };
 
-    yp_string_shared_init(&node->name, name->start, name->end);
     return node;
 }
 
@@ -2748,7 +2746,7 @@ yp_match_required_node_create(yp_parser_t *parser, yp_node_t *value, yp_node_t *
 
 // Allocate a new ModuleNode node.
 static yp_module_node_t *
-yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, const yp_token_t *name, yp_node_t *body, const yp_token_t *end_keyword) {
+yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *body, const yp_token_t *end_keyword) {
     yp_module_node_t *node = YP_ALLOC_NODE(parser, yp_module_node_t);
 
     *node = (yp_module_node_t) {
@@ -2763,11 +2761,9 @@ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const
         .module_keyword_loc = YP_LOCATION_TOKEN_VALUE(module_keyword),
         .constant_path = constant_path,
         .body = body,
-        .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword),
-        .name = YP_EMPTY_STRING
+        .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
     };
 
-    yp_string_shared_init(&node->name, name->start, name->end);
     return node;
 }
 
@@ -4328,13 +4324,11 @@ parser_lex_encoding_comment_start(yp_parser_t *parser, const char *cursor, ptrdi
 
     const char *cursor_limit = cursor + length - key_length + 1;
     while ((cursor = yp_memchr(cursor, 'c', (size_t) (cursor_limit - cursor), parser->encoding_changed, &parser->encoding)) != NULL) {
-        if (strncmp(cursor, "coding", key_length - 1) == 0) {
-            size_t whitespace_after_coding = yp_strspn_inline_whitespace(cursor + key_length - 1, parser->end - (cursor + key_length - 1));
-            size_t cur_pos = key_length + whitespace_after_coding;
-
-            if (cursor[cur_pos - 1] == ':' || cursor[cur_pos - 1] == '=') {
-                return cursor + cur_pos;
-            }
+        if (
+            (strncmp(cursor, "coding", key_length - 1) == 0) &&
+            (cursor[key_length - 1] == ':' || cursor[key_length - 1] == '=')
+        ) {
+            return cursor + key_length;
         }
 
         cursor++;
@@ -6614,13 +6608,7 @@ parser_lex(yp_parser_t *parser) {
 
         case YP_LEX_REGEXP: {
             // First, we'll set to start of this token to be the current end.
-            if (parser->next_start == NULL) {
-                parser->current.start = parser->current.end;
-            } else {
-                parser->current.start = parser->next_start;
-                parser->current.end = parser->next_start;
-                parser->next_start = NULL;
-            }
+            parser->current.start = parser->current.end;
 
             // We'll check if we're at the end of the file. If we are, then we need to
             // return the EOF token.
@@ -6651,10 +6639,7 @@ parser_lex(yp_parser_t *parser) {
                     // through this branch twice -- once with YP_TOKEN_REGEXP_BEGIN and then again
                     // with YP_TOKEN_STRING_CONTENT. Let's avoid tracking the newline twice, by
                     // tracking it only in the REGEXP_BEGIN case.
-                    if (
-                        !(lex_mode->as.regexp.terminator == '\n' && parser->current.type != YP_TOKEN_REGEXP_BEGIN)
-                        && parser->heredoc_end == NULL
-                    ) {
+                    if (!(lex_mode->as.regexp.terminator == '\n' && parser->current.type != YP_TOKEN_REGEXP_BEGIN)) {
                         yp_newline_list_append(&parser->newline_list, breakpoint);
                     }
 
@@ -6699,19 +6684,9 @@ parser_lex(yp_parser_t *parser) {
                 if (*breakpoint == '\\') {
                     size_t difference = yp_unescape_calculate_difference(parser, breakpoint, YP_UNESCAPE_ALL, false);
 
-                    // If the result is an escaped newline ...
-                    if (*(breakpoint + difference - 1) == '\n') {
-                        if (parser->heredoc_end) {
-                            // ... if we are on the same line as a heredoc, flush the heredoc and
-                            // continue parsing after heredoc_end.
-                            parser->current.end = breakpoint + difference;
-                            parser_flush_heredoc_end(parser);
-                            LEX(YP_TOKEN_STRING_CONTENT);
-                        } else {
-                            // ... else track the newline.
-                            yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1);
-                        }
-                    }
+                    // If the result is an escaped newline, then we need to
+                    // track that newline.
+                    yp_newline_list_check_append(&parser->newline_list, breakpoint + difference - 1);
 
                     breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
                     continue;
@@ -6849,19 +6824,9 @@ parser_lex(yp_parser_t *parser) {
                         yp_unescape_type_t unescape_type = parser->lex_modes.current->as.string.interpolation ? YP_UNESCAPE_ALL : YP_UNESCAPE_MINIMAL;
                         size_t difference = yp_unescape_calculate_difference(parser, breakpoint, unescape_type, false);
 
-                        // If the result is an escaped newline ...
-                        if (*(breakpoint + difference - 1) == '\n') {
-                            if (parser->heredoc_end) {
-                                // ... if we are on the same line as a heredoc, flush the heredoc and
-                                // continue parsing after heredoc_end.
-                                parser->current.end = breakpoint + difference;
-                                parser_flush_heredoc_end(parser);
-                                LEX(YP_TOKEN_STRING_CONTENT);
-                            } else {
-                                // ... else track the newline.
-                                yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1);
-                            }
-                        }
+                        // If the result is an escaped newline, then we need to
+                        // track that newline.
+                        yp_newline_list_check_append(&parser->newline_list, breakpoint + difference - 1);
 
                         breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
                         break;
@@ -10886,12 +10851,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
                 return (yp_node_t *) yp_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous);
             }
 
-            yp_node_t *constant_path = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected to find a class name after `class`.");
-            yp_token_t name = parser->previous;
-            if (name.type != YP_TOKEN_CONSTANT) {
-                yp_diagnostic_list_append(&parser->error_list, name.start, name.end, "Expected a constant name after `class`.");
-            }
-
+            yp_node_t *name = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected to find a class name after `class`.");
             yp_token_t inheritance_operator;
             yp_node_t *superclass;
 
@@ -10932,7 +10892,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
             yp_constant_id_list_t locals = parser->current_scope->locals;
             yp_parser_scope_pop(parser);
             yp_do_loop_stack_pop(parser);
-            return (yp_node_t *) yp_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous);
+            return (yp_node_t *) yp_class_node_create(parser, &locals, &class_keyword, name, &inheritance_operator, superclass, statements, &parser->previous);
         }
         case YP_TOKEN_KEYWORD_DEF: {
             yp_token_t def_keyword = parser->current;
@@ -11326,14 +11286,13 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
             parser_lex(parser);
 
             yp_token_t module_keyword = parser->previous;
-            yp_node_t *constant_path = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected to find a module name after `module`.");
-            yp_token_t name;
+            yp_node_t *name = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected to find a module name after `module`.");
 
-            // If we can recover from a syntax error that occurred while parsing
-            // the name of the module, then we'll handle that here.
-            if (YP_NODE_TYPE_P(constant_path, YP_NODE_MISSING_NODE)) {
-                yp_token_t missing = (yp_token_t) { .type = YP_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
-                return (yp_node_t *) yp_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing);
+            // If we can recover from a syntax error that occurred while parsing the
+            // name of the module, then we'll handle that here.
+            if (YP_NODE_TYPE_P(name, YP_NODE_MISSING_NODE)) {
+                yp_token_t end_keyword = (yp_token_t) { .type = YP_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
+                return (yp_node_t *) yp_module_node_create(parser, NULL, &module_keyword, name, NULL, &end_keyword);
             }
 
             while (accept(parser, YP_TOKEN_COLON_COLON)) {
@@ -11342,15 +11301,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
                 expect(parser, YP_TOKEN_CONSTANT, "Expected to find a module name after `::`.");
                 yp_node_t *constant = (yp_node_t *) yp_constant_read_node_create(parser, &parser->previous);
 
-                constant_path = (yp_node_t *) yp_constant_path_node_create(parser, constant_path, &double_colon, constant);
-            }
-
-            // Here we retrieve the name of the module. If it wasn't a constant,
-            // then it's possible that `module foo` was passed, which is a
-            // syntax error. We handle that here as well.
-            name = parser->previous;
-            if (name.type != YP_TOKEN_CONSTANT) {
-                yp_diagnostic_list_append(&parser->error_list, name.start, name.end, "Expected to find a module name after `module`.");
+                name = (yp_node_t *)yp_constant_path_node_create(parser, name, &double_colon, constant);
             }
 
             yp_parser_scope_push(parser, true);
@@ -11377,7 +11328,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
                 yp_diagnostic_list_append(&parser->error_list, module_keyword.start, module_keyword.end, "Module definition in method body");
             }
 
-            return (yp_node_t *) yp_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous);
+            return (yp_node_t *) yp_module_node_create(parser, &locals, &module_keyword, name, statements, &parser->previous);
         }
         case YP_TOKEN_KEYWORD_NIL:
             parser_lex(parser);
diff --git a/templates/java/org/yarp/Loader.java.erb b/templates/java/org/yarp/Loader.java.erb
index 312e2321..454f5f30 100644
--- a/templates/java/org/yarp/Loader.java.erb
+++ b/templates/java/org/yarp/Loader.java.erb
@@ -95,28 +95,13 @@ public class Loader {
         return new ParseResult(node, comments, errors, warnings);
     }
 
-    private byte[] loadEmbeddedString() {
+    private byte[] loadString() {
         int length = loadVarInt();
         byte[] string = new byte[length];
         buffer.get(string);
         return string;
     }
 
-    private byte[] loadString() {
-        switch (buffer.get()) {
-            case 1:
-                int start = loadVarInt();
-                int length = loadVarInt();
-                byte[] string = new byte[length];
-                System.arraycopy(source.bytes, start, string, 0, length);
-                return string;
-            case 2:
-                return loadEmbeddedString();
-            default:
-                throw new Error("Expected 0 or 1 but was " + buffer.get());
-        }
-    }
-
     private ParseResult.Comment[] loadComments() {
         int count = loadVarInt();
         ParseResult.Comment[] comments = new ParseResult.Comment[count];
@@ -138,7 +123,7 @@ public class Loader {
 
         // error messages only contain ASCII characters
         for (int i = 0; i < count; i++) {
-            byte[] bytes = loadEmbeddedString();
+            byte[] bytes = loadString();
             String message = new String(bytes, StandardCharsets.US_ASCII);
             Nodes.Location location = loadLocation();
 
@@ -155,7 +140,7 @@ public class Loader {
 
         // warning messages only contain ASCII characters
         for (int i = 0; i < count; i++) {
-            byte[] bytes = loadEmbeddedString();
+            byte[] bytes = loadString();
             String message = new String(bytes, StandardCharsets.US_ASCII);
             Nodes.Location location = loadLocation();
 
diff --git a/templates/lib/yarp/serialize.rb.erb b/templates/lib/yarp/serialize.rb.erb
index 8ee072c0..65cd52e2 100644
--- a/templates/lib/yarp/serialize.rb.erb
+++ b/templates/lib/yarp/serialize.rb.erb
@@ -54,8 +54,8 @@ module YARP
         end
 
         comments = load_varint.times.map { Comment.new(Comment::TYPES.fetch(load_varint), load_location) }
-        errors = load_varint.times.map { ParseError.new(load_embedded_string, load_location) }
-        warnings = load_varint.times.map { ParseWarning.new(load_embedded_string, load_location) }
+        errors = load_varint.times.map { ParseError.new(load_string, load_location) }
+        warnings = load_varint.times.map { ParseWarning.new(load_string, load_location) }
 
         raise "Expected to consume all bytes while deserializing" unless @io.eof?
 
@@ -70,8 +70,8 @@ module YARP
         @input = input.force_encoding(@encoding).freeze
 
         comments = load_varint.times.map { Comment.new(Comment::TYPES.fetch(io.getbyte), load_location) }
-        errors = load_varint.times.map { ParseError.new(load_embedded_string, load_location) }
-        warnings = load_varint.times.map { ParseWarning.new(load_embedded_string, load_location) }
+        errors = load_varint.times.map { ParseError.new(load_string, load_location) }
+        warnings = load_varint.times.map { ParseWarning.new(load_string, load_location) }
 
         @constant_pool_offset = io.read(4).unpack1("L")
         @constant_pool = Array.new(load_varint, nil)
@@ -110,19 +110,8 @@ module YARP
         end
       end
 
-      def load_embedded_string
-        io.read(load_varint).force_encoding(encoding)
-      end
-
       def load_string
-        case io.getbyte
-        when 1
-          input.byteslice(load_varint, load_varint).force_encoding(encoding)
-        when 2
-          load_embedded_string
-        else
-          raise
-        end
+        io.read(load_varint).force_encoding(encoding)
       end
 
       def load_location
diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb
index 9b495405..497e287b 100644
--- a/templates/src/serialize.c.erb
+++ b/templates/src/serialize.c.erb
@@ -15,7 +15,7 @@ yp_sizet_to_u32(size_t value) {
 }
 
 static void
-yp_serialize_location(yp_parser_t *parser, yp_location_t *location, yp_buffer_t *buffer) {
+serialize_location(yp_parser_t *parser, yp_location_t *location, yp_buffer_t *buffer) {
     assert(location->start);
     assert(location->end);
     assert(location->start <= location->end);
@@ -24,36 +24,13 @@ yp_serialize_location(yp_parser_t *parser, yp_location_t *location, yp_buffer_t
     yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(location->end - location->start));
 }
 
-static void
-yp_serialize_string(yp_parser_t *parser, yp_string_t *string, yp_buffer_t *buffer) {
-    switch (string->type) {
-        case YP_STRING_SHARED: {
-            yp_buffer_append_u8(buffer, 1);
-            yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(yp_string_source(string) - parser->start));
-            yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_string_length(string)));
-            break;
-        }
-        case YP_STRING_OWNED:
-        case YP_STRING_CONSTANT: {
-            uint32_t length = yp_sizet_to_u32(yp_string_length(string));
-            yp_buffer_append_u8(buffer, 2);
-            yp_buffer_append_u32(buffer, length);
-            yp_buffer_append_str(buffer, yp_string_source(string), length);
-            break;
-        }
-        case YP_STRING_MAPPED:
-            assert(false && "Cannot serialize mapped strings.");
-            break;
-    }
-}
-
 void
 yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) {
     yp_buffer_append_u8(buffer, (uint8_t) YP_NODE_TYPE(node));
 
     size_t offset = buffer->length;
 
-    yp_serialize_location(parser, &node->location, buffer);
+    serialize_location(parser, &node->location, buffer);
 
     switch (YP_NODE_TYPE(node)) {
         // We do not need to serialize a ScopeNode ever as
@@ -79,7 +56,9 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) {
                 yp_serialize_node(parser, (yp_node_t *)((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
             }
             <%- when StringParam -%>
-            yp_serialize_string(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
+            uint32_t <%= param.name %>_length = yp_sizet_to_u32(yp_string_length(&((yp_<%= node.human %>_t *)node)-><%= param.name %>));
+            yp_buffer_append_u32(buffer, <%= param.name %>_length);
+            yp_buffer_append_str(buffer, yp_string_source(&((yp_<%= node.human %>_t *)node)-><%= param.name %>), <%= param.name %>_length);
             <%- when NodeListParam -%>
             uint32_t <%= param.name %>_size = yp_sizet_to_u32(((yp_<%= node.human %>_t *)node)-><%= param.name %>.size);
             yp_buffer_append_u32(buffer, <%= param.name %>_size);
@@ -90,7 +69,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) {
             uint32_t <%= param.name %>_size = yp_sizet_to_u32(((yp_<%= node.human %>_t *)node)-><%= param.name %>.size);
             yp_buffer_append_u32(buffer, <%= param.name %>_size);
             for (uint32_t index = 0; index < <%= param.name %>_size; index++) {
-                yp_serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>.locations[index], buffer);
+                serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>.locations[index], buffer);
             }
             <%- when ConstantParam -%>
             yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_<%= node.human %>_t *)node)-><%= param.name %>));
@@ -101,13 +80,13 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) {
                 yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_<%= node.human %>_t *)node)-><%= param.name %>.ids[index]));
             }
             <%- when LocationParam -%>
-            yp_serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
+            serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
             <%- when OptionalLocationParam -%>
             if (((yp_<%= node.human %>_t *)node)-><%= param.name %>.start == NULL) {
                 yp_buffer_append_u8(buffer, 0);
             } else {
                 yp_buffer_append_u8(buffer, 1);
-                yp_serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
+                serialize_location(parser, &((yp_<%= node.human %>_t *)node)-><%= param.name %>, buffer);
             }
             <%- when UInt32Param -%>
             yp_buffer_append_u32(buffer, ((yp_<%= node.human %>_t *)node)-><%= param.name %>);
@@ -128,8 +107,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) {
     }
 }
 
-static void
-yp_serialize_comment(yp_parser_t *parser, yp_comment_t *comment, yp_buffer_t *buffer) {
+void yp_serialize_comment(yp_parser_t *parser, yp_comment_t *comment, yp_buffer_t *buffer) {
     // serialize type
     yp_buffer_append_u8(buffer, (uint8_t) comment->type);
 
@@ -138,18 +116,16 @@ yp_serialize_comment(yp_parser_t *parser, yp_comment_t *comment, yp_buffer_t *bu
     yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(comment->end - comment->start));
 }
 
-static void
-yp_serialize_comment_list(yp_parser_t *parser, yp_list_t *list, yp_buffer_t *buffer) {
-    yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(list)));
+void yp_serialize_comment_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) {
+    yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(&list)));
 
     yp_comment_t *comment;
-    for (comment = (yp_comment_t *) list->head; comment != NULL; comment = (yp_comment_t *) comment->node.next) {
+    for (comment = (yp_comment_t *) list.head; comment != NULL; comment = (yp_comment_t *) comment->node.next) {
         yp_serialize_comment(parser, comment, buffer);
     }
 }
 
-static void
-yp_serialize_diagnostic(yp_parser_t *parser, yp_diagnostic_t *diagnostic, yp_buffer_t *buffer) {
+void yp_serialize_diagnostic(yp_parser_t *parser, yp_diagnostic_t *diagnostic, yp_buffer_t *buffer) {
     // serialize message
     size_t message_length = strlen(diagnostic->message);
     yp_buffer_append_u32(buffer, yp_sizet_to_u32(message_length));
@@ -160,12 +136,11 @@ yp_serialize_diagnostic(yp_parser_t *parser, yp_diagnostic_t *diagnostic, yp_buf
     yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(diagnostic->end - diagnostic->start));
 }
 
-static void
-yp_serialize_diagnostic_list(yp_parser_t *parser, yp_list_t *list, yp_buffer_t *buffer) {
-    yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(list)));
+void yp_serialize_diagnostic_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) {
+    yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(&list)));
 
     yp_diagnostic_t *diagnostic;
-    for (diagnostic = (yp_diagnostic_t *) list->head; diagnostic != NULL; diagnostic = (yp_diagnostic_t *) diagnostic->node.next) {
+    for (diagnostic = (yp_diagnostic_t *) list.head; diagnostic != NULL; diagnostic = (yp_diagnostic_t *) diagnostic->node.next) {
         yp_serialize_diagnostic(parser, diagnostic, buffer);
     }
 }
@@ -178,9 +153,14 @@ yp_serialize_content(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer)
     yp_buffer_append_u32(buffer, yp_sizet_to_u32(encoding_length));
     yp_buffer_append_str(buffer, parser->encoding.name, encoding_length);
 
-    yp_serialize_comment_list(parser, &parser->comment_list, buffer);
-    yp_serialize_diagnostic_list(parser, &parser->error_list, buffer);
-    yp_serialize_diagnostic_list(parser, &parser->warning_list, buffer);
+    // Serialize the comments
+    yp_serialize_comment_list(parser, parser->comment_list, buffer);
+
+    // Serialize the errors
+    yp_serialize_diagnostic_list(parser, parser->error_list, buffer);
+
+    // Serialize the warnings
+    yp_serialize_diagnostic_list(parser, parser->warning_list, buffer);
 
     // Here we're going to leave space for the offset of the constant pool in
     // the buffer.
@@ -244,11 +224,16 @@ yp_lex_serialize(const char *source, size_t size, const char *filepath, yp_buffe
     yp_node_t *node = yp_parse(&parser);
 
     // Append 0 to mark end of tokens
-    yp_buffer_append_u8(buffer, 0);
+    yp_buffer_append_u32(buffer, 0);
+
+    // Serialize the comments
+    yp_serialize_comment_list(&parser, parser.comment_list, buffer);
+
+    // Serialize the errors
+    yp_serialize_diagnostic_list(&parser, parser.error_list, buffer);
 
-    yp_serialize_comment_list(&parser, &parser.comment_list, buffer);
-    yp_serialize_diagnostic_list(&parser, &parser.error_list, buffer);
-    yp_serialize_diagnostic_list(&parser, &parser.warning_list, buffer);
+    // Serialize the warnings
+    yp_serialize_diagnostic_list(&parser, parser.warning_list, buffer);
 
     yp_node_destroy(&parser, node);
     yp_parser_free(&parser);


Test patch:
diff --git a/test/encoding_test.rb b/test/encoding_test.rb
index c96a08e6..95d7bd32 100644
--- a/test/encoding_test.rb
+++ b/test/encoding_test.rb
@@ -50,13 +50,6 @@ class EncodingTest < Test::Unit::TestCase
     assert_equal Encoding.find("utf-8"), actual
   end
 
-  def test_coding_with_whitespace
-    result = YARP.parse("# coding \t \r  \v   :     \t \v    \r   ascii-8bit \nident")
-    actual = result.value.statements.body.first.name.encoding
-    assert_equal Encoding.find("ascii-8bit"), actual
-  end
-
-
   def test_emacs_style
     result = YARP.parse("# -*- coding: utf-8 -*-\nident")
     actual = result.value.statements.body.first.name.encoding
diff --git a/test/errors_test.rb b/test/errors_test.rb
index d58fd274..6ac2dcbc 100644
--- a/test/errors_test.rb
+++ b/test/errors_test.rb
@@ -18,10 +18,9 @@ class ErrorsTest < Test::Unit::TestCase
       Location(),
       ConstantReadNode(),
       StatementsNode(
-        [ModuleNode([], Location(), MissingNode(), nil, Location(), "")]
+        [ModuleNode([], Location(), MissingNode(), nil, Location())]
       ),
-      Location(),
-      "Parent"
+      Location()
     )
 
     assert_errors expected, "module Parent module end", [
@@ -131,14 +130,6 @@ class ErrorsTest < Test::Unit::TestCase
     ]
   end
 
-  def test_unterminated_regular_expression_with_heredoc
-    source = "<<-END + /b\nEND\n"
-
-    assert_errors expression(source), source, [
-      ["Expected a closing delimiter for a regular expression.", 10..10]
-    ]
-  end
-
   def test_unterminated_xstring
     assert_errors expression("`hello"), "`hello", [
       ["Expected a closing delimiter for an xstring.", 1..1]
@@ -392,7 +383,7 @@ class ErrorsTest < Test::Unit::TestCase
       Location(),
       nil,
       nil,
-      StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location(), "A")]),
+      StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location())]),
       [],
       Location(),
       nil,
@@ -423,7 +414,7 @@ class ErrorsTest < Test::Unit::TestCase
            BlockNode(
              [],
              nil,
-             StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location(), "Foo")]),
+             StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location())]),
              Location(),
              Location()
            ),
@@ -464,8 +455,7 @@ class ErrorsTest < Test::Unit::TestCase
            nil,
            nil,
            nil,
-           Location(),
-           "A"
+           Location()
          )]
       ),
       [],
@@ -965,8 +955,7 @@ class ErrorsTest < Test::Unit::TestCase
       nil,
       nil,
       StatementsNode([ReturnNode(Location(), nil)]),
-      Location(),
-      "A"
+      Location()
     )
 
     assert_errors expected, "class A; return; end", [
@@ -980,8 +969,7 @@ class ErrorsTest < Test::Unit::TestCase
       Location(),
       ConstantReadNode(),
       StatementsNode([ReturnNode(Location(), nil)]),
-      Location(),
-      "A"
+      Location()
     )
 
     assert_errors expected, "module A; return; end", [
diff --git a/test/fixtures/wrapping_heredoc.txt b/test/fixtures/wrapping_heredoc.txt
deleted file mode 100644
index d5fc7101..00000000
--- a/test/fixtures/wrapping_heredoc.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-# test regex, string, and lists that wrap a heredoc thanks to an escaped newline
-
-# ripper incorrectly creates a "b\nc" string instead of two separate string tokens
-pp <<-A.gsub(/b\
-a
-A
-c/, "")
-
-# ripper incorrectly creates a "e\nf" string instead of two separate string tokens
-pp <<-A + "e\
-d
-A
-f"
diff --git a/test/parse_test.rb b/test/parse_test.rb
index f8c1fe12..c0f3ecf5 100644
--- a/test/parse_test.rb
+++ b/test/parse_test.rb
@@ -112,10 +112,6 @@ class ParseTest < Test::Unit::TestCase
       # Waiting for feedback on https://bugs.ruby-lang.org/issues/19838.
       return if relative == "seattlerb/heredoc_nested.txt"
 
-      # Ripper seems to have a bug that the regex portions before and after the heredoc are combined
-      # into a single token.
-      return if relative == "wrapping_heredoc.txt"
-
       # Finally, assert that we can lex the source and get the same tokens as
       # Ripper.
       lex_result = YARP.lex_compat(source)
diff --git a/test/snapshots/classes.txt b/test/snapshots/classes.txt
index 33b3d042..60ab0ead 100644
--- a/test/snapshots/classes.txt
+++ b/test/snapshots/classes.txt
@@ -16,8 +16,7 @@ ProgramNode(0...370)(
             (10...11)
           )]
        ),
-       (14...17),
-       "A"
+       (14...17)
      ),
      ClassNode(19...39)(
        [],
@@ -33,8 +32,7 @@ ProgramNode(0...370)(
          EnsureNode(28...39)((28...34), nil, (36...39)),
          (36...39)
        ),
-       (36...39),
-       "A"
+       (36...39)
      ),
      ClassNode(41...75)(
        [],
@@ -50,8 +48,7 @@ ProgramNode(0...370)(
          EnsureNode(64...75)((64...70), nil, (72...75)),
          (72...75)
        ),
-       (72...75),
-       "A"
+       (72...75)
      ),
      ClassNode(77...98)(
        [:a],
@@ -68,8 +65,7 @@ ProgramNode(0...370)(
             (91...92)
           )]
        ),
-       (95...98),
-       "A"
+       (95...98)
      ),
      SingletonClassNode(100...120)(
        [],
@@ -122,8 +118,7 @@ ProgramNode(0...370)(
             (154...157)
           )]
        ),
-       (159...162),
-       "A"
+       (159...162)
      ),
      ClassNode(164...218)(
        [],
@@ -148,8 +143,7 @@ ProgramNode(0...370)(
             (210...213)
           )]
        ),
-       (215...218),
-       "A"
+       (215...218)
      ),
      SingletonClassNode(220...240)(
        [],
@@ -280,8 +274,7 @@ ProgramNode(0...370)(
          "[]"
        ),
        nil,
-       (367...370),
-       "A"
+       (367...370)
      )]
   )
 )
diff --git a/test/snapshots/method_calls.txt b/test/snapshots/method_calls.txt
index b2c84d0d..f59fb7e4 100644
--- a/test/snapshots/method_calls.txt
+++ b/test/snapshots/method_calls.txt
@@ -1191,8 +1191,7 @@ ProgramNode(0...1237)(
                  "baz"
                )]
             ),
-            (926...929),
-            "Bar"
+            (926...929)
           )]
        ),
        nil,
@@ -1223,8 +1222,7 @@ ProgramNode(0...1237)(
                  "baz"
                )]
             ),
-            (957...960),
-            "Bar"
+            (957...960)
           )]
        ),
        nil,
diff --git a/test/snapshots/modules.txt b/test/snapshots/modules.txt
index a3cf30b9..705563a9 100644
--- a/test/snapshots/modules.txt
+++ b/test/snapshots/modules.txt
@@ -14,8 +14,7 @@ ProgramNode(0...140)(
             (11...12)
           )]
        ),
-       (15...18),
-       "A"
+       (15...18)
      ),
      InterpolatedStringNode(20...38)(
        (20...23),
@@ -49,8 +48,7 @@ ProgramNode(0...140)(
          (48...50)
        ),
        nil,
-       (52...55),
-       "M"
+       (52...55)
      ),
      ModuleNode(57...85)(
        [:x],
@@ -72,16 +70,14 @@ ProgramNode(0...140)(
          nil,
          (82...85)
        ),
-       (82...85),
-       "A"
+       (82...85)
      ),
      ModuleNode(87...101)(
        [],
        (87...93),
        ConstantPathNode(94...97)(nil, ConstantReadNode(96...97)(), (94...96)),
        nil,
-       (98...101),
-       "A"
+       (98...101)
      ),
      ModuleNode(103...120)(
        [],
@@ -102,8 +98,7 @@ ProgramNode(0...140)(
          (113...115)
        ),
        nil,
-       (117...120),
-       "B"
+       (117...120)
      ),
      ModuleNode(122...140)(
        [],
@@ -124,8 +119,7 @@ ProgramNode(0...140)(
          (133...135)
        ),
        nil,
-       (137...140),
-       "B"
+       (137...140)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/TestRubyParserShared.txt b/test/snapshots/seattlerb/TestRubyParserShared.txt
index 0eee2a39..cfad7e8a 100644
--- a/test/snapshots/seattlerb/TestRubyParserShared.txt
+++ b/test/snapshots/seattlerb/TestRubyParserShared.txt
@@ -86,8 +86,7 @@ ProgramNode(0...689)(
             (243...246)
           )]
        ),
-       (266...269),
-       "X"
+       (266...269)
      ),
      ClassNode(293...376)(
        [],
@@ -109,12 +108,10 @@ ProgramNode(0...689)(
                  (339...340)
                )]
             ),
-            (355...358),
-            "Y"
+            (355...358)
           )]
        ),
-       (373...376),
-       "X"
+       (373...376)
      ),
      ClassNode(395...498)(
        [],
@@ -160,8 +157,7 @@ ProgramNode(0...689)(
             (477...480)
           )]
        ),
-       (495...498),
-       "X"
+       (495...498)
      ),
      ModuleNode(517...565)(
        [],
@@ -179,8 +175,7 @@ ProgramNode(0...689)(
             (530...531)
           )]
        ),
-       (562...565),
-       "X"
+       (562...565)
      ),
      ModuleNode(568...651)(
        [],
@@ -198,12 +193,10 @@ ProgramNode(0...689)(
                  (614...615)
                )]
             ),
-            (630...633),
-            "Y"
+            (630...633)
           )]
        ),
-       (648...651),
-       "X"
+       (648...651)
      ),
      CallNode(670...689)(
        nil,
diff --git a/test/snapshots/seattlerb/class_comments.txt b/test/snapshots/seattlerb/class_comments.txt
index b96c5d63..12b347ee 100644
--- a/test/snapshots/seattlerb/class_comments.txt
+++ b/test/snapshots/seattlerb/class_comments.txt
@@ -22,8 +22,7 @@ ProgramNode(19...71)(
             (64...67)
           )]
        ),
-       (68...71),
-       "X"
+       (68...71)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/defn_oneliner_eq2.txt b/test/snapshots/seattlerb/defn_oneliner_eq2.txt
index d5798209..30aaf719 100644
--- a/test/snapshots/seattlerb/defn_oneliner_eq2.txt
+++ b/test/snapshots/seattlerb/defn_oneliner_eq2.txt
@@ -30,8 +30,7 @@ ProgramNode(0...28)(
             nil
           )]
        ),
-       (25...28),
-       "X"
+       (25...28)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/defs_oneliner_eq2.txt b/test/snapshots/seattlerb/defs_oneliner_eq2.txt
index 2ec8dc86..8a4f9e90 100644
--- a/test/snapshots/seattlerb/defs_oneliner_eq2.txt
+++ b/test/snapshots/seattlerb/defs_oneliner_eq2.txt
@@ -30,8 +30,7 @@ ProgramNode(0...33)(
             nil
           )]
        ),
-       (30...33),
-       "X"
+       (30...33)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/magic_encoding_comment.txt b/test/snapshots/seattlerb/magic_encoding_comment.txt
index 08c8d9ea..2ab320ed 100644
--- a/test/snapshots/seattlerb/magic_encoding_comment.txt
+++ b/test/snapshots/seattlerb/magic_encoding_comment.txt
@@ -30,8 +30,7 @@ ProgramNode(18...90)(
             (83...86)
           )]
        ),
-       (87...90),
-       "ExampleUTF8ClassNameVarietà"
+       (87...90)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/module_comments.txt b/test/snapshots/seattlerb/module_comments.txt
index 4f399904..808f4799 100644
--- a/test/snapshots/seattlerb/module_comments.txt
+++ b/test/snapshots/seattlerb/module_comments.txt
@@ -20,8 +20,7 @@ ProgramNode(24...77)(
             (70...73)
           )]
        ),
-       (74...77),
-       "X"
+       (74...77)
      )]
   )
 )
diff --git a/test/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt b/test/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt
index 4445e447..4f7ae811 100644
--- a/test/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt
+++ b/test/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt
@@ -18,8 +18,7 @@ ProgramNode(0...48)(
        nil,
        nil,
        nil,
-       (45...48),
-       "Foo"
+       (45...48)
      )]
   )
 )
diff --git a/test/snapshots/unparser/corpus/literal/class.txt b/test/snapshots/unparser/corpus/literal/class.txt
index aa457618..96b50c7a 100644
--- a/test/snapshots/unparser/corpus/literal/class.txt
+++ b/test/snapshots/unparser/corpus/literal/class.txt
@@ -8,8 +8,7 @@ ProgramNode(0...213)(
        nil,
        nil,
        nil,
-       (8...11),
-       "A"
+       (8...11)
      ),
      SingletonClassNode(13...27)(
        [],
@@ -40,8 +39,7 @@ ProgramNode(0...213)(
        nil,
        nil,
        nil,
-       (60...63),
-       "B"
+       (60...63)
      ),
      ClassNode(65...82)(
        [],
@@ -58,8 +56,7 @@ ProgramNode(0...213)(
        nil,
        nil,
        nil,
-       (79...82),
-       "C"
+       (79...82)
      ),
      ClassNode(84...99)(
        [],
@@ -68,8 +65,7 @@ ProgramNode(0...213)(
        (92...93),
        ConstantReadNode(94...95)(),
        nil,
-       (96...99),
-       "A"
+       (96...99)
      ),
      ClassNode(101...119)(
        [],
@@ -82,8 +78,7 @@ ProgramNode(0...213)(
          (112...114)
        ),
        nil,
-       (116...119),
-       "A"
+       (116...119)
      ),
      ClassNode(121...142)(
        [],
@@ -100,8 +95,7 @@ ProgramNode(0...213)(
          (135...137)
        ),
        nil,
-       (139...142),
-       "B"
+       (139...142)
      ),
      ClassNode(144...198)(
        [],
@@ -149,8 +143,7 @@ ProgramNode(0...213)(
             (191...194)
           )]
        ),
-       (195...198),
-       "A"
+       (195...198)
      ),
      ClassNode(200...213)(
        [],
@@ -163,8 +156,7 @@ ProgramNode(0...213)(
        nil,
        nil,
        nil,
-       (210...213),
-       "A"
+       (210...213)
      )]
   )
 )
diff --git a/test/snapshots/unparser/corpus/literal/if.txt b/test/snapshots/unparser/corpus/literal/if.txt
index 1bfbe7e2..8375e9ac 100644
--- a/test/snapshots/unparser/corpus/literal/if.txt
+++ b/test/snapshots/unparser/corpus/literal/if.txt
@@ -80,8 +80,7 @@ ProgramNode(0...246)(
             nil
           )]
        ),
-       (130...133),
-       "A"
+       (130...133)
      ),
      ModuleNode(135...170)(
        [:foo],
@@ -114,8 +113,7 @@ ProgramNode(0...246)(
             nil
           )]
        ),
-       (167...170),
-       "B"
+       (167...170)
      ),
      UnlessNode(171...197)(
        (171...177),
diff --git a/test/snapshots/unparser/corpus/literal/module.txt b/test/snapshots/unparser/corpus/literal/module.txt
index 4c805d3d..c917fedd 100644
--- a/test/snapshots/unparser/corpus/literal/module.txt
+++ b/test/snapshots/unparser/corpus/literal/module.txt
@@ -1,14 +1,7 @@
 ProgramNode(0...106)(
   [],
   StatementsNode(0...106)(
-    [ModuleNode(0...12)(
-       [],
-       (0...6),
-       ConstantReadNode(7...8)(),
-       nil,
-       (9...12),
-       "A"
-     ),
+    [ModuleNode(0...12)([], (0...6), ConstantReadNode(7...8)(), nil, (9...12)),
      ModuleNode(14...29)(
        [],
        (14...20),
@@ -18,8 +11,7 @@ ProgramNode(0...106)(
          (22...24)
        ),
        nil,
-       (26...29),
-       "B"
+       (26...29)
      ),
      ModuleNode(31...49)(
        [],
@@ -34,8 +26,7 @@ ProgramNode(0...106)(
          (42...44)
        ),
        nil,
-       (46...49),
-       "C"
+       (46...49)
      ),
      ModuleNode(51...106)(
        [],
@@ -81,8 +72,7 @@ ProgramNode(0...106)(
             (99...102)
           )]
        ),
-       (103...106),
-       "A"
+       (103...106)
      )]
   )
 )
diff --git a/test/snapshots/unparser/corpus/literal/send.txt b/test/snapshots/unparser/corpus/literal/send.txt
index 083a0140..2c2ce8cd 100644
--- a/test/snapshots/unparser/corpus/literal/send.txt
+++ b/test/snapshots/unparser/corpus/literal/send.txt
@@ -47,8 +47,7 @@ ProgramNode(0...999)(
             (15...18)
           )]
        ),
-       (32...35),
-       "A"
+       (32...35)
      ),
      ModuleNode(37...73)(
        [:local],
@@ -74,8 +73,7 @@ ProgramNode(0...999)(
             "bar"
           )]
        ),
-       (70...73),
-       "A"
+       (70...73)
      ),
      CallNode(74...89)(
        ClassNode(74...85)(
@@ -85,8 +83,7 @@ ProgramNode(0...999)(
          nil,
          nil,
          nil,
-         (82...85),
-         "A"
+         (82...85)
        ),
        (85...86),
        (86...89),
@@ -103,8 +100,7 @@ ProgramNode(0...999)(
          (90...96),
          ConstantReadNode(97...98)(),
          nil,
-         (99...102),
-         "A"
+         (99...102)
        ),
        (102...103),
        (103...106),
diff --git a/test/snapshots/unparser/corpus/literal/while.txt b/test/snapshots/unparser/corpus/literal/while.txt
index dae7e0f0..98088460 100644
--- a/test/snapshots/unparser/corpus/literal/while.txt
+++ b/test/snapshots/unparser/corpus/literal/while.txt
@@ -62,8 +62,7 @@ ProgramNode(0...620)(
             "foo"
           )]
        ),
-       (65...68),
-       "A"
+       (65...68)
      ),
      DefNode(70...110)(
        (74...77),
@@ -155,8 +154,7 @@ ProgramNode(0...620)(
             0
           )]
        ),
-       (143...146),
-       "A"
+       (143...146)
      ),
      ModuleNode(148...182)(
        [:foo],
@@ -188,8 +186,7 @@ ProgramNode(0...620)(
             0
           )]
        ),
-       (179...182),
-       "A"
+       (179...182)
      ),
      ModuleNode(184...228)(
        [:foo],
@@ -231,8 +228,7 @@ ProgramNode(0...620)(
             0
           )]
        ),
-       (225...228),
-       "A"
+       (225...228)
      ),
      ModuleNode(230...299)(
        [],
@@ -305,8 +301,7 @@ ProgramNode(0...620)(
             "each"
           )]
        ),
-       (296...299),
-       "A"
+       (296...299)
      ),
      ModuleNode(301...370)(
        [],
@@ -369,8 +364,7 @@ ProgramNode(0...620)(
             "each"
           )]
        ),
-       (367...370),
-       "A"
+       (367...370)
      ),
      LocalVariableWriteNode(371...402)(
        :x,
diff --git a/test/snapshots/unparser/corpus/semantic/while.txt b/test/snapshots/unparser/corpus/semantic/while.txt
index 148db33d..fd495fbd 100644
--- a/test/snapshots/unparser/corpus/semantic/while.txt
+++ b/test/snapshots/unparser/corpus/semantic/while.txt
@@ -178,8 +178,7 @@ ProgramNode(0...188)(
             0
           )]
        ),
-       (185...188),
-       "A"
+       (185...188)
      )]
   )
 )
diff --git a/test/snapshots/while.txt b/test/snapshots/while.txt
index 484eb68b..cc0d2fbf 100644
--- a/test/snapshots/while.txt
+++ b/test/snapshots/while.txt
@@ -130,8 +130,7 @@ ProgramNode(0...314)(
               (181...182)
             )]
          ),
-         (195...198),
-         "Foo"
+         (195...198)
        ),
        StatementsNode(200...205)([BreakNode(200...205)(nil, (200...205))]),
        0
diff --git a/test/snapshots/whitequark/class.txt b/test/snapshots/whitequark/class.txt
index c176350d..0061b34a 100644
--- a/test/snapshots/whitequark/class.txt
+++ b/test/snapshots/whitequark/class.txt
@@ -8,8 +8,7 @@ ProgramNode(0...29)(
        nil,
        nil,
        nil,
-       (10...13),
-       "Foo"
+       (10...13)
      ),
      ClassNode(15...29)(
        [],
@@ -18,8 +17,7 @@ ProgramNode(0...29)(
        nil,
        nil,
        nil,
-       (26...29),
-       "Foo"
+       (26...29)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/class_definition_in_while_cond.txt b/test/snapshots/whitequark/class_definition_in_while_cond.txt
index 0af9f40e..a7bee91d 100644
--- a/test/snapshots/whitequark/class_definition_in_while_cond.txt
+++ b/test/snapshots/whitequark/class_definition_in_while_cond.txt
@@ -84,8 +84,7 @@ ProgramNode(0...197)(
               (122...123)
             )]
          ),
-         (136...139),
-         "Foo"
+         (136...139)
        ),
        StatementsNode(141...146)([BreakNode(141...146)(nil, (141...146))]),
        0
@@ -111,8 +110,7 @@ ProgramNode(0...197)(
               "tap"
             )]
          ),
-         (182...185),
-         "Foo"
+         (182...185)
        ),
        StatementsNode(187...192)([BreakNode(187...192)(nil, (187...192))]),
        0
diff --git a/test/snapshots/whitequark/class_super.txt b/test/snapshots/whitequark/class_super.txt
index 3dda8280..aa2845a1 100644
--- a/test/snapshots/whitequark/class_super.txt
+++ b/test/snapshots/whitequark/class_super.txt
@@ -8,8 +8,7 @@ ProgramNode(0...20)(
        (10...11),
        ConstantReadNode(12...15)(),
        nil,
-       (17...20),
-       "Foo"
+       (17...20)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/class_super_label.txt b/test/snapshots/whitequark/class_super_label.txt
index 17e92e16..ae6759c1 100644
--- a/test/snapshots/whitequark/class_super_label.txt
+++ b/test/snapshots/whitequark/class_super_label.txt
@@ -20,8 +20,7 @@ ProgramNode(0...20)(
          "a"
        ),
        nil,
-       (17...20),
-       "Foo"
+       (17...20)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/cpath.txt b/test/snapshots/whitequark/cpath.txt
index 2f838711..94714a1a 100644
--- a/test/snapshots/whitequark/cpath.txt
+++ b/test/snapshots/whitequark/cpath.txt
@@ -6,8 +6,7 @@ ProgramNode(0...39)(
        (0...6),
        ConstantPathNode(7...12)(nil, ConstantReadNode(9...12)(), (7...9)),
        nil,
-       (14...17),
-       "Foo"
+       (14...17)
      ),
      ModuleNode(19...39)(
        [],
@@ -18,8 +17,7 @@ ProgramNode(0...39)(
          (29...31)
        ),
        nil,
-       (36...39),
-       "Foo"
+       (36...39)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/if_while_after_class__since_32.txt b/test/snapshots/whitequark/if_while_after_class__since_32.txt
index 2096097f..77f26487 100644
--- a/test/snapshots/whitequark/if_while_after_class__since_32.txt
+++ b/test/snapshots/whitequark/if_while_after_class__since_32.txt
@@ -18,8 +18,7 @@ ProgramNode(0...178)(
        nil,
        nil,
        nil,
-       (35...38),
-       "Kernel"
+       (35...38)
      ),
      ClassNode(40...87)(
        [],
@@ -42,8 +41,7 @@ ProgramNode(0...178)(
        nil,
        nil,
        nil,
-       (84...87),
-       "Kernel"
+       (84...87)
      ),
      ModuleNode(89...128)(
        [],
@@ -60,8 +58,7 @@ ProgramNode(0...178)(
          (115...117)
        ),
        nil,
-       (125...128),
-       "Kernel"
+       (125...128)
      ),
      ModuleNode(130...178)(
        [],
@@ -82,8 +79,7 @@ ProgramNode(0...178)(
          (165...167)
        ),
        nil,
-       (175...178),
-       "Kernel"
+       (175...178)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/module.txt b/test/snapshots/whitequark/module.txt
index 1695fb8f..54fccb1f 100644
--- a/test/snapshots/whitequark/module.txt
+++ b/test/snapshots/whitequark/module.txt
@@ -6,8 +6,7 @@ ProgramNode(0...15)(
        (0...6),
        ConstantReadNode(7...10)(),
        nil,
-       (12...15),
-       "Foo"
+       (12...15)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/numparam_outside_block.txt b/test/snapshots/whitequark/numparam_outside_block.txt
index ac120e81..99cb79b9 100644
--- a/test/snapshots/whitequark/numparam_outside_block.txt
+++ b/test/snapshots/whitequark/numparam_outside_block.txt
@@ -21,8 +21,7 @@ ProgramNode(0...83)(
        StatementsNode(36...38)(
          [CallNode(36...38)(nil, nil, (36...38), nil, nil, nil, nil, 2, "_1")]
        ),
-       (40...43),
-       "A"
+       (40...43)
      ),
      DefNode(45...64)(
        (54...55),
@@ -46,8 +45,7 @@ ProgramNode(0...83)(
        StatementsNode(76...78)(
          [CallNode(76...78)(nil, nil, (76...78), nil, nil, nil, nil, 2, "_1")]
        ),
-       (80...83),
-       "A"
+       (80...83)
      )]
   )
 )
diff --git a/test/snapshots/whitequark/parser_bug_490.txt b/test/snapshots/whitequark/parser_bug_490.txt
index 8ea556d9..6f4c3a84 100644
--- a/test/snapshots/whitequark/parser_bug_490.txt
+++ b/test/snapshots/whitequark/parser_bug_490.txt
@@ -47,8 +47,7 @@ ProgramNode(0...132)(
                  nil,
                  nil,
                  nil,
-                 (72...75),
-                 "C"
+                 (72...75)
                )]
             ),
             (77...80)
@@ -78,8 +77,7 @@ ProgramNode(0...132)(
                  (109...115),
                  ConstantReadNode(116...117)(),
                  nil,
-                 (119...122),
-                 "M"
+                 (119...122)
                )]
             ),
             (124...127)
diff --git a/test/snapshots/whitequark/parser_bug_518.txt b/test/snapshots/whitequark/parser_bug_518.txt
index bee652b2..4de48dad 100644
--- a/test/snapshots/whitequark/parser_bug_518.txt
+++ b/test/snapshots/whitequark/parser_bug_518.txt
@@ -8,8 +8,7 @@ ProgramNode(0...15)(
        (8...9),
        ConstantReadNode(10...11)(),
        nil,
-       (12...15),
-       "A"
+       (12...15)
      )]
   )
 )
diff --git a/test/snapshots/wrapping_heredoc.txt b/test/snapshots/wrapping_heredoc.txt
deleted file mode 100644
index 674db56e..00000000
--- a/test/snapshots/wrapping_heredoc.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-ProgramNode(165...298)(
-  [],
-  StatementsNode(165...298)(
-    [CallNode(165...193)(
-       nil,
-       nil,
-       (165...167),
-       nil,
-       ArgumentsNode(168...193)(
-         [CallNode(168...193)(
-            InterpolatedStringNode(168...172)(
-              (168...172),
-              [StringNode(182...184)(nil, (182...184), nil, "a\n")],
-              (184...186)
-            ),
-            (172...173),
-            (173...177),
-            (177...178),
-            ArgumentsNode(178...192)(
-              [InterpolatedRegularExpressionNode(178...188)(
-                 (178...179),
-                 [StringNode(179...182)(nil, (179...182), nil, "b"),
-                  StringNode(186...187)(nil, (186...187), nil, "c")],
-                 (187...188),
-                 0
-               ),
-               StringNode(190...192)(
-                 (190...191),
-                 (191...191),
-                 (191...192),
-                 ""
-               )]
-            ),
-            (192...193),
-            nil,
-            0,
-            "gsub"
-          )]
-       ),
-       nil,
-       nil,
-       0,
-       "pp"
-     ),
-     CallNode(278...298)(
-       nil,
-       nil,
-       (278...280),
-       nil,
-       ArgumentsNode(281...298)(
-         [CallNode(281...298)(
-            InterpolatedStringNode(281...285)(
-              (281...285),
-              [StringNode(292...294)(nil, (292...294), nil, "d\n")],
-              (294...296)
-            ),
-            nil,
-            (286...287),
-            nil,
-            ArgumentsNode(288...298)(
-              [InterpolatedStringNode(288...298)(
-                 (288...289),
-                 [StringNode(289...292)(nil, (289...292), nil, "e"),
-                  StringNode(296...297)(nil, (296...297), nil, "f")],
-                 (297...298)
-               )]
-            ),
-            nil,
-            nil,
-            0,
-            "+"
-          )]
-       ),
-       nil,
-       nil,
-       0,
-       "pp"
-     )]
-  )
-)