summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-02-23 22:21:10 -0500
committergit <svn-admin@ruby-lang.org>2024-02-24 03:39:29 +0000
commit804b2a3787e17ccc4537b4c525d4f81adc27ab7c (patch)
tree8f18f8aeae5e0027b69f8616186fe225d4035247
parentaa8841405bd48ac61b3c1397dd864ed2db3b3b2a (diff)
[ruby/prism] Rebase against main
https://github.com/ruby/prism/commit/813e20d449
-rw-r--r--lib/prism/parse_result.rb2
-rw-r--r--lib/prism/ripper_compat.rb208
2 files changed, 1 insertions, 209 deletions
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index af4006d683..102567f59c 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -67,7 +67,7 @@ module Prism
# concept of code units that differs from the number of characters in other
# encodings, it is not captured here.
def code_units_offset(byte_offset, encoding)
- byteslice = source.byteslice(0, byte_offset).encode(encoding)
+ byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding)
(encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length
end
diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb
deleted file mode 100644
index 51b4339426..0000000000
--- a/lib/prism/ripper_compat.rb
+++ /dev/null
@@ -1,208 +0,0 @@
-# frozen_string_literal: true
-
-require "ripper"
-
-module Prism
- # Note: This integration is not finished, and therefore still has many
- # inconsistencies with Ripper. If you'd like to help out, pull requests would
- # be greatly appreciated!
- #
- # This class is meant to provide a compatibility layer between prism and
- # Ripper. It functions by parsing the entire tree first and then walking it
- # and executing each of the Ripper callbacks as it goes.
- #
- # This class is going to necessarily be slower than the native Ripper API. It
- # is meant as a stopgap until developers migrate to using prism. It is also
- # meant as a test harness for the prism parser.
- #
- # To use this class, you treat `Prism::RipperCompat` effectively as you would
- # treat the `Ripper` class.
- class RipperCompat < Visitor
- # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that
- # returns the arrays of [type, *children].
- class SexpBuilder < RipperCompat
- private
-
- Ripper::PARSER_EVENTS.each do |event|
- define_method(:"on_#{event}") do |*args|
- [event, *args]
- end
- end
-
- Ripper::SCANNER_EVENTS.each do |event|
- define_method(:"on_#{event}") do |value|
- [:"@#{event}", value, [lineno, column]]
- end
- end
- end
-
- # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that
- # returns the same values as ::Ripper::SexpBuilder except with a couple of
- # niceties that flatten linked lists into arrays.
- class SexpBuilderPP < SexpBuilder
- private
-
- def _dispatch_event_new # :nodoc:
- []
- end
-
- def _dispatch_event_push(list, item) # :nodoc:
- list << item
- list
- end
-
- Ripper::PARSER_EVENT_TABLE.each do |event, arity|
- case event
- when /_new\z/
- alias_method :"on_#{event}", :_dispatch_event_new if arity == 0
- when /_add\z/
- alias_method :"on_#{event}", :_dispatch_event_push
- end
- end
- end
-
- # The source that is being parsed.
- attr_reader :source
-
- # The current line number of the parser.
- attr_reader :lineno
-
- # The current column number of the parser.
- attr_reader :column
-
- # Create a new RipperCompat object with the given source.
- def initialize(source)
- @source = source
- @result = nil
- @lineno = nil
- @column = nil
- end
-
- ############################################################################
- # Public interface
- ############################################################################
-
- # True if the parser encountered an error during parsing.
- def error?
- result.failure?
- end
-
- # Parse the source and return the result.
- def parse
- result.magic_comments.each do |magic_comment|
- on_magic_comment(magic_comment.key, magic_comment.value)
- end
-
- if error?
- result.errors.each do |error|
- on_parse_error(error.message)
- end
- else
- result.value.accept(self)
- end
- end
-
- ############################################################################
- # Visitor methods
- ############################################################################
-
- # Visit a CallNode node.
- def visit_call_node(node)
- message = node.message
- if message && !message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments && node.arguments.arguments && node.arguments.arguments.length == 1
- left = visit(node.receiver)
- right = visit(node.arguments.arguments.first)
-
- bounds(node.location)
- on_binary(left, node.name, right)
- else
- raise NotImplementedError
- end
- end
-
- # Visit a FloatNode node.
- def visit_float_node(node)
- bounds(node.location)
- on_float(node.slice)
- end
-
- # Visit a ImaginaryNode node.
- def visit_imaginary_node(node)
- bounds(node.location)
- on_imaginary(node.slice)
- end
-
- # Visit an IntegerNode node.
- def visit_integer_node(node)
- bounds(node.location)
- on_int(node.slice)
- end
-
- # Visit a RationalNode node.
- def visit_rational_node(node)
- bounds(node.location)
- on_rational(node.slice)
- end
-
- # Visit a StatementsNode node.
- def visit_statements_node(node)
- bounds(node.location)
- node.body.inject(on_stmts_new) do |stmts, stmt|
- on_stmts_add(stmts, visit(stmt))
- end
- end
-
- # Visit a ProgramNode node.
- def visit_program_node(node)
- statements = visit(node.statements)
- bounds(node.location)
- on_program(statements)
- end
-
- ############################################################################
- # Entrypoints for subclasses
- ############################################################################
-
- # This is a convenience method that runs the SexpBuilder subclass parser.
- def self.sexp_raw(source)
- SexpBuilder.new(source).parse
- end
-
- # This is a convenience method that runs the SexpBuilderPP subclass parser.
- def self.sexp(source)
- SexpBuilderPP.new(source).parse
- end
-
- private
-
- # This method is responsible for updating lineno and column information
- # to reflect the current node.
- #
- # This method could be drastically improved with some caching on the start
- # of every line, but for now it's good enough.
- def bounds(location)
- @lineno = location.start_line
- @column = location.start_column
- end
-
- # Lazily initialize the parse result.
- def result
- @result ||= Prism.parse(source)
- end
-
- def _dispatch0; end # :nodoc:
- def _dispatch1(_); end # :nodoc:
- def _dispatch2(_, _); end # :nodoc:
- def _dispatch3(_, _, _); end # :nodoc:
- def _dispatch4(_, _, _, _); end # :nodoc:
- def _dispatch5(_, _, _, _, _); end # :nodoc:
- def _dispatch7(_, _, _, _, _, _, _); end # :nodoc:
-
- alias_method :on_parse_error, :_dispatch1
- alias_method :on_magic_comment, :_dispatch2
-
- (Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity|
- alias_method :"on_#{event}", :"_dispatch#{arity}"
- end
- end
-end