class Prism::RipperCompat
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.
Attributes
The current column number of the parser.
The current line number of the parser.
The source that is being parsed.
Public Class Methods
Create a new RipperCompat
object with the given source.
# File lib/prism/ripper_compat.rb, line 74 def initialize(source) @source = source @result = nil @lineno = nil @column = nil end
This is a convenience method that runs the SexpBuilderPP
subclass parser.
# File lib/prism/ripper_compat.rb, line 171 def self.sexp(source) SexpBuilderPP.new(source).parse end
This is a convenience method that runs the SexpBuilder
subclass parser.
# File lib/prism/ripper_compat.rb, line 166 def self.sexp_raw(source) SexpBuilder.new(source).parse end
Public Instance Methods
True if the parser encountered an error during parsing.
# File lib/prism/ripper_compat.rb, line 86 def error? result.failure? end
Parse the source and return the result.
# File 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
Visit a CallNode
node.
# File 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 FloatNode
node.
# File lib/prism/ripper_compat.rb, line 123 def visit_float_node(node) bounds(node.location) on_float(node.slice) end
Visit a ImaginaryNode
node.
# File lib/prism/ripper_compat.rb, line 129 def visit_imaginary_node(node) bounds(node.location) on_imaginary(node.slice) end
Visit an IntegerNode
node.
# File lib/prism/ripper_compat.rb, line 135 def visit_integer_node(node) bounds(node.location) on_int(node.slice) end
Visit a ProgramNode
node.
# File 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 RationalNode
node.
# File lib/prism/ripper_compat.rb, line 141 def visit_rational_node(node) bounds(node.location) on_rational(node.slice) end
Visit a StatementsNode
node.
# File 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
Private Instance Methods
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 lib/prism/ripper_compat.rb, line 182 def bounds(location) @lineno = location.start_line @column = location.start_column end
Lazily initialize the parse result.
# File lib/prism/ripper_compat.rb, line 188 def result @result ||= Prism.parse(source) end