Because parser only parses Ruby <= 3.3 and prism only Ruby >= 3.3, if you want to continue parsing both old and new versions, you need to depend on both parser and prism.
require 'parser'
require 'prism'
def parser_for_ruby_version(ruby_version)
case ruby_version
when 3.1
require 'parser/ruby31'
Parser::Ruby31
when 3.2
require 'parser/ruby32'
Parser::Ruby32
when 3.3
Prism::Translation::Parser33
when 3.4
Prism::Translation::Parser34
else
raise 'Unknown Ruby version'
end
end
parser_for_ruby_version(3.4).parse(<<~RUBY)
puts 'Hello World!'
RUBYIf you are using Parser::CurrentRuby, you need to do similar branching logic:
def parser_for_current_ruby
if Gem::Version.new(RUBY_VERSION) <= '3.3'
require 'parser/current'
Parser::CurrentRuby
else
require 'prism'
# Only available on prism > 1.4.0
Prism::Translation::ParserCurrent
end
end
parser_for_current_ruby.parse(<<~RUBY)
puts 'Hello World!'
RUBYIf you are providing a custom builder (see Customization), you must create a copy that behaves the same for prism, but inherits from a different base class. This is because the builder used internally by prism has more functionality for more modern node types, which is lacking in the builder from parser.
# Use a module to not duplicate the implementation
module BuilderExtensions
def self.inherited(base)
# Always emit the most modern format available
base.modernize
end
end
class BuilderParser < Parser::Builders::Default
include BuilderExtensions
end
class BuilderPrism < Prism::Translation::Parser::Builder
include BuilderExtensions
endYou can then conditionally use the proper builder class, branching on the version of ruby that will get analyzed.
As new syntax gets added to Ruby, the prism gem may emit nodes that have no counterpart in the parser gem. These nodes will be documented in the usual place but are otherwise not supported or emitted by the parser gem.