class Puppet::Pops::Parser::Locator::SubLocator
A Sublocator locates a concrete locator (subspace) in a virtual space. The `leading_line_count` is the (virtual) number of lines preceding the first line in the concrete locator. The `leading_offset` is the (virtual) byte offset of the first byte in the concrete locator. The `leading_line_offset` is the (virtual) offset / margin in characters for each line.
This illustrates characters in the sublocator (`.`) inside the subspace (`X`):
1:XXXXXXXX 2:XXXX.... .. ... .. 3:XXXX. . .... .. 4:XXXX............
This sublocator would be configured with leading_line_count
= 1, leading_offset
=8, and leading_line_offset=4
Note that leading_offset
must be the same for all lines and measured in characters.
A SubLocator
is only used during parsing as the parser will translate the local offsets/lengths to the parent locator when a sublocated expression is reduced. Do not call the methods `char_offset` or `char_length` as those methods will raise an error.
Attributes
Public Class Methods
Puppet::Pops::Parser::Locator::AbstractLocator::new
# File lib/puppet/pops/parser/locator.rb 222 def initialize(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line) 223 super(str, locator.file) 224 @locator = locator 225 @leading_line_count = leading_line_count 226 @leading_offset = leading_offset 227 @has_margin = has_margin 228 @margin_per_line = margin_per_line 229 230 # Since lines can have different margin - accumulated margin per line must be computed 231 # and since this accumulated margin adjustment is needed more than once; both for start offset, 232 # and for end offset (to compute global length) it is computed up front here. 233 # The accumulated_offset holds the sum of all removed margins before a position on line n (line index is 1-n, 234 # and (unused) position 0 is always 0). 235 # The last entry is duplicated since there will be the line "after last line" that would otherwise require 236 # conditional logic. 237 # 238 @accumulated_margin = margin_per_line.reduce([0]) {|memo, val| memo << memo[-1] + val; memo } 239 @accumulated_margin << @accumulated_margin[-1] 240 end
Public Instance Methods
Do not call this method
# File lib/puppet/pops/parser/locator.rb 282 def char_length(offset, end_offset) 283 raise "Should not be called" 284 end
Do not call this method
# File lib/puppet/pops/parser/locator.rb 277 def char_offset(offset) 278 raise "Should not be called" 279 end
# File lib/puppet/pops/parser/locator.rb 242 def file 243 @locator.file 244 end
Returns array with transposed (local) offset and (local) length. The transposed values take the margin into account such that it is added to the content to the right
Using X to denote margin and where end of line is explicitly shown as n: “` XXXXabcn XXXXdefn “` A local offset of 0 is translated to the start of the first heredoc line, and a length of 1 is adjusted to 5 - i.e to cover “XXXXa”. A local offset of 1, with length 1 would cover “b”. A local offset of 4 and length 1 would cover “XXXXd”
It is possible that lines have different margin and that is taken into account.
# File lib/puppet/pops/parser/locator.rb 260 def to_global(offset, length) 261 # simple case, no margin 262 return [offset + @leading_offset, length] unless @has_margin 263 264 # compute local start and end line 265 start_line = line_for_offset(offset) 266 end_line = line_for_offset(offset+length) 267 268 # complex case when there is a margin 269 transposed_offset = offset == 0 ? @leading_offset : offset + @leading_offset + @accumulated_margin[start_line] 270 transposed_length = length + 271 @accumulated_margin[end_line] - @accumulated_margin[start_line] + # the margins between start and end (0 is line 1) 272 (offset_on_line(offset) == 0 ? margin_per_line[start_line - 1] : 0) # include start's margin in position 0 273 [transposed_offset, transposed_length] 274 end