123456789_123456789_123456789_123456789_123456789_

Class: Prism::RipperCompat

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Visitor
Instance Chain:
self, Visitor
Inherits: Visitor
Defined in: lib/prism/ripper_compat.rb

Overview

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 RipperCompat effectively as you would treat the Ripper class.

Class Method Summary

Instance Attribute Summary

  • #column readonly

    The current column number of the parser.

  • #error? ⇒ Boolean readonly

    True if the parser encountered an error during parsing.

  • #lineno readonly

    The current line number of the parser.

  • #source readonly

    The source that is being parsed.

Instance Method Summary

Constructor Details

.new(source) ⇒ RipperCompat

Create a new RipperCompat object with the given source.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 74

def initialize(source)
  @source = source
  @result = nil
  @lineno = nil
  @column = nil
end

Class Method Details

.sexp(source)

This is a convenience method that runs the RipperCompat::SexpBuilderPP subclass parser.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 171

def self.sexp(source)
  SexpBuilderPP.new(source).parse
end

.sexp_raw(source)

This is a convenience method that runs the RipperCompat::SexpBuilder subclass parser.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 166

def self.sexp_raw(source)
  SexpBuilder.new(source).parse
end

Instance Attribute Details

#column (readonly)

The current column number of the parser.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 71

attr_reader :column

#error?Boolean (readonly)

True if the parser encountered an error during parsing.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 86

def error?
  result.failure?
end

#lineno (readonly)

The current line number of the parser.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 68

attr_reader :lineno

#source (readonly)

The source that is being parsed.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 65

attr_reader :source

Instance Method Details

#_dispatch0 (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 192

def _dispatch0; end # :nodoc:

#_dispatch1(_) (private) Also known as: #on_parse_error

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 193

def _dispatch1(_); end # :nodoc:

#_dispatch2(_, _) (private) Also known as: #on_magic_comment

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 194

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

#_dispatch3(_, _, _) (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 195

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

#_dispatch4(_, _, _, _) (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 196

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

#_dispatch5(_, _, _, _, _) (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 197

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

#_dispatch7(_, _, _, _, _, _, _) (private)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 198

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

#bounds(location) (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.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 182

def bounds(location)
  @lineno = location.start_line
  @column = location.start_column
end

#on_magic_comment(_, _) (private)

Alias for #_dispatch2.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 201

alias_method :on_magic_comment, :_dispatch2

#on_parse_error(_) (private)

Alias for #_dispatch1.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 200

alias_method :on_parse_error, :_dispatch1

#parse

Parse the source and return the result.

[ GitHub ]

  
# 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

#result (private)

Lazily initialize the parse result.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 188

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

#visit_call_node(node)

Visit a CallNode node.

[ GitHub ]

  
# 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_float_node(node)

Visit a FloatNode node.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 123

def visit_float_node(node)
  bounds(node.location)
  on_float(node.slice)
end

#visit_imaginary_node(node)

Visit a ImaginaryNode node.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 129

def visit_imaginary_node(node)
  bounds(node.location)
  on_imaginary(node.slice)
end

#visit_integer_node(node)

Visit an IntegerNode node.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 135

def visit_integer_node(node)
  bounds(node.location)
  on_int(node.slice)
end

#visit_program_node(node)

Visit a ProgramNode node.

[ GitHub ]

  
# 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_rational_node(node)

Visit a RationalNode node.

[ GitHub ]

  
# File 'lib/prism/ripper_compat.rb', line 141

def visit_rational_node(node)
  bounds(node.location)
  on_rational(node.slice)
end

#visit_statements_node(node)

Visit a StatementsNode node.

[ GitHub ]

  
# 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