[Awesome Ruby Gem - Abstract Syntax Tree (AST)] Use unparser gem to produce equivalent source code from Parser's ASTs

parser

unparser generate equivalent source for ASTs from parser. You can also use unparser to produce equivalent source code from Parser’s ASTs whitequark/parser: A Ruby parser. - https://github.com/whitequark/parser.

Installation

You can install it as a gem:

1
$ gem install unparser

or add it into a Gemfile (Bundler):

1
2
3
4
5
# Gemfile

# mbj/unparser: Turn Ruby AST into semantically equivalent Ruby source
# https://github.com/mbj/unparser](https://github.com/mbj/unparser
gem 'unparser', '0.6.0'

Then, run bundle install.

1
$ bundle install

Usage

1
2
3
4
5
6
require 'parser/current'
require 'unparser'

ast = Unparser.parse('your(ruby(code))')

Unparser.unparse(ast) # => 'your(ruby(code))'

To preserve the comments from the source:

1
2
3
4
5
6
require 'parser/current'
require 'unparser'

ast, comments = Unparser.parse_with_comments('your(ruby(code)) # with comments')

Unparser.unparse(ast, comments) # => 'your(ruby(code)) # with comments'

Passing in manually constructed AST:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require 'parser/current'
require 'unparser'

module YourHelper
def s(type, *children)
Parser::AST::Node.new(type, children)
end
end

include YourHelper

node = s(:def,
:foo,
s(:args,
s(:arg, :x)
),
s(:send,
s(:lvar, :x),
:+,
s(:int, 3)
)
)

Unparser.unparse(node) # => "def foo(x)\n x + 3\nend"

Note: DO NOT attempt to pass in nodes generated via AST::Sexp#s, these ones return API incompatible AST::Node instances, unparser needs Parser::AST::Node instances.


Equivalent vs identical:

1
2
3
4
5
6
7
8
9
10
require 'unparser'

node = Unparser.parse(<<~'RUBY')
%w[foo bar]
RUBY

generated = Unparser.unparse(node) # ["foo", "bar"], NOT %w[foo bar] !

code == generated # false, not identical code
Unparser.parse(generated) == node # true, but identical AST

Summary: unparser does not reproduce your source! It produces equivalent source.

References

[1] mbj/unparser: Turn Ruby AST into semantically equivalent Ruby source - https://github.com/mbj/unparser

[2] unparser | RubyGems.org | your community gem host - https://rubygems.org/gems/unparser

[3] whitequark/parser: A Ruby parser. - https://github.com/whitequark/parser