class Prism::RipperCompat

treat the ‘Ripper` class.
To use this class, you treat `Prism::RipperCompat` effectively as you would
meant as a test harness for the prism parser.
is meant as a stopgap until developers migrate to using prism. It is also
This class is going to necessarily be slower than the native Ripper API. It
and executing each of the Ripper callbacks as it goes.
Ripper. It functions by parsing the entire tree first and then walking it
This class is meant to provide a compatibility layer between prism and
be greatly appreciated!
inconsistencies with Ripper. If you’d like to help out, pull requests would
Note: This integration is not finished, and therefore still has many

def self.sexp(source)

This is a convenience method that runs the SexpBuilderPP subclass parser.
def self.sexp(source)
  SexpBuilderPP.new(source).parse
end

def self.sexp_raw(source)

This is a convenience method that runs the SexpBuilder subclass parser.
def self.sexp_raw(source)
  SexpBuilder.new(source).parse
end

def _dispatch0; end # :nodoc:

:nodoc:
def _dispatch0; end # :nodoc:

def _dispatch1(_); end # :nodoc:

:nodoc:
:nodoc:
def _dispatch1(_); end # :nodoc:

def _dispatch2(_, _); end # :nodoc:

:nodoc:
:nodoc:
:nodoc:
def _dispatch2(_, _); end # :nodoc:

def _dispatch3(_, _, _); end # :nodoc:

:nodoc:
:nodoc:
:nodoc:
:nodoc:
def _dispatch3(_, _, _); end # :nodoc:

def _dispatch4(_, _, _, _); end # :nodoc:

:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
def _dispatch4(_, _, _, _); end # :nodoc:

def _dispatch5(_, _, _, _, _); end # :nodoc:

:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
def _dispatch5(_, _, _, _, _); end # :nodoc:

def _dispatch7(_, _, _, _, _, _, _); end # :nodoc:

:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
:nodoc:
def _dispatch7(_, _, _, _, _, _, _); end # :nodoc:

def bounds(location)

of every line, but for now it's good enough.
This method could be drastically improved with some caching on the start

to reflect the current node.
This method is responsible for updating lineno and column information
def bounds(location)
  @lineno = location.start_line
  @column = location.start_column
end

def bounds_values(lineno, column)

and column to reflect the current node.
If we need to do something unusual, we can directly update the line number
def bounds_values(lineno, column)
  @lineno = lineno
  @column = column
end

def error?

True if the parser encountered an error during parsing.
def error?
  result.failure?
end

def initialize(source)

Create a new RipperCompat object with the given source.
def initialize(source)
  @source = source
  @result = nil
  @lineno = nil
  @column = nil
end

def parse

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
    nil
  else
    result.value.accept(self)
  end
end

def result

Lazily initialize the parse result.
def result
  @result ||= Prism.parse(source)
end

def visit_array_node(node)

Visit an ArrayNode node.
def visit_array_node(node)
  elements = visit_elements(node.elements) unless node.elements.empty?
  bounds(node.location)
  on_array(elements)
end

def visit_call_node(node)

Visit a CallNode node.
def visit_call_node(node)
  if node.variable_call?
    if node.message.match?(/^[[:alpha:]_]/)
      bounds(node.message_loc)
      return on_vcall(on_ident(node.message))
    end
    raise NotImplementedError, "Non-alpha variable call"
  end
  if node.opening_loc.nil?
    left = visit(node.receiver)
    if node.arguments&.arguments&.length == 1
      right = visit(node.arguments.arguments.first)
      on_binary(left, node.name, right)
    elsif !node.arguments || node.arguments.empty?
      on_unary(node.name, left)
    else
      raise NotImplementedError, "More than two arguments for operator"
    end
  else
    raise NotImplementedError, "Non-nil opening_loc"
  end
end

def visit_elements(elements)

Visit a list of elements, like the elements of an array or arguments.
def visit_elements(elements)
  bounds(elements.first.location)
  elements.inject(on_args_new) do |args, element|
    on_args_add(args, visit(element))
  end
end

def visit_float_node(node)

Visit a FloatNode node.
def visit_float_node(node)
  visit_number(node) { |text| on_float(text) }
end

def visit_imaginary_node(node)

Visit a ImaginaryNode node.
def visit_imaginary_node(node)
  visit_number(node) { |text| on_imaginary(text) }
end

def visit_integer_node(node)

Visit an IntegerNode node.
def visit_integer_node(node)
  visit_number(node) { |text| on_int(text) }
end

def visit_number(node)

unary - operator.
Visit a node that represents a number. We need to explicitly handle the
def visit_number(node)
  slice = node.slice
  location = node.location
  if slice[0] == "-"
    bounds_values(location.start_line, location.start_column + 1)
    value = yield slice[1..-1]
    bounds(node.location)
    on_unary(RUBY_ENGINE == "jruby" ? :- : :-@, value)
  else
    bounds(location)
    yield slice
  end
end

def visit_parentheses_node(node)

Visit a ParenthesesNode node.
def visit_parentheses_node(node)
  body =
    if node.body.nil?
      on_stmts_add(on_stmts_new, on_void_stmt)
    else
      visit(node.body)
    end
  bounds(node.location)
  on_paren(body)
end

def visit_program_node(node)

Visit a ProgramNode node.
def visit_program_node(node)
  statements = visit(node.statements)
  bounds(node.location)
  on_program(statements)
end

def visit_range_node(node)

Visit a RangeNode node.
def visit_range_node(node)
  left = visit(node.left)
  right = visit(node.right)
  bounds(node.location)
  if node.exclude_end?
    on_dot3(left, right)
  else
    on_dot2(left, right)
  end
end

def visit_rational_node(node)

Visit a RationalNode node.
def visit_rational_node(node)
  visit_number(node) { |text| on_rational(text) }
end

def visit_statements_node(node)

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