This class provides 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. To use this class, you treat ‘Prism::Translation::Ripper` effectively as you would treat the `Ripper` class.

Note that this class will serve the most common use cases, but Ripper’s API is extensive and undocumented. It relies on reporting the state of the parser at any given time. We do our best to replicate that here, but because it is a different architecture it is not possible to perfectly replicate the behavior of Ripper.

The main known difference is that we may omit dispatching some events in some cases. This impacts the following events:

  • on_assign_error

  • on_comma

  • on_ignored_nl

  • on_ignored_sp

  • on_kw

  • on_label_end

  • on_lbrace

  • on_lbracket

  • on_lparen

  • on_nl

  • on_op

  • on_operator_ambiguous

  • on_rbrace

  • on_rbracket

  • on_rparen

  • on_semicolon

  • on_sp

  • on_symbeg

  • on_tstring_beg

  • on_tstring_end

Constants

This contains a table of all of the parser events and their corresponding arity.

This contains a table of all of the scanner events and their corresponding arity.

This array contains name of parser events.

This array contains name of scanner events.

This array contains name of all ripper events.

A list of all of the Ruby keywords.

A list of all of the Ruby binary operators.

Attributes
Read

The source that is being parsed.

Read

The filename of the source being parsed.

Read

The current line number of the parser.

Read

The current column number of the parser.

Class Methods

Tokenizes the Ruby program and returns an array of an array, which is formatted like [[lineno, column], type, token, state]. The filename argument is mostly ignored. By default, this method does not handle syntax errors in src, use the raise_errors keyword to raise a SyntaxError for an error in src.

require "ripper"
require "pp"

pp Ripper.lex("def m(a) nil end")
#=> [[[1,  0], :on_kw,     "def", FNAME    ],
     [[1,  3], :on_sp,     " ",   FNAME    ],
     [[1,  4], :on_ident,  "m",   ENDFN    ],
     [[1,  5], :on_lparen, "(",   BEG|LABEL],
     [[1,  6], :on_ident,  "a",   ARG      ],
     [[1,  7], :on_rparen, ")",   ENDFN    ],
     [[1,  8], :on_sp,     " ",   BEG      ],
     [[1,  9], :on_kw,     "nil", END      ],
     [[1, 12], :on_sp,     " ",   END      ],
     [[1, 13], :on_kw,     "end", END      ]]

Create a new Translation::Ripper object with the given source.

Parses the given Ruby program read from src. src must be a String or an IO or a object with a gets method.

Parses src and create S-exp tree. Returns more readable tree rather than Ripper.sexp_raw. This method is mainly for developer use. The filename argument is mostly ignored. By default, this method does not handle syntax errors in src, returning nil in such cases. Use the raise_errors keyword to raise a SyntaxError for an error in src.

require "ripper"
require "pp"

pp Ripper.sexp("def m(a) nil end")
  #=> [:program,
       [[:def,
        [:@ident, "m", [1, 4]],
        [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
        [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]

Parses src and create S-exp tree. This method is mainly for developer use. The filename argument is mostly ignored. By default, this method does not handle syntax errors in src, returning nil in such cases. Use the raise_errors keyword to raise a SyntaxError for an error in src.

require "ripper"
require "pp"

pp Ripper.sexp_raw("def m(a) nil end")
  #=> [:program,
       [:stmts_add,
        [:stmts_new],
        [:def,
         [:@ident, "m", [1, 4]],
         [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
         [:bodystmt,
          [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
          nil,
          nil,
          nil]]]]
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.

Returns true if the given node is a command node.

This method is called when the parser found syntax error.

This method is provided by the Ripper C extension. It is called when a string needs to be dedented because of a tilde heredoc. It is expected that it will modify the string in place and return the number of bytes that were removed.

True if the parser encountered an error during parsing.

Parse the source and return the result.

Lazily initialize the parse result.

Returns true if there is a comma between the two locations.

alias $foo $bar ^^^^^^^^^^^^^^^

Visit one side of an alias global variable node.

alias foo bar ^^^^^^^^^^^^^

foo => bar | baz

^^^^^^^^^

a and b ^^^^^^^

Visit a list of elements, like the elements of an array or arguments.

foo(bar)

^^^

^^

foo => [bar]

^^^^^

{ a: 1 }

^^^^

def foo(**); bar(**); end

^^

{ **foo }

^^^^^

$+ ^^

begin end ^^^^^^^^^

Visit the clauses of a begin node to form an on_bodystmt call.

foo(&bar)

^^^^

foo { |; bar| }

^^^

Visit a BlockNode.

def foo(&bar); end

^^^^

A block’s parameters.

Visit the body of a structure that can have either a set of statements or statements wrapped in rescue/else/ensure.

break ^^^^^

break foo ^^^^^^^^^

foo.bar &&= baz ^^^^^^^^^^^^^^^

foo ^^^

foo.bar ^^^^^^^

foo.bar() {} ^^^^^^^^^^^^

Visit the arguments and block of a call node and return the arguments and block as they should be used.

foo.bar += baz ^^^^^^^^^^^^^^^

foo.bar ||= baz ^^^^^^^^^^^^^^^

foo.bar, = 1 ^^^^^^^

foo => bar => baz

^^^^^^^^^^

case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^

case foo; when bar; end ^^^^^^^^^^^^^^^^^^^^^^^

class Foo; end ^^^^^^^^^^^^^^

@@foo &&= bar ^^^^^^^^^^^^^

@@foo += bar ^^^^^^^^^^^^

@@foo ||= bar ^^^^^^^^^^^^^

@@foo ^^^^^

@@foo, = bar ^^^^^

@@foo = 1 ^^^^^^^^^

@@foo, @@bar = 1 ^^^^^ ^^^^^

Foo &&= bar ^^^^^^^^^^^^

Foo += bar ^^^^^^^^^^^

Foo ||= bar ^^^^^^^^^^^^

Foo::Bar &&= baz ^^^^^^^^^^^^^^^^

Foo::Bar ^^^^^^^^

Foo::Bar += baz ^^^^^^^^^^^^^^^

Foo::Bar ||= baz ^^^^^^^^^^^^^^^^

Foo::Bar, = baz ^^^^^^^^

Foo::Bar = 1 ^^^^^^^^^^^^

Foo::Foo, Bar::Bar = 1 ^^^^^^^^ ^^^^^^^^

Visit a constant path that is part of a write node.

Foo ^^^

Foo, = bar ^^^

Foo = 1 ^^^^^^^

Foo, Bar = 1 ^^^ ^^^

def foo; end ^^^^^^^^^^^^

def self.foo; end ^^^^^^^^^^^^^^^^^

defined? a ^^^^^^^^^^

defined?(a) ^^^^^^^^^^^

Visit a destructured positional parameter node.

if foo then bar else baz end

^^^^^^^^^^^^

“foo #{bar}”

^^^^^^

“foo #@bar”

^^^^^

Visit an EnsureNode node.

false ^^^^^

foo => [*, bar, *]

^^^^^^^^^^^

if foo .. bar; end

^^^^^^^^^^

1.0 ^^^

for foo in bar do end ^^^^^^^^^^^^^^^^^^^^^

def foo(…); bar(…); end

^^^

def foo(…); end

^^^

super ^^^^^

super {} ^^^^^^^^

$foo &&= bar ^^^^^^^^^^^^

$foo += bar ^^^^^^^^^^^

$foo ||= bar ^^^^^^^^^^^^

$foo ^^^^

$foo, = bar ^^^^

$foo = 1 ^^^^^^^^

$foo, $bar = 1 ^^^^ ^^^^

{} ^^

foo => {}

^^

Visit a string that is expressed using a <<~ heredoc.

Ripper gives back the escaped string content but strips out the common leading whitespace. Prism gives back the unescaped string content and a location for the escaped string content. Unfortunately these don’t work well together, so here we need to re-derive the common leading whitespace.

Visit a heredoc node that is representing a string.

Visit a heredoc node that is representing an xstring.

if foo then bar end ^^^^^^^^^^^^^^^^^^^

bar if foo ^^^^^^^^^^

foo ? bar : baz ^^^^^^^^^^^^^^^

1i ^^

{ foo: }

^^^^

foo { |bar,| }

^

case foo; in bar; end ^^^^^^^^^^^^^^^^^^^^^

foo &&= baz ^^^^^^^^^^^^^^^^

foo += baz ^^^^^^^^^^^^^^^

foo ||= baz ^^^^^^^^^^^^^^^^

foo, = 1 ^^^^^^^^

@foo &&= bar ^^^^^^^^^^^^

@foo += bar ^^^^^^^^^^^

@foo ||= bar ^^^^^^^^^^^^

@foo ^^^^

@foo, = bar ^^^^

@foo = 1 ^^^^^^^^

1 ^

if /foo #{bar}/ then end

^^^^^^^^^^^^

/foo #{bar}/ ^^^^^^^^^^^^

“foo #{bar}” ^^^^^^^^^^^^

:“foo #{bar}” ^^^^^^^^^^^^^

‘foo #{bar}` ^^^^^^^^^^^^

-> { it }

^^

-> { it } ^^^^^^^^^

foo(bar: baz)

^^^^^^^^

def foo(**bar); end

^^^^^

def foo(**); end

^^

-> {}

foo &&= bar ^^^^^^^^^^^

foo += bar ^^^^^^^^^^

foo ||= bar ^^^^^^^^^^^

foo ^^^

foo, = bar ^^^

foo = 1 ^^^^^^^

if /foo/ then end

^^^^^

foo in bar ^^^^^^^^^^

foo => bar ^^^^^^^^^^

/(?<foo>foo)/ =~ bar ^^^^^^^^^^^^^^^^^^^^

A node that is missing from the syntax tree. This is only used in the case of a syntax error.

module Foo; end ^^^^^^^^^^^^^^^

(foo, bar), bar = qux ^^^^^^^^^^

Visit the targets of a multi-target node.

foo, bar = baz ^^^^^^^^^^^^^^

next ^^^^

next foo ^^^^^^^^

nil ^^^

def foo(**nil); end

^^^^^

Visit a node that represents a number. We need to explicitly handle the unary - operator.

-> { _1 + _2 } ^^^^^^^^^^^^^^

$1 ^^

def foo(bar: baz); end

^^^^^^^^

def foo(bar = 1); end

^^^^^^^

a or b ^^^^^^

def foo(bar, *baz); end

^^^^^^^^^

() ^^

(1) ^^^

Visit a pattern within a pattern match. This is used to bypass the parenthesis node that can be used to wrap patterns.

foo => ^(bar)

^^^^^^

foo = 1 and bar => ^foo

^^^^

END {} ^^^^^^

BEGIN {} ^^^^^^^^

The top-level program node.

0..5 ^^^^

1r ^^

redo ^^^^

/foo/ ^^^^^

def foo(bar:); end

^^^^

def foo(bar); end

^^^

foo rescue bar ^^^^^^^^^^^^^^

begin; rescue; end

^^^^^^^

def foo(*bar); end

^^^^

def foo(*); end

^

retry ^^^^^

return ^^^^^^

return 1 ^^^^^^^^

self ^^^^

A shareable constant.

class << self; end ^^^^^^^^^^^^^^^^^^

__ENCODING__ ^^^^^^^^^^^^

__FILE__ ^^^^^^^^

__LINE__ ^^^^^^^^

foo(*bar)

^^^^

def foo((bar, *baz)); end

^^^^

def foo(*); bar(*); end

^

A list of statements.

Visit the list of statements of a statements node. We support nil statements in the list. This would normally not be allowed by the structure of the prism parse tree, but we manually add them here so that we can mirror Ripper’s void stmt.

Visit an individual part of a string-like node.

“foo” ^^^^^

super(foo) ^^^^^^^^^^

:foo ^^^^

Visit the string content of a particular node. This method is used to split into the various token types.

true ^^^^

undef foo ^^^^^^^^^

unless foo; bar end ^^^^^^^^^^^^^^^^^^^

bar unless foo ^^^^^^^^^^^^^^

until foo; bar end ^^^^^^^^^^^^^^^^^

bar until foo ^^^^^^^^^^^^^

case foo; when bar; end

^^^^^^^^^^^^^

while foo; bar end ^^^^^^^^^^^^^^^^^^

bar while foo ^^^^^^^^^^^^^

Dispatch a words_sep event that contains the space between the elements of list literals.

Visit a node that represents a write value. This is used to handle the special case of an implicit array that is generated without brackets.

‘foo` ^^^^^

yield ^^^^^

yield 1 ^^^^^^^

Returns true if there is a semicolon between the two locations.

This method is called when weak warning is produced by the parser. fmt and args is printf style.

This method is called when strong warning is produced by the parser. fmt and args is printf style.