summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/prism/parse_result.rb113
1 files changed, 104 insertions, 9 deletions
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index 00ae3aaa1a..5c2d97bc1e 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -5,19 +5,28 @@ module Prism
# conjunction with locations to allow them to resolve line numbers and source
# ranges.
class Source
- attr_reader :source, :offsets
+ # The source code that this source object represents.
+ attr_reader :source
+ # The list of newline byte offsets in the source code.
+ attr_reader :offsets
+
+ # Create a new source object with the given source code and newline byte
+ # offsets. If no newline byte offsets are given, they will be computed from
+ # the source code.
def initialize(source, offsets = compute_offsets(source))
@source = source
@offsets = offsets
end
+ # Perform a byteslice on the source code using the given byte offset and
+ # byte length.
def slice(offset, length)
source.byteslice(offset, length)
end
# Binary search through the offsets to find the line number for the given
- # offset.
+ # byte offset.
def line(value)
left = 0
right = offsets.length - 1
@@ -36,10 +45,13 @@ module Prism
left - 1
end
+ # Return the byte offset of the start of the line corresponding to the given
+ # byte offset.
def line_offset(value)
offsets[line(value)]
end
+ # Return the column number for the given byte offset.
def column(value)
value - offsets[line(value)]
end
@@ -69,6 +81,8 @@ module Prism
# The list of comments attached to this location
attr_reader :comments
+ # Create a new location object with the given source, start byte offset, and
+ # byte length.
def initialize(source, start_offset, length)
@source = source
@start_offset = start_offset
@@ -128,14 +142,17 @@ module Prism
source.column(end_offset)
end
+ # Implement the hash pattern matching interface for Location.
def deconstruct_keys(keys)
{ start_offset: start_offset, end_offset: end_offset }
end
+ # Implement the pretty print interface for Location.
def pretty_print(q)
q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})")
end
+ # Returns true if the given other location is equal to this location.
def ==(other)
other.is_a?(Location) &&
other.start_offset == start_offset &&
@@ -152,6 +169,9 @@ module Prism
Location.new(source, start_offset, other.end_offset - start_offset)
end
+ # Returns a null location that does not correspond to a source and points to
+ # the beginning of the file. Useful for when you want a location object but
+ # do not care where it points.
def self.null
new(nil, 0, 0)
end
@@ -159,24 +179,41 @@ module Prism
# This represents a comment that was encountered during parsing.
class Comment
+ # These are the three types that comments can be from a source file.
+ #
+ # :inline comments are the most common. They correspond to comments in the
+ # source file like this one that start with #.
+ #
+ # :embdoc comments are comments that are surrounded by =begin and =end.
+ #
+ # :__END__ comments are comments that are after the __END__ keyword in a
+ # source file.
TYPES = [:inline, :embdoc, :__END__]
- attr_reader :type, :location
+ # The type of comment that this comment is.
+ attr_reader :type
+
+ # The location of this comment in the source.
+ attr_reader :location
+ # Create a new comment object with the given type and location.
def initialize(type, location)
@type = type
@location = location
end
+ # Implement the hash pattern matching interface for Comment.
def deconstruct_keys(keys)
{ type: type, location: location }
end
- # Returns true if the comment happens on the same line as other code and false if the comment is by itself
+ # Returns true if the comment happens on the same line as other code and
+ # false if the comment is by itself.
def trailing?
type == :inline && !location.start_line_slice.strip.empty?
end
+ # Returns a string representation of this comment.
def inspect
"#<Prism::Comment @type=#{@type.inspect} @location=#{@location.inspect}>"
end
@@ -184,25 +221,34 @@ module Prism
# This represents a magic comment that was encountered during parsing.
class MagicComment
- attr_reader :key_loc, :value_loc
+ # A Location object representing the location of the key in the source.
+ attr_reader :key_loc
+ # A Location object representing the location of the value in the source.
+ attr_reader :value_loc
+
+ # Create a new magic comment object with the given key and value locations.
def initialize(key_loc, value_loc)
@key_loc = key_loc
@value_loc = value_loc
end
+ # Returns the key of the magic comment by slicing it from the source code.
def key
key_loc.slice
end
+ # Returns the value of the magic comment by slicing it from the source code.
def value
value_loc.slice
end
+ # Implement the hash pattern matching interface for MagicComment.
def deconstruct_keys(keys)
{ key_loc: key_loc, value_loc: value_loc }
end
+ # Returns a string representation of this magic comment.
def inspect
"#<Prism::MagicComment @key=#{key.inspect} @value=#{value.inspect}>"
end
@@ -210,17 +256,24 @@ module Prism
# This represents an error that was encountered during parsing.
class ParseError
- attr_reader :message, :location
+ # The message associated with this error.
+ attr_reader :message
+
+ # A Location object representing the location of this error in the source.
+ attr_reader :location
+ # Create a new error object with the given message and location.
def initialize(message, location)
@message = message
@location = location
end
+ # Implement the hash pattern matching interface for ParseError.
def deconstruct_keys(keys)
{ message: message, location: location }
end
+ # Returns a string representation of this error.
def inspect
"#<Prism::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
end
@@ -228,17 +281,24 @@ module Prism
# This represents a warning that was encountered during parsing.
class ParseWarning
- attr_reader :message, :location
+ # The message associated with this warning.
+ attr_reader :message
+ # A Location object representing the location of this warning in the source.
+ attr_reader :location
+
+ # Create a new warning object with the given message and location.
def initialize(message, location)
@message = message
@location = location
end
+ # Implement the hash pattern matching interface for ParseWarning.
def deconstruct_keys(keys)
{ message: message, location: location }
end
+ # Returns a string representation of this warning.
def inspect
"#<Prism::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
end
@@ -248,8 +308,27 @@ module Prism
# the AST, any comments that were encounters, and any errors that were
# encountered.
class ParseResult
- attr_reader :value, :comments, :magic_comments, :errors, :warnings, :source
+ # The value that was generated by parsing. Normally this holds the AST, but
+ # it can sometimes how a list of tokens or other results passed back from
+ # the parser.
+ attr_reader :value
+
+ # The list of comments that were encountered during parsing.
+ attr_reader :comments
+ # The list of magic comments that were encountered during parsing.
+ attr_reader :magic_comments
+
+ # The list of errors that were generated during parsing.
+ attr_reader :errors
+
+ # The list of warnings that were generated during parsing.
+ attr_reader :warnings
+
+ # A Source instance that represents the source code that was parsed.
+ attr_reader :source
+
+ # Create a new parse result object with the given values.
def initialize(value, comments, magic_comments, errors, warnings, source)
@value = value
@comments = comments
@@ -259,14 +338,19 @@ module Prism
@source = source
end
+ # Implement the hash pattern matching interface for ParseResult.
def deconstruct_keys(keys)
{ value: value, comments: comments, magic_comments: magic_comments, errors: errors, warnings: warnings }
end
+ # Returns true if there were no errors during parsing and false if there
+ # were.
def success?
errors.empty?
end
+ # Returns true if there were errors during parsing and false if there were
+ # not.
def failure?
!success?
end
@@ -274,18 +358,28 @@ module Prism
# This represents a token from the Ruby source.
class Token
- attr_reader :type, :value, :location
+ # The type of token that this token is.
+ attr_reader :type
+
+ # A byteslice of the source that this token represents.
+ attr_reader :value
+
+ # A Location object representing the location of this token in the source.
+ attr_reader :location
+ # Create a new token object with the given type, value, and location.
def initialize(type, value, location)
@type = type
@value = value
@location = location
end
+ # Implement the hash pattern matching interface for Token.
def deconstruct_keys(keys)
{ type: type, value: value, location: location }
end
+ # Implement the pretty print interface for Token.
def pretty_print(q)
q.group do
q.text(type.to_s)
@@ -300,6 +394,7 @@ module Prism
end
end
+ # Returns true if the given other token is equal to this token.
def ==(other)
other.is_a?(Token) &&
other.type == type &&