Skip to content

Commit 4e70793

Browse files
fix: %w list spanning a heredoc
Two fixes were necessary: - ensure we are handling newlines correctly - accept two consecutive string tokens without a separator Co-authored-by: Kevin Newton <kddnewton@gmail.com>
1 parent c148d95 commit 4e70793

File tree

4 files changed

+48
-12
lines changed

4 files changed

+48
-12
lines changed

src/yarp.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6942,9 +6942,19 @@ parser_lex(yp_parser_t *parser) {
69426942
yp_unescape_type_t unescape_type = lex_mode->as.list.interpolation ? YP_UNESCAPE_ALL : YP_UNESCAPE_MINIMAL;
69436943
size_t difference = yp_unescape_calculate_difference(parser, breakpoint, unescape_type, false);
69446944

6945-
// If the result is an escaped newline, then we need to
6946-
// track that newline.
6947-
yp_newline_list_check_append(&parser->newline_list, breakpoint + difference - 1);
6945+
// If the result is an escaped newline ...
6946+
if (*(breakpoint + difference - 1) == '\n') {
6947+
if (parser->heredoc_end) {
6948+
// ... if we are on the same line as a heredoc, flush the heredoc and
6949+
// continue parsing after heredoc_end.
6950+
parser->current.end = breakpoint + difference;
6951+
parser_flush_heredoc_end(parser);
6952+
LEX(YP_TOKEN_STRING_CONTENT);
6953+
} else {
6954+
// ... else track the newline.
6955+
yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1);
6956+
}
6957+
}
69486958

69496959
breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
69506960
continue;
@@ -12098,12 +12108,9 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
1209812108
accept(parser, YP_TOKEN_WORDS_SEP);
1209912109

1210012110
while (!match_any_type_p(parser, 2, YP_TOKEN_STRING_END, YP_TOKEN_EOF)) {
12101-
if (yp_array_node_size(array) == 0) {
12102-
accept(parser, YP_TOKEN_WORDS_SEP);
12103-
} else {
12104-
expect(parser, YP_TOKEN_WORDS_SEP, "Expected a separator for the strings in a `%w` list.");
12105-
if (match_type_p(parser, YP_TOKEN_STRING_END)) break;
12106-
}
12111+
accept(parser, YP_TOKEN_WORDS_SEP);
12112+
if (match_type_p(parser, YP_TOKEN_STRING_END)) break;
12113+
1210712114
expect(parser, YP_TOKEN_STRING_CONTENT, "Expected a string in a `%w` list.");
1210812115

1210912116
yp_token_t opening = not_provided(parser);

test/yarp/fixtures/spanning_heredoc.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,9 @@ pp <<-A, %Q[h\
2323
g
2424
A
2525
h]
26+
27+
# ripper can't parse this successfully, though ruby runs it correctly
28+
pp <<-A, %w[j\
29+
i
30+
A
31+
j]

test/yarp/parse_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def test_parse_lex_file
7777
# into a single token. See https://bugs.ruby-lang.org/issues/19838.
7878
#
7979
# Additionally, Ripper cannot parse the %w[] fixture in this file, so set ripper_should_parse to false.
80-
ripper_should_match = false if relative == "spanning_heredoc.txt"
80+
ripper_should_parse = false if relative == "spanning_heredoc.txt"
8181

8282
define_method "test_filepath_#{relative}" do
8383
# First, read the source from the filepath. Use binmode to avoid converting CRLF on Windows,

test/yarp/snapshots/spanning_heredoc.txt

Lines changed: 25 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)