Skip to content

Commit 420a634

Browse files
committed
[ruby/prism] Small fixes for the parser translator
ruby/prism@4327051c86
1 parent 8f9d999 commit 420a634

File tree

2 files changed

+96
-93
lines changed

2 files changed

+96
-93
lines changed

lib/prism/translation/parser.rb

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def initialize(message, location)
2626
Racc_debug_parser = false # :nodoc:
2727

2828
def version # :nodoc:
29-
33
29+
34
3030
end
3131

3232
# The default encoding for Ruby files is UTF-8.
@@ -42,9 +42,10 @@ def parse(source_buffer)
4242
@source_buffer = source_buffer
4343
source = source_buffer.source
4444

45-
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
45+
offset_cache = build_offset_cache(source)
46+
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
4647

47-
build_ast(result.value, build_offset_cache(source))
48+
build_ast(result.value, offset_cache)
4849
ensure
4950
@source_buffer = nil
5051
end
@@ -55,7 +56,7 @@ def parse_with_comments(source_buffer)
5556
source = source_buffer.source
5657

5758
offset_cache = build_offset_cache(source)
58-
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
59+
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
5960

6061
[
6162
build_ast(result.value, offset_cache),
@@ -72,7 +73,7 @@ def tokenize(source_buffer, _recover = false)
7273
source = source_buffer.source
7374

7475
offset_cache = build_offset_cache(source)
75-
result = unwrap(Prism.parse_lex(source, filepath: source_buffer.name))
76+
result = unwrap(Prism.parse_lex(source, filepath: source_buffer.name), offset_cache)
7677

7778
program, tokens = result.value
7879

@@ -93,16 +94,23 @@ def try_declare_numparam(node)
9394

9495
private
9596

97+
# This is a hook to allow consumers to disable some errors if they don't
98+
# want them to block creating the syntax tree.
99+
def valid_error?(error)
100+
true
101+
end
102+
96103
# If there was a error generated during the parse, then raise an
97104
# appropriate syntax error. Otherwise return the result.
98-
def unwrap(result)
99-
return result if result.success?
105+
def unwrap(result, offset_cache)
106+
result.errors.each do |error|
107+
next unless valid_error?(error)
100108

101-
error = result.errors.first
102-
offset_cache = build_offset_cache(source_buffer.source)
109+
location = build_range(error.location, offset_cache)
110+
diagnostics.process(Diagnostic.new(error.message, location))
111+
end
103112

104-
diagnostic = Diagnostic.new(error.message, build_range(error.location, offset_cache))
105-
raise ::Parser::SyntaxError, diagnostic
113+
result
106114
end
107115

108116
# Prism deals with offsets in bytes, while the parser gem deals with

lib/prism/translation/parser/compiler.rb

Lines changed: 77 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -241,53 +241,51 @@ def visit_call_node(node)
241241
block = nil
242242
end
243243

244+
if node.call_operator_loc.nil?
245+
case name
246+
when :!
247+
return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block)
248+
when :[]
249+
return visit_block(builder.index(visit(node.receiver), token(node.opening_loc), visit_all(arguments), token(node.closing_loc)), block)
250+
when :[]=
251+
if node.message != "[]=" && node.arguments && block.nil? && !node.safe_navigation?
252+
return visit_block(
253+
builder.assign(
254+
builder.index_asgn(
255+
visit(node.receiver),
256+
token(node.opening_loc),
257+
visit_all(node.arguments.arguments[...-1]),
258+
token(node.closing_loc),
259+
),
260+
srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, ["="]),
261+
visit(node.arguments.arguments.last)
262+
),
263+
block
264+
)
265+
end
266+
end
267+
end
268+
269+
message_loc = node.message_loc
270+
call_operator_loc = node.call_operator_loc
271+
call_operator = [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)] if call_operator_loc
272+
244273
visit_block(
245-
if name == :!
246-
builder.not_op(
247-
token(node.message_loc),
248-
token(node.opening_loc),
249-
visit(node.receiver),
250-
token(node.closing_loc)
274+
if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
275+
builder.assign(
276+
builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
277+
srange_find(message_loc.end_offset, node.arguments.location.start_offset, ["="]),
278+
visit(node.arguments.arguments.last)
251279
)
252-
elsif name == :[]
253-
builder.index(
280+
else
281+
builder.call_method(
254282
visit(node.receiver),
283+
call_operator,
284+
message_loc ? [node.name, srange(message_loc)] : nil,
255285
token(node.opening_loc),
256286
visit_all(arguments),
257287
token(node.closing_loc)
258288
)
259-
elsif name == :[]= && node.message != "[]=" && node.arguments && block.nil?
260-
builder.assign(
261-
builder.index_asgn(
262-
visit(node.receiver),
263-
token(node.opening_loc),
264-
visit_all(node.arguments.arguments[...-1]),
265-
token(node.closing_loc),
266-
),
267-
srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, ["="]),
268-
visit(node.arguments.arguments.last)
269-
)
270-
else
271-
message_loc = node.message_loc
272-
call_operator_loc = node.call_operator_loc
273-
call_operator = [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)] if call_operator_loc
274-
275-
if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
276-
builder.assign(
277-
builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
278-
srange_find(message_loc.end_offset, node.arguments.location.start_offset, ["="]),
279-
visit(node.arguments.arguments.last)
280-
)
281-
else
282-
builder.call_method(
283-
visit(node.receiver),
284-
call_operator,
285-
message_loc ? [node.name, srange(message_loc)] : nil,
286-
token(node.opening_loc),
287-
visit_all(arguments),
288-
token(node.closing_loc)
289-
)
290-
end
291289
end,
292290
block
293291
)
@@ -519,8 +517,6 @@ def visit_constant_path_target_node(node)
519517
# def self.foo; end
520518
# ^^^^^^^^^^^^^^^^^
521519
def visit_def_node(node)
522-
forwarding = find_forwarding(node.parameters)
523-
524520
if node.equal_loc
525521
if node.receiver
526522
builder.def_endless_singleton(
@@ -530,15 +526,15 @@ def visit_def_node(node)
530526
token(node.name_loc),
531527
builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
532528
token(node.equal_loc),
533-
node.body&.accept(copy_compiler(forwarding: forwarding))
529+
node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters)))
534530
)
535531
else
536532
builder.def_endless_method(
537533
token(node.def_keyword_loc),
538534
token(node.name_loc),
539535
builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
540536
token(node.equal_loc),
541-
node.body&.accept(copy_compiler(forwarding: forwarding))
537+
node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters)))
542538
)
543539
end
544540
elsif node.receiver
@@ -548,15 +544,15 @@ def visit_def_node(node)
548544
token(node.operator_loc),
549545
token(node.name_loc),
550546
builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
551-
node.body&.accept(copy_compiler(forwarding: forwarding)),
547+
node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))),
552548
token(node.end_keyword_loc)
553549
)
554550
else
555551
builder.def_method(
556552
token(node.def_keyword_loc),
557553
token(node.name_loc),
558554
builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false),
559-
node.body&.accept(copy_compiler(forwarding: forwarding)),
555+
node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))),
560556
token(node.end_keyword_loc)
561557
)
562558
end
@@ -993,24 +989,24 @@ def visit_keyword_rest_parameter_node(node)
993989

994990
# -> {}
995991
def visit_lambda_node(node)
992+
parameters = node.parameters
993+
996994
builder.block(
997995
builder.call_lambda(token(node.operator_loc)),
998996
[node.opening, srange(node.opening_loc)],
999-
if node.parameters
1000-
if node.parameters.is_a?(NumberedParametersNode)
1001-
visit(node.parameters)
1002-
else
1003-
builder.args(
1004-
token(node.parameters.opening_loc),
1005-
visit(node.parameters),
1006-
token(node.parameters.closing_loc),
1007-
false
1008-
)
1009-
end
1010-
else
997+
if parameters.nil?
1011998
builder.args(nil, [], nil, false)
999+
elsif node.parameters.is_a?(NumberedParametersNode)
1000+
visit(node.parameters)
1001+
else
1002+
builder.args(
1003+
token(node.parameters.opening_loc),
1004+
visit(node.parameters),
1005+
token(node.parameters.closing_loc),
1006+
false
1007+
)
10121008
end,
1013-
node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters&.parameters))),
1009+
node.body&.accept(copy_compiler(forwarding: parameters.is_a?(NumberedParametersNode) ? [] : find_forwarding(parameters&.parameters))),
10141010
[node.closing, srange(node.closing_loc)]
10151011
)
10161012
end
@@ -1096,7 +1092,7 @@ def visit_match_write_node(node)
10961092
# case of a syntax error. The parser gem doesn't have such a concept, so
10971093
# we invent our own here.
10981094
def visit_missing_node(node)
1099-
raise CompilationError, "Cannot compile missing nodes"
1095+
::AST::Node.new(:missing, [], location: ::Parser::Source::Map.new(srange(node.location)))
11001096
end
11011097

11021098
# module Foo; end
@@ -1727,29 +1723,29 @@ def token(location)
17271723
# Visit a block node on a call.
17281724
def visit_block(call, block)
17291725
if block
1726+
parameters = block.parameters
1727+
17301728
builder.block(
17311729
call,
17321730
token(block.opening_loc),
1733-
if (parameters = block.parameters)
1734-
if parameters.is_a?(NumberedParametersNode)
1735-
visit(parameters)
1736-
else
1737-
builder.args(
1738-
token(parameters.opening_loc),
1739-
if procarg0?(parameters.parameters)
1740-
parameter = parameters.parameters.requireds.first
1741-
[builder.procarg0(visit(parameter))].concat(visit_all(parameters.locals))
1742-
else
1743-
visit(parameters)
1744-
end,
1745-
token(parameters.closing_loc),
1746-
false
1747-
)
1748-
end
1749-
else
1731+
if parameters.nil?
17501732
builder.args(nil, [], nil, false)
1733+
elsif parameters.is_a?(NumberedParametersNode)
1734+
visit(parameters)
1735+
else
1736+
builder.args(
1737+
token(parameters.opening_loc),
1738+
if procarg0?(parameters.parameters)
1739+
parameter = parameters.parameters.requireds.first
1740+
[builder.procarg0(visit(parameter))].concat(visit_all(parameters.locals))
1741+
else
1742+
visit(parameters)
1743+
end,
1744+
token(parameters.closing_loc),
1745+
false
1746+
)
17511747
end,
1752-
block.body&.accept(copy_compiler(forwarding: find_forwarding(block.parameters&.parameters))),
1748+
block.body&.accept(copy_compiler(forwarding: parameters.is_a?(NumberedParametersNode) ? [] : find_forwarding(parameters&.parameters))),
17531749
token(block.closing_loc)
17541750
)
17551751
else
@@ -1762,9 +1758,9 @@ def visit_heredoc(node)
17621758
children = []
17631759
node.parts.each do |part|
17641760
pushing =
1765-
if part.is_a?(StringNode) && part.unescaped.count("\n") > 1
1766-
unescaped = part.unescaped.split("\n")
1767-
escaped = part.content.split("\n")
1761+
if part.is_a?(StringNode) && part.unescaped.include?("\n")
1762+
unescaped = part.unescaped.lines(chomp: true)
1763+
escaped = part.content.lines(chomp: true)
17681764

17691765
escaped_lengths =
17701766
if node.opening.end_with?("'")
@@ -1779,7 +1775,6 @@ def visit_heredoc(node)
17791775
unescaped.zip(escaped_lengths).map do |unescaped_line, escaped_length|
17801776
end_offset = start_offset + (escaped_length || 0)
17811777
inner_part = builder.string_internal(["#{unescaped_line}\n", srange_offsets(start_offset, end_offset)])
1782-
17831778
start_offset = end_offset
17841779
inner_part
17851780
end

0 commit comments

Comments
 (0)