⚠️ Moved: The translation from Prism AST to parser gem AST moved to the prism gem as Prism::Translation::Parser.
This gem provides a new backend for the whitequark/parser gem's syntax tree that uses the prism parser.
Add this line to your application's Gemfile:
gem "parser-prism"
And then execute:
$ bundle
Or install it yourself as:
$ gem install parser-prism
The parser
gem provides multiple parsers to support different versions of the Ruby grammar. This includes all of the Ruby versions going back to 1.8, as well as third-party parsers like MacRuby and RubyMotion. The parser-prism
gem provides another parser that uses the prism
parser to build the syntax tree.
You can use the prism
parser like you would any other. After requiring the parser, you should be able to call any of the regular Parser::Base
APIs that you would normally use.
require "parser/prism"
Parser::Prism.parse_file("path/to/file.rb")
To run RuboCop using the parser-prism
gem as the parser, you will need to require the parser/prism/rubocop
file. This file injects prism
into the known options for both rubocop
and rubocop-ast
, such that you can specify it in your .rubocop.yml
file. Unfortunately rubocop
doesn't support any direct way to do this, so we have to get a bit hacky.
First, set the TargetRubyVersion
in your RuboCop configuration file to 80_82_73_83_77.33
. This is the version of Ruby that prism
reports itself as. (The leading numbers are the ASCII values for PRISM
.)
AllCops:
TargetRubyVersion: 80_82_73_83_77.33
Now when you run rubocop
you will need to require the parser/prism/rubocop
file before executing so that it can inject the prism
parser into the known options.
bundle exec ruby -rparser/prism/rubocop $(bundle exec which rubocop)
This should run RuboCop using the prism
parser.
As a whole, this parser should be significantly faster than the parser
gem. The bin/bench
script in this repository compares the performance of Parser::CurrentRuby
and Parser::Prism
. Running against a large file like lib/parser/prism/compiler.rb
yields:
Warming up --------------------------------------
Parser::CurrentRuby 1.000 i/100ms
Parser::Prism 6.000 i/100ms
Calculating -------------------------------------
Parser::CurrentRuby 16.642 (± 0.0%) i/s - 84.000 in 5.052021s
Parser::Prism 64.951 (± 3.1%) i/s - 330.000 in 5.088147s
Comparison:
Parser::Prism: 65.0 i/s
Parser::CurrentRuby: 16.6 i/s - 3.90x slower
When running with --yjit
, the comparison is even more stark:
Warming up --------------------------------------
Parser::CurrentRuby 1.000 i/100ms
Parser::Prism 9.000 i/100ms
Calculating -------------------------------------
Parser::CurrentRuby 20.062 (± 0.0%) i/s - 101.000 in 5.034389s
Parser::Prism 112.823 (± 9.7%) i/s - 558.000 in 5.009460s
Comparison:
Parser::Prism: 112.8 i/s
Parser::CurrentRuby: 20.1 i/s - 5.62x slower
These benchmarks were run on a single laptop without a lot of control for other processes, so take them with a grain of salt.
Run bundle exec rake test
to run the tests. This runs tests exported from the parser
gem into their own fixture files.
Bug reports and pull requests are welcome on GitHub at https://github.com/kddnewton/parser-prism.
The gem is available as open source under the terms of the MIT License.