Skip to content

Commit 115d58f

Browse files
committed
Revert "Split up newline token"
This reverts commit 3dbe592.
1 parent 3dbe592 commit 115d58f

6 files changed

Lines changed: 48 additions & 68 deletions

File tree

config.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,6 @@ tokens:
359359
comment: "when"
360360
- name: NEWLINE
361361
comment: "a newline character outside of other tokens"
362-
- name: NEWLINE_TERMINATOR
363-
comment: "a newline that terminates a construct where a newline is otherwise insignificant"
364362
- name: PARENTHESIS_RIGHT
365363
comment: ")"
366364
- name: PIPE

lib/prism/lex_compat.rb

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ def deconstruct_keys(keys) # :nodoc:
191191
MINUS_EQUAL: :on_op,
192192
MINUS_GREATER: :on_tlambda,
193193
NEWLINE: :on_nl,
194-
NEWLINE_TERMINATOR: :on_ignored_nl,
195194
NUMBERED_REFERENCE: :on_backref,
196195
PARENTHESIS_LEFT: :on_lparen,
197196
PARENTHESIS_LEFT_GROUPING: :on_lparen,
@@ -618,9 +617,6 @@ def result
618617

619618
bom = source.slice(0, 3) == "\xEF\xBB\xBF"
620619

621-
last_comment_token = nil #: lex_compat_token?
622-
last_comment_end = nil #: Integer?
623-
624620
result_value.each_with_index do |(prism_token, prism_state), index|
625621
lineno = prism_token.location.start_line
626622
column = prism_token.location.start_column
@@ -629,16 +625,6 @@ def result
629625
value = prism_token.value
630626
lex_state = Translation::Ripper::Lexer::State[prism_state]
631627

632-
# A comment token does not include its terminating newline, but
633-
# ripper's comment value does, so the newline token that directly
634-
# follows a comment is folded back into it.
635-
if last_comment_token && last_comment_end == prism_token.location.start_offset && (event == :on_nl || event == :on_ignored_nl)
636-
last_comment_token[2] += value
637-
last_comment_token = nil
638-
last_comment_end = nil
639-
next
640-
end
641-
642628
# If there's a UTF-8 byte-order mark as the start of the file, then for
643629
# certain tokens ripper sets the first token back by 3 bytes. It also
644630
# keeps the byte order mark in the first token's value. This is weird,
@@ -728,16 +714,11 @@ def result
728714
eof_token = prism_token
729715
previous_token = result_value[index - 1][0]
730716

731-
# A newline that was folded back into a comment still marks the
732-
# comment boundary for the check below.
733-
comment_boundary = previous_token.type == :COMMENT ||
734-
(index >= 2 && %i[NEWLINE NEWLINE_TERMINATOR IGNORED_NEWLINE].include?(previous_token.type) && result_value[index - 2][0].type == :COMMENT && result_value[index - 2][0].location.end_offset == previous_token.location.start_offset)
735-
736717
# If we're at the end of the file and the previous token was a
737718
# comment and there is still whitespace after the comment, then
738719
# Ripper will append a on_nl token (even though there isn't
739720
# necessarily a newline). We mirror that here.
740-
if comment_boundary
721+
if previous_token.type == :COMMENT
741722
# If the comment is at the start of a heredoc: <<HEREDOC # comment
742723
# then the comment's end_offset is up near the heredoc_beg.
743724
# This is not the correct offset to use for figuring out if
@@ -764,11 +745,6 @@ def result
764745

765746
previous_state = lex_state
766747

767-
if event == :on_comment
768-
last_comment_token = lex_compat_token
769-
last_comment_end = prism_token.location.end_offset
770-
end
771-
772748
# The order in which tokens appear in our lexer is different from the
773749
# order that they appear in Ripper. When we hit the declaration of a
774750
# heredoc in prism, we skip forward and lex the rest of the content of

lib/prism/translation/parser/lexer.rb

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ class Lexer # :nodoc:
141141
MINUS_EQUAL: :tOP_ASGN,
142142
MINUS_GREATER: :tLAMBDA,
143143
NEWLINE: :tNL,
144-
NEWLINE_TERMINATOR: :tNL,
145144
NUMBERED_REFERENCE: :tNTH_REF,
146145
PARENTHESIS_LEFT: :tLPAREN2,
147146
PARENTHESIS_LEFT_GROUPING: :tLPAREN,
@@ -188,6 +187,11 @@ class Lexer # :nodoc:
188187
XSTRING_BEGIN: :tXSTRING_BEG
189188
}
190189

190+
# Types of tokens that are allowed to continue a method call with comments in-between.
191+
# For these, the parser gem doesn't emit a newline token after the last comment.
192+
COMMENT_CONTINUATION_TYPES = Set.new([:COMMENT, :AMPERSAND_DOT, :DOT])
193+
private_constant :COMMENT_CONTINUATION_TYPES
194+
191195
# Heredocs are complex and require us to keep track of a bit of info to refer to later
192196
HeredocData = Struct.new(:identifier, :common_whitespace, keyword_init: true)
193197

@@ -238,13 +242,6 @@ def to_a
238242
value = token.value
239243
location = range(token.location.start_offset, token.location.end_offset)
240244

241-
# A newline deferred past a run of comments is emitted before the
242-
# token that follows the last comment.
243-
if comment_newline_location && type != :tCOMMENT
244-
tokens << [:tNL, [nil, comment_newline_location]]
245-
comment_newline_location = nil
246-
end
247-
248245
case type
249246
when :tCHARACTER
250247
value.delete_prefix!("?")
@@ -262,9 +259,27 @@ def to_a
262259
location = range(token.location.start_offset, next_token.location.end_offset)
263260
index += 1
264261
else
265-
# A carriage return before the terminating newline is part of
266-
# the comment token but not of the comment's value.
267-
location = range(token.location.start_offset, token.location.end_offset - 1) if value.chomp!
262+
is_at_eol = value.chomp!.nil?
263+
location = range(token.location.start_offset, token.location.end_offset + (is_at_eol ? 0 : -1))
264+
265+
prev_token, _ = lexed[index - 2] if index - 2 >= 0
266+
next_token, _ = lexed[index]
267+
268+
is_inline_comment = prev_token&.location&.start_line == token.location.start_line
269+
if is_inline_comment && !is_at_eol && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type)
270+
tokens << [:tCOMMENT, [value, location]]
271+
272+
nl_location = range(token.location.end_offset - 1, token.location.end_offset)
273+
tokens << [:tNL, [nil, nl_location]]
274+
next
275+
elsif is_inline_comment && next_token&.type == :COMMENT
276+
comment_newline_location = range(token.location.end_offset - 1, token.location.end_offset)
277+
elsif comment_newline_location && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type)
278+
tokens << [:tCOMMENT, [value, location]]
279+
tokens << [:tNL, [nil, comment_newline_location]]
280+
comment_newline_location = nil
281+
next
282+
end
268283
end
269284
when :tNL
270285
next_token, _ = lexed[index]
@@ -486,10 +501,6 @@ def to_a
486501
end
487502
end
488503

489-
if comment_newline_location
490-
tokens << [:tNL, [nil, comment_newline_location]]
491-
end
492-
493504
tokens
494505
end
495506

src/prism.c

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10212,6 +10212,7 @@ parser_lex(pm_parser_t *parser) {
1021210212
pm_comment_t *comment = parser_comment(parser, PM_COMMENT_INLINE);
1021310213
pm_list_append(&parser->comment_list, (pm_list_node_t *) comment);
1021410214

10215+
if (ending) parser->current.end++;
1021510216
parser->current.type = PM_TOKEN_COMMENT;
1021610217
parser_lex_callback(parser);
1021710218

@@ -10229,16 +10230,7 @@ parser_lex(pm_parser_t *parser) {
1022910230
}
1023010231
}
1023110232

10232-
/* The comment does not include its terminating newline,
10233-
* which lexes through the newline handling below as its
10234-
* own token. A comment that ends the file has no newline,
10235-
* so the newline handling runs without one to emit. */
10236-
if (ending == NULL) {
10237-
lexed_comment = true;
10238-
} else {
10239-
parser->current.start = ending;
10240-
parser->current.end = ending + 1;
10241-
}
10233+
lexed_comment = true;
1024210234
}
1024310235
PRISM_FALLTHROUGH
1024410236
case '\r':
@@ -10276,11 +10268,7 @@ parser_lex(pm_parser_t *parser) {
1027610268
break;
1027710269
case PM_IGNORED_NEWLINE_PATTERN:
1027810270
if (parser->pattern_matching_newlines || parser->in_keyword_arg) {
10279-
if (!lexed_comment) {
10280-
parser->current.type = PM_TOKEN_NEWLINE_TERMINATOR;
10281-
parser_lex_callback(parser);
10282-
}
10283-
10271+
if (!lexed_comment) parser_lex_ignored_newline(parser);
1028410272
lex_state_set(parser, PM_LEX_STATE_BEG);
1028510273
parser->command_start = true;
1028610274
parser->current.type = PM_TOKEN_NEWLINE;
@@ -10377,15 +10365,11 @@ parser_lex(pm_parser_t *parser) {
1037710365
// If we hit a . after a newline, then we're in a call chain and
1037810366
// we need to return the call operator.
1037910367
if (next_content[0] == '.') {
10380-
/* A beginless range on the next line means this
10381-
* newline terminates the statement rather than
10382-
* continuing a method chain. */
10368+
// To match ripper, we need to emit an ignored newline even though
10369+
// it's a real newline in the case that we have a beginless range
10370+
// on a subsequent line.
1038310371
if (peek_at(parser, next_content + 1) == '.') {
10384-
if (!lexed_comment) {
10385-
parser->current.type = PM_TOKEN_NEWLINE_TERMINATOR;
10386-
parser_lex_callback(parser);
10387-
}
10388-
10372+
if (!lexed_comment) parser_lex_ignored_newline(parser);
1038910373
lex_state_set(parser, PM_LEX_STATE_BEG);
1039010374
parser->command_start = true;
1039110375
parser->current.type = PM_TOKEN_NEWLINE;

templates/src/tokens.c.erb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,6 @@ pm_token_str(pm_token_type_t token_type) {
275275
return "'->'";
276276
case PM_TOKEN_NEWLINE:
277277
return "newline";
278-
case PM_TOKEN_NEWLINE_TERMINATOR:
279-
return "newline";
280278
case PM_TOKEN_NUMBERED_REFERENCE:
281279
return "numbered reference";
282280
case PM_TOKEN_PARENTHESIS_LEFT:

test/prism/ruby/parser_test.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,26 @@ class ParserTest < TestCase
109109
# These files are failing to translate their lexer output into the lexer
110110
# output expected by the parser gem, so we'll skip them for now.
111111
skip_tokens = [
112+
"dash_heredocs.txt",
112113
"embdoc_no_newline_at_end.txt",
114+
"seattlerb/case_in.txt",
115+
"seattlerb/difficult4__leading_dots2.txt",
113116
"seattlerb/heredoc_unicode.txt",
114117
"seattlerb/parse_line_heredoc.txt",
115118
"seattlerb/pct_w_heredoc_interp_nested.txt",
119+
"seattlerb/required_kwarg_no_value.txt",
120+
"seattlerb/TestRubyParserShared.txt",
116121
"unparser/corpus/literal/assignment.txt",
117122
"unparser/corpus/literal/literal.txt",
118-
"whitequark/forward_arg_with_open_args.txt"
123+
"whitequark/args.txt",
124+
"whitequark/beginless_erange_after_newline.txt",
125+
"whitequark/beginless_irange_after_newline.txt",
126+
"whitequark/forward_arg_with_open_args.txt",
127+
"whitequark/kwarg_no_paren.txt",
128+
"whitequark/multiple_pattern_matches.txt",
129+
"whitequark/newline_in_hash_argument.txt",
130+
"whitequark/pattern_matching_hash.txt",
131+
"whitequark/ruby_bug_9669.txt"
119132
]
120133

121134
Fixture.each_for_version(except: skip_syntax_error, version: "3.3") do |fixture|

0 commit comments

Comments
 (0)