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.
The source that is being parsed.
The current line number of the parser.
The current column number of the parser.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 74
def initialize(source)
@source = source
@result = nil
@lineno = nil
@column = nil
end
Create a new RipperCompat
object with the given source.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 171
def self.sexp(source)
SexpBuilderPP.new(source).parse
end
This is a convenience method that runs the SexpBuilderPP
subclass parser.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 166
def self.sexp_raw(source)
SexpBuilder.new(source).parse
end
This is a convenience method that runs the SexpBuilder
subclass parser.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 182
def bounds(location)
@lineno = location.start_line
@column = location.start_column
end
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.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 86
def error?
result.failure?
end
True if the parser encountered an error during parsing.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 91
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
Parse the source and return the result.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 188
def result
@result ||= Prism.parse(source)
end
Lazily initialize the parse result.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 110
def visit_call_node(node)
if !node.message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && 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 CallNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 123
def visit_float_node(node)
bounds(node.location)
on_float(node.slice)
end
Visit a FloatNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 129
def visit_imaginary_node(node)
bounds(node.location)
on_imaginary(node.slice)
end
Visit a ImaginaryNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 135
def visit_integer_node(node)
bounds(node.location)
on_int(node.slice)
end
Visit an IntegerNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 155
def visit_program_node(node)
statements = visit(node.statements)
bounds(node.location)
on_program(statements)
end
Visit a ProgramNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 141
def visit_rational_node(node)
bounds(node.location)
on_rational(node.slice)
end
Visit a RationalNode
node.
# File tmp/rubies/ruby-3.3.0/lib/prism/ripper_compat.rb, line 147
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 StatementsNode
node.