Class: Parser::Source::Map
- Inherits:
-
Object
- Object
- Parser::Source::Map
- Defined in:
- lib/parser/source/map.rb
Overview
Map relates AST nodes to the source code they were parsed from. More specifically, a Map or its subclass contains a set of ranges:
expression
: smallest range which includes all source corresponding to the node and allexpression
ranges of its children.- other ranges (
begin
,end
,operator
, ...): node-specific ranges pointing to various interesting tokens corresponding to the node.
Note that the Heredoc map is the only one whose expression
does
not include other ranges. It only covers the heredoc marker (<<HERE
),
not the here document itself.
All ranges except expression
are defined by Map subclasses.
Ranges (except expression
) can be nil
if the corresponding token is
not present in source. For example, a hash may not have opening/closing
braces, and so would its source map.
p Parser::CurrentRuby.parse('[1 => 2]').children[0].loc
# => <Parser::Source::Map::Collection:0x007f5492b547d8
# @end=nil, @begin=nil,
# @expression=#<Source::Range (string) 1...7>>
The AST_FORMAT document describes how ranges associated to source code tokens. For example, the entry
(array (int 1) (int 2))
"[1, 2]"
^ begin
^ end
~~~~~~ expression
means that if node
is an AST::Node (array (int 1) (int 2))
,
then node.loc
responds to begin
, end
and expression
, and
node.loc.begin
returns a range pointing at the opening bracket, and so on.
If you want to write code polymorphic by the source map (i.e. accepting
several subclasses of Map), use respond_to?
instead of is_a?
to
check whether the map features the range you need. Concrete Map
subclasses may not be preserved between versions, but their interfaces
will be kept compatible.
You can visualize the source maps with ruby-parse -E
command-line tool.
Direct Known Subclasses
Collection, Condition, Constant, Definition, For, Heredoc, Keyword, Operator, RescueBody, Send, Ternary, Variable
Defined Under Namespace
Classes: Collection, Condition, Constant, Definition, For, Heredoc, Keyword, Operator, RescueBody, Send, Ternary, Variable
Instance Attribute Summary collapse
- #expression ⇒ Range readonly
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compares source maps.
-
#column ⇒ Integer
A shortcut for
self.expression.column
. -
#initialize(expression) ⇒ Map
constructor
A new instance of Map.
-
#line ⇒ Integer
A shortcut for
self.expression.line
. -
#to_hash ⇒ Hash(Symbol, Parser::Source::Range)
Converts this source map to a hash with keys corresponding to ranges.
Constructor Details
#initialize(expression) ⇒ Map
Returns a new instance of Map.
69 70 71 72 73 |
# File 'lib/parser/source/map.rb', line 69 def initialize(expression) @expression = expression freeze end |
Instance Attribute Details
#expression ⇒ Range (readonly)
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/parser/source/map.rb', line 64 class Map attr_reader :expression ## # @param [Range] expression def initialize(expression) @expression = expression freeze end ## # A shortcut for `self.expression.line`. # @return [Integer] # def line @expression.line end ## # A shortcut for `self.expression.column`. # @return [Integer] # def column @expression.column end ## # @api private # def with_expression(expression_l) with { |map| map.update_expression(expression_l) } end ## # Compares source maps. # @return [Boolean] # def ==(other) other.class == self.class && instance_variables.map do |ivar| instance_variable_get(ivar) == other.send(:instance_variable_get, ivar) end.reduce(:&) end ## # Converts this source map to a hash with keys corresponding to # ranges. For example, if called on an instance of {Collection}, # which adds the `begin` and `end` ranges, the resulting hash # will contain keys `:expression`, `:begin` and `:end`. # # @example # require 'parser/current' # # p Parser::CurrentRuby.parse('[1, 2]').loc.to_hash # # => { # # :begin => #<Source::Range (string) 0...1>, # # :end => #<Source::Range (string) 5...6>, # # :expression => #<Source::Range (string) 0...6> # # } # # @return [Hash(Symbol, Parser::Source::Range)] # def to_hash Hash[instance_variables.map do |ivar| [ ivar[1..-1].to_sym, instance_variable_get(ivar) ] end] end protected def with(&block) dup.tap(&block).freeze end def update_expression(expression_l) @expression = expression_l end end |
Instance Method Details
#==(other) ⇒ Boolean
Compares source maps.
102 103 104 105 106 107 108 |
# File 'lib/parser/source/map.rb', line 102 def ==(other) other.class == self.class && instance_variables.map do |ivar| instance_variable_get(ivar) == other.send(:instance_variable_get, ivar) end.reduce(:&) end |
#column ⇒ Integer
A shortcut for self.expression.column
.
87 88 89 |
# File 'lib/parser/source/map.rb', line 87 def column @expression.column end |
#line ⇒ Integer
A shortcut for self.expression.line
.
79 80 81 |
# File 'lib/parser/source/map.rb', line 79 def line @expression.line end |
#to_hash ⇒ Hash(Symbol, Parser::Source::Range)
Converts this source map to a hash with keys corresponding to
ranges. For example, if called on an instance of Collection,
which adds the begin
and end
ranges, the resulting hash
will contain keys :expression
, :begin
and :end
.
128 129 130 131 132 |
# File 'lib/parser/source/map.rb', line 128 def to_hash Hash[instance_variables.map do |ivar| [ ivar[1..-1].to_sym, instance_variable_get(ivar) ] end] end |