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)
-
- (Range) expression
readonly
-
- (Parser::AST::Node) node
readonly
The node that is described by this map.
Instance Method Summary (collapse)
-
- (Boolean) ==(other)
Compares source maps.
-
- (Integer) column
A shortcut for
self.expression.column
. -
- (Map) initialize(expression)
constructor
A new instance of Map.
-
- (Integer) line
A shortcut for
self.expression.line
. -
- (Hash(Symbol, Parser::Source::Range)) to_hash
Converts this source map to a hash with keys corresponding to ranges.
Constructor Details
- (Map) initialize(expression)
Returns a new instance of Map
74 75 76 |
# File 'lib/parser/source/map.rb', line 74 def initialize(expression) @expression = expression end |
Instance Attribute Details
- (Range) expression (readonly)
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/parser/source/map.rb', line 68 class Map attr_reader :node attr_reader :expression ## # @param [Range] expression def initialize(expression) @expression = expression end ## # @api private def initialize_copy(other) super @node = nil end ## # @api private def node=(node) @node = node freeze @node 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 instance_variables.inject({}) do |hash, ivar| next hash if ivar == :@node hash[ivar[1..-1].to_sym] = instance_variable_get(ivar) hash end end protected def with(&block) dup.tap(&block) end def update_expression(expression_l) @expression = expression_l end end |
- (Parser::AST::Node) node
The node that is described by this map. Nodes and maps have 1:1 correspondence.
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/parser/source/map.rb', line 68 class Map attr_reader :node attr_reader :expression ## # @param [Range] expression def initialize(expression) @expression = expression end ## # @api private def initialize_copy(other) super @node = nil end ## # @api private def node=(node) @node = node freeze @node 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 instance_variables.inject({}) do |hash, ivar| next hash if ivar == :@node hash[ivar[1..-1].to_sym] = instance_variable_get(ivar) hash end end protected def with(&block) dup.tap(&block) end def update_expression(expression_l) @expression = expression_l end end |
Instance Method Details
- (Boolean) ==(other)
Compares source maps.
120 121 122 123 124 125 126 |
# File 'lib/parser/source/map.rb', line 120 def ==(other) other.class == self.class && instance_variables.map do |ivar| instance_variable_get(ivar) == other.send(:instance_variable_get, ivar) end.reduce(:&) end |
- (Integer) column
A shortcut for self.expression.column
.
105 106 107 |
# File 'lib/parser/source/map.rb', line 105 def column @expression.column end |
- (Integer) line
A shortcut for self.expression.line
.
97 98 99 |
# File 'lib/parser/source/map.rb', line 97 def line @expression.line end |
- (Hash(Symbol, Parser::Source::Range)) to_hash
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
.
146 147 148 149 150 151 152 |
# File 'lib/parser/source/map.rb', line 146 def to_hash instance_variables.inject({}) do |hash, ivar| next hash if ivar == :@node hash[ivar[1..-1].to_sym] = instance_variable_get(ivar) hash end end |