Module: Prism
Overview
The Prism Ruby parser.
“Parsing Ruby is suddenly manageable!”
- You, hopefully
Constant Summary
-
BACKEND =
The FFI backend is used on other Ruby implementations.
:FFI
-
VERSION =
The version constant is set by reading the result of calling pm_version.
LibRubyParser.pm_version.read_string
Class Method Summary
-
.dump(source, **options) ⇒ String
Dump the AST corresponding to the given string to a string.
-
.dump_file(filepath, **options) ⇒ String
Dump the AST corresponding to the given file to a string.
- .lex(source, **options) ⇒ LexResult
-
.lex_compat(source, **options) ⇒ LexCompat::Result
Returns a parse result whose value is an array of tokens that closely resembles the return value of
Ripper.lex
. - .lex_file(filepath, **options) ⇒ LexResult
-
.lex_ripper(source) ⇒ Array
This lexes with the Ripper lex.
-
.load(source, serialized) ⇒ ParseResult
Load the serialized AST using the source as a reference into a tree.
-
.parse(source, **options) ⇒ ParseResult
Parse the given string and return a
ParseResult
instance. -
.parse_comments(source, **options) ⇒ Array
Parse the given string and return an array of
Comment
objects. -
.parse_failure?(source, **options) ⇒ Boolean
Parse the given string and return true if it parses with errors.
-
.parse_file(filepath, **options)
Mirror the
parse_file
API by using the serialization API. -
.parse_file_comments(filepath, **options)
Mirror the
parse_file_comments
API by using the serialization API. -
.parse_file_failure?(filepath, **options) ⇒ Boolean
Parse the given file and return true if it parses with errors.
-
.parse_file_success?(filepath, **options) ⇒ Boolean
Parse the given file and return true if it parses without errors.
-
.parse_lex(source, **options) ⇒ ParseLexResult
Parse the given string and return a
ParseLexResult
instance that contains a 2-element array, where the first element is the AST and the second element is an array ofToken
instances. -
.parse_lex_file(filepath, **options) ⇒ ParseLexResult
Parse the given file and return a
ParseLexResult
instance that contains a 2-element array, where the first element is the AST and the second element is an array ofToken
instances. -
.parse_stream(stream, **options) ⇒ ParseResult
Parse the given object that responds to
gets
and return aParseResult
instance. -
.parse_success?(source, **options) ⇒ Boolean
Parse the given string and return true if it parses without errors.
-
.profile(source, **options) ⇒ nil
Parse the given string and return nothing.
-
.profile_file(filepath, **options) ⇒ nil
Parse the given file and return nothing.
-
.dump_options(options)
private
Convert the given options into a serialized options string.
-
.dump_options_command_line(options)
private
Return the value that should be dumped for the command_line option.
-
.dump_options_version(version)
private
Return the value that should be dumped for the version option.
- .dump_common(string, options) private Internal use only
- .lex_common(string, code, options) private Internal use only
- .parse_comments_common(string, code, options) private Internal use only
- .parse_common(string, code, options) private Internal use only
- .parse_file_success_common(string, options) private Internal use only
- .parse_lex_common(string, code, options) private Internal use only
Class Method Details
.dump(source, **options) ⇒ String
Dump the AST corresponding to the given string to a string. For supported options, see .parse.
# File 'prism/extension.c', line 333
static VALUE dump(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); #ifdef PRISM_BUILD_DEBUG size_t length = pm_string_length(&input); char* dup = xmalloc(length); memcpy(dup, pm_string_source(&input), length); pm_string_constant_init(&input, dup, length); #endif VALUE value = dump_input(&input, &options); #ifdef PRISM_BUILD_DEBUG xfree(dup); #endif pm_string_free(&input); pm_options_free(&options); return value; }
.dump_common(string, options) (private)
# File 'lib/prism/ffi.rb', line 354
def dump_common(string, ) # :nodoc: LibRubyParser::PrismBuffer.with do |buffer| LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, ( )) buffer.read end end
.dump_file(filepath, **options) ⇒ String
Dump the AST corresponding to the given file to a string. For supported options, see .parse.
# File 'prism/extension.c', line 365
static VALUE dump_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = dump_input(&input, &options); pm_string_free(&input); pm_options_free(&options); return value; }
.dump_options(options) (private)
Convert the given options into a serialized options string.
# File 'lib/prism/ffi.rb', line 441
def ( ) template = +"" values = [] template << "L" if (filepath = [:filepath]) values.push(filepath.bytesize, filepath.b) template << "A*" else values << 0 end template << "l" values << .fetch(:line, 1) template << "L" if (encoding = [:encoding]) name = encoding.is_a?(Encoding) ? encoding.name : encoding values.push(name.bytesize, name.b) template << "A*" else values << 0 end template << "C" values << ( .fetch(:frozen_string_literal, false) ? 1 : 0) template << "C" values << ( ) template << "C" values << ( [:version]) template << "C" values << ( [:encoding] == false ? 1 : 0) template << "C" values << ( .fetch(:main_script, false) ? 1 : 0) template << "C" values << ( .fetch(:partial_script, false) ? 1 : 0) template << "L" if (scopes = [:scopes]) values << scopes.length scopes.each do |scope| template << "L" values << scope.length scope.each do |local| name = local.name template << "L" values << name.bytesize template << "A*" values << name.b end end else values << 0 end values.pack(template) end
.dump_options_command_line(options) (private)
Return the value that should be dumped for the command_line option.
# File 'lib/prism/ffi.rb', line 409
def ( ) command_line = .fetch(:command_line, "") raise ArgumentError, "command_line must be a string" unless command_line.is_a?(String) command_line.each_char.inject(0) do |value, char| case char when "a" then value | 0b000001 when "e" then value | 0b000010 when "l" then value | 0b000100 when "n" then value | 0b001000 when "p" then value | 0b010000 when "x" then value | 0b100000 else raise ArgumentError, "invalid command_line option: #{char}" end end end
.dump_options_version(version) (private)
Return the value that should be dumped for the version option.
# File 'lib/prism/ffi.rb', line 427
def (version) case version when nil, "latest" 0 when /\A3\.3(\.\d+)?\z/ 1 when /\A3\.4(\.\d+)?\z/ 0 else raise ArgumentError, "invalid version: #{version}" end end
.lex(source, **options) ⇒ LexResult
Return a ::Prism::LexResult
instance that contains an array of ::Prism::Token
instances corresponding to the given string. For supported options, see .parse.
# File 'prism/extension.c', line 679
static VALUE lex(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); VALUE result = parse_lex_input(&input, &options, false); pm_string_free(&input); pm_options_free(&options); return result; }
.lex_common(string, code, options) (private)
# File 'lib/prism/ffi.rb', line 361
def lex_common(string, code, ) # :nodoc: serialized = LibRubyParser::PrismBuffer.with do |buffer| LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, ( )) buffer.read end Serialize.load_tokens(Source.for(code), serialized) end
.lex_compat(source, **options) ⇒ LexCompat::Result
Returns a parse result whose value is an array of tokens that closely resembles the return value of Ripper.lex
. The main difference is that the :on_sp
token is not emitted.
For supported options, see .parse.
.lex_file(filepath, **options) ⇒ LexResult
Return a ::Prism::LexResult
instance that contains an array of ::Prism::Token
instances corresponding to the given file. For supported options, see .parse.
# File 'prism/extension.c', line 699
static VALUE lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, false); pm_string_free(&input); pm_options_free(&options); return value; }
.lex_ripper(source) ⇒ Array
This lexes with the Ripper lex. It drops any space events but otherwise returns the same tokens. Raises SyntaxError if the syntax in source is invalid.
.load(source, serialized) ⇒ ParseResult
Load the serialized AST using the source as a reference into a tree.
# File 'lib/prism.rb', line 65
def self.load(source, serialized) Serialize.load(source, serialized) end
.parse(source, **options) ⇒ ParseResult
Parse the given string and return a ::Prism::ParseResult
instance. The options that are supported are:
-
command_line
- either nil or a string of the various options that wereset on the command line. Valid values are combinations of "a", "l", "n", "p", and "x".
-
encoding
- the encoding of the source being parsed. This should be anencoding or nil.
-
filepath
- the filepath of the source being parsed. This should be astring or nil.
-
frozen_string_literal
- whether or not the frozen string literal pragmahas been set. This should be a boolean or nil.
-
line
- the line number that the parse starts on. This should be aninteger or nil. Note that this is 1-indexed.
-
main_script
- a boolean indicating whether or not the source being parsedis the main script being run by the interpreter. This controls whether or not shebangs are parsed for additional flags and whether or not the parser will attempt to find a matching shebang if the first one does not contain the word "ruby".
-
partial_script
- when the file being parsed is considered a “partial”script, jumps will not be marked as errors if they are not contained within loops/blocks. This is used in the case that you're parsing a script that you know will be embedded inside another script later, but you do not have that context yet. For example, when parsing an ERB template that will be evaluated inside another script.
-
scopes
- the locals that are in scope surrounding the code that is beingparsed. This should be an array of arrays of symbols or nil. Scopes are ordered from the outermost scope to the innermost one.
-
version
- the version of Ruby syntax that prism should used to parse Rubycode. By default prism assumes you want to parse with the latest version of Ruby syntax (which you can trigger with {nil} or {"latest"}). You may also restrict the syntax to a specific version of Ruby, e.g., with {"3.3.0"}. To parse with the same syntax version that the current Ruby is running use `version: RUBY_VERSION`. Raises ArgumentError if the version is not currently supported by Prism.
# File 'prism/extension.c', line 779
static VALUE parse(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); #ifdef PRISM_BUILD_DEBUG size_t length = pm_string_length(&input); char* dup = xmalloc(length); memcpy(dup, pm_string_source(&input), length); pm_string_constant_init(&input, dup, length); #endif VALUE value = parse_input(&input, &options); #ifdef PRISM_BUILD_DEBUG xfree(dup); #endif pm_string_free(&input); pm_options_free(&options); return value; }
.parse_comments(source, **options) ⇒ Array
Parse the given string and return an array of ::Prism::Comment
objects. For supported options, see .parse.
# File 'prism/extension.c', line 963
static VALUE parse_comments(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); VALUE result = parse_input_comments(&input, &options); pm_string_free(&input); pm_options_free(&options); return result; }
.parse_comments_common(string, code, options) (private)
# File 'lib/prism/ffi.rb', line 375
def parse_comments_common(string, code, ) # :nodoc: LibRubyParser::PrismBuffer.with do |buffer| LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, ( )) source = Source.for(code) loader = Serialize::Loader.new(source, buffer.read) loader.load_header loader.load_encoding loader.load_start_line loader.load_comments end end
.parse_common(string, code, options) (private)
# File 'lib/prism/ffi.rb', line 370
def parse_common(string, code, ) # :nodoc: serialized = dump_common(string, ) Prism.load(code, serialized) end
.parse_failure?(source, **options) ⇒ Boolean
Parse the given string and return true if it parses with errors. For supported options, see .parse.
# File 'prism/extension.c', line 1098
static VALUE parse_failure_p(int argc, VALUE *argv, VALUE self) { return RTEST(parse_success_p(argc, argv, self)) ? Qfalse : Qtrue; }
.parse_file(filepath, **options)
Mirror the parse_file
API by using the serialization API. This uses native strings instead of Ruby strings because it allows us to use mmap when it is available.
# File 'prism/extension.c', line 810
static VALUE parse_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_input(&input, &options); pm_string_free(&input); pm_options_free(&options); return value; }
.parse_file_comments(filepath, **options)
Mirror the parse_file_comments
API by using the serialization API. This uses native strings instead of Ruby strings because it allows us to use mmap when it is available.
# File 'prism/extension.c', line 983
static VALUE parse_file_comments(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_input_comments(&input, &options); pm_string_free(&input); pm_options_free(&options); return value; }
.parse_file_failure?(filepath, **options) ⇒ Boolean
Parse the given file and return true if it parses with errors. For supported options, see .parse.
# File 'prism/extension.c', line 1132
static VALUE parse_file_failure_p(int argc, VALUE *argv, VALUE self) { return RTEST(parse_file_success_p(argc, argv, self)) ? Qfalse : Qtrue; }
.parse_file_success?(filepath, **options) ⇒ Boolean
Parse the given file and return true if it parses without errors. For supported options, see .parse.
# File 'prism/extension.c', line 1110
static VALUE parse_file_success_p(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE result = parse_input_success_p(&input, &options); pm_string_free(&input); pm_options_free(&options); return result; }
.parse_file_success_common(string, options) (private)
# File 'lib/prism/ffi.rb', line 404
def parse_file_success_common(string, ) # :nodoc: LibRubyParser.pm_parse_success_p(string.pointer, string.length, ( )) end
.parse_lex(source, **options) ⇒ ParseLexResult
Parse the given string and return a ::Prism::ParseLexResult
instance that contains a 2-element array, where the first element is the AST and the second element is an array of ::Prism::Token
instances.
This API is only meant to be used in the case where you need both the AST and the tokens. If you only need one or the other, use either .parse or .lex.
For supported options, see .parse.
# File 'prism/extension.c', line 1012
static VALUE parse_lex(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); VALUE value = parse_lex_input(&input, &options, true); pm_string_free(&input); pm_options_free(&options); return value; }
.parse_lex_common(string, code, options) (private)
# File 'lib/prism/ffi.rb', line 389
def parse_lex_common(string, code, ) # :nodoc: LibRubyParser::PrismBuffer.with do |buffer| LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, ( )) source = Source.for(code) loader = Serialize::Loader.new(source, buffer.read) tokens = loader.load_tokens node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes tokens.each { |token,| token.value.force_encoding(loader.encoding) } ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source) end end
.parse_lex_file(filepath, **options) ⇒ ParseLexResult
Parse the given file and return a ::Prism::ParseLexResult
instance that contains a 2-element array, where the first element is the AST and the second element is an array of ::Prism::Token
instances.
This API is only meant to be used in the case where you need both the AST and the tokens. If you only need one or the other, use either .parse_file or .lex_file.
For supported options, see .parse.
# File 'prism/extension.c', line 1039
static VALUE parse_lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, true); pm_string_free(&input); pm_options_free(&options); return value; }
.parse_stream(stream, **options) ⇒ ParseResult
Parse the given object that responds to gets
and return a ::Prism::ParseResult
instance. The options that are supported are the same as .parse.
# File 'prism/extension.c', line 910
static VALUE parse_stream(int argc, VALUE *argv, VALUE self) { VALUE stream; VALUE keywords; rb_scan_args(argc, argv, "1:", &stream, &keywords); pm_options_t options = { 0 }; extract_options(&options, Qnil, keywords); pm_parser_t parser; pm_buffer_t buffer; pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE source = pm_source_new(&parser, encoding); VALUE value = pm_ast_new(&parser, node, encoding, source); VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source); pm_node_destroy(&parser, node); pm_buffer_free(&buffer); pm_parser_free(&parser); return result; }
.parse_success?(source, **options) ⇒ Boolean
Parse the given string and return true if it parses without errors. For supported options, see .parse.
# File 'prism/extension.c', line 1078
static VALUE parse_success_p(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); VALUE result = parse_input_success_p(&input, &options); pm_string_free(&input); pm_options_free(&options); return result; }
.profile(source, **options) ⇒ nil
Parse the given string and return nothing. This method is meant to allow profilers to avoid the overhead of reifying the AST to Ruby. For supported options, see .parse.
# File 'prism/extension.c', line 846
static VALUE profile(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; string_options(argc, argv, &input, &options); profile_input(&input, &options); pm_string_free(&input); pm_options_free(&options); return Qnil; }
.profile_file(filepath, **options) ⇒ nil
Parse the given file and return nothing. This method is meant to allow profilers to avoid the overhead of reifying the AST to Ruby. For supported options, see .parse.
# File 'prism/extension.c', line 867
static VALUE profile_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; pm_options_t options = { 0 }; VALUE encoded_filepath; file_options(argc, argv, &input, &options, &encoded_filepath); profile_input(&input, &options); pm_string_free(&input); pm_options_free(&options); return Qnil; }