class Prism::RipperCompat
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.
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 prism/ripper_compat.rb, line 67 def initialize(source) @source = source @result = nil @lineno = nil @column = nil end
This is a convenience method that runs the SexpBuilderPP
subclass parser.
# File prism/ripper_compat.rb, line 157 def self.sexp(source) SexpBuilderPP.new(source).parse end
This is a convenience method that runs the SexpBuilder
subclass parser.
# File prism/ripper_compat.rb, line 152 def self.sexp_raw(source) SexpBuilder.new(source).parse end
Public Instance Methods
True if the parser encountered an error during parsing.
# File prism/ripper_compat.rb, line 79 def error? result.errors.any? end
Parse the source and return the result.
# File prism/ripper_compat.rb, line 84 def parse result.value.accept(self) unless error? end
This method is responsible for dispatching to the correct visitor method based on the type of the node.
# File prism/ripper_compat.rb, line 94 def visit(node) node&.accept(self) end
Visit a CallNode
node.
# File prism/ripper_compat.rb, line 99 def visit_call_node(node) if !node.opening_loc && node.arguments.arguments.length == 1 bounds(node.receiver.location) left = visit(node.receiver) bounds(node.arguments.arguments.first.location) right = visit(node.arguments.arguments.first) on_binary(left, source[node.message_loc.start_offset...node.message_loc.end_offset].to_sym, right) else raise NotImplementedError end end
Visit an IntegerNode
node.
# File prism/ripper_compat.rb, line 114 def visit_integer_node(node) bounds(node.location) on_int(source[node.location.start_offset...node.location.end_offset]) end
Visit a ProgramNode
node.
# File prism/ripper_compat.rb, line 142 def visit_program_node(node) bounds(node.location) on_program(visit(node.statements)) end
Visit a StatementsNode
node.
# File prism/ripper_compat.rb, line 120 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 token found during parsing.
# File prism/ripper_compat.rb, line 128 def visit_token(node) bounds(node.location) case node.type when :MINUS on_op(node.value) when :PLUS on_op(node.value) else raise NotImplementedError, "Unknown token: #{node.type}" 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 prism/ripper_compat.rb, line 168 def bounds(location) start_offset = location.start_offset @lineno = source[0..start_offset].count("\n") + 1 @column = start_offset - (source.rindex("\n", start_offset) || 0) end
Lazily initialize the parse result.
# File prism/ripper_compat.rb, line 176 def result @result ||= Prism.parse(source) end