[ruby/prism] Raise diagnostics for parser

https://github.com/ruby/prism/commit/102b4a16f5
This commit is contained in:
Kevin Newton 2024-01-29 11:02:11 -05:00 коммит произвёл git
Родитель adf29c9a98
Коммит e050097beb
2 изменённых файлов: 49 добавлений и 17 удалений

Просмотреть файл

@ -9,6 +9,20 @@ module Prism
# the parser gem, and overrides the parse* methods to parse with prism and
# then translate.
class Parser < ::Parser::Base
# The parser gem has a list of diagnostics with a hard-coded set of error
# messages. We create our own diagnostic class in order to set our own
# error messages.
class Diagnostic < ::Parser::Diagnostic
# The message generated by prism.
attr_reader :message
# Initialize a new diagnostic with the given message and location.
def initialize(message, location)
@message = message
super(:error, :prism_error, {}, location, [])
end
end
Racc_debug_parser = false # :nodoc:
def version # :nodoc:
@ -28,10 +42,9 @@ module Prism
@source_buffer = source_buffer
source = source_buffer.source
build_ast(
Prism.parse(source, filepath: source_buffer.name).value,
build_offset_cache(source)
)
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
build_ast(result.value, build_offset_cache(source))
ensure
@source_buffer = nil
end
@ -42,7 +55,7 @@ module Prism
source = source_buffer.source
offset_cache = build_offset_cache(source)
result = Prism.parse(source, filepath: source_buffer.name)
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
[
build_ast(result.value, offset_cache),
@ -59,7 +72,8 @@ module Prism
source = source_buffer.source
offset_cache = build_offset_cache(source)
result = Prism.parse_lex(source, filepath: source_buffer.name)
result = unwrap(Prism.parse_lex(source, filepath: source_buffer.name))
program, tokens = result.value
[
@ -79,6 +93,18 @@ module Prism
private
# If there was a error generated during the parse, then raise an
# appropriate syntax error. Otherwise return the result.
def unwrap(result)
return result if result.success?
error = result.errors.first
offset_cache = build_offset_cache(source_buffer.source)
diagnostic = Diagnostic.new(error.message, build_range(error.location, offset_cache))
raise ::Parser::SyntaxError, diagnostic
end
# Prism deals with offsets in bytes, while the parser gem deals with
# offsets in characters. We need to handle this conversion in order to
# build the parser gem AST.
@ -109,15 +135,7 @@ module Prism
# Build the parser gem comments from the prism comments.
def build_comments(comments, offset_cache)
comments.map do |comment|
location = comment.location
::Parser::Source::Comment.new(
::Parser::Source::Range.new(
source_buffer,
offset_cache[location.start_offset],
offset_cache[location.end_offset]
)
)
::Parser::Source::Comment.new(build_range(comment.location, offset_cache))
end
end
@ -126,6 +144,15 @@ module Prism
Lexer.new(source_buffer, tokens.map(&:first), offset_cache).to_a
end
# Build a range from a prism location.
def build_range(location, offset_cache)
::Parser::Source::Range.new(
source_buffer,
offset_cache[location.start_offset],
offset_cache[location.end_offset]
)
end
require_relative "parser/compiler"
require_relative "parser/lexer"

Просмотреть файл

@ -83,11 +83,16 @@ module Prism
elements = [*node.requireds]
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
elements.concat(node.posts)
visited = visit_all(elements)
if node.rest.is_a?(ImplicitRestNode)
visited[-1] = builder.match_with_trailing_comma(visited[-1], token(node.rest.location))
end
if node.constant
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all(elements), nil), token(node.closing_loc))
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc))
else
builder.array_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc))
builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc))
end
end