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

has_margin[R]
leading_line_count[R]
leading_offset[R]
locator[R]
margin_per_line[R]

Public Class Methods

new(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line) click to toggle source
    # File lib/puppet/pops/parser/locator.rb
223 def initialize(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line)
224   super(str, locator.file)
225   @locator = locator
226   @leading_line_count = leading_line_count
227   @leading_offset = leading_offset
228   @has_margin = has_margin
229   @margin_per_line = margin_per_line
230 
231   # Since lines can have different margin - accumulated margin per line must be computed
232   # and since this accumulated margin adjustment is needed more than once; both for start offset,
233   # and for end offset (to compute global length) it is computed up front here.
234   # The accumulated_offset holds the sum of all removed margins before a position on line n (line index is 1-n,
235   # and (unused) position 0 is always 0).
236   # The last entry is duplicated since there will be  the line "after last line" that would otherwise require
237   # conditional logic.
238   #
239   @accumulated_margin = margin_per_line.reduce([0]) {|memo, val| memo << memo[-1] + val; memo }
240   @accumulated_margin << @accumulated_margin[-1]
241 end

Public Instance Methods

char_length(offset, end_offset) click to toggle source

Do not call this method

    # File lib/puppet/pops/parser/locator.rb
283 def char_length(offset, end_offset)
284   raise "Should not be called"
285 end
char_offset(offset) click to toggle source

Do not call this method

    # File lib/puppet/pops/parser/locator.rb
278 def char_offset(offset)
279   raise "Should not be called"
280 end
file() click to toggle source
    # File lib/puppet/pops/parser/locator.rb
243 def file
244   @locator.file
245 end
to_global(offset, length) click to toggle source

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
261 def to_global(offset, length)
262   # simple case, no margin
263   return [offset + @leading_offset, length] unless @has_margin
264 
265   # compute local start and end line
266   start_line = line_for_offset(offset)
267   end_line = line_for_offset(offset+length)
268 
269   # complex case when there is a margin
270   transposed_offset = offset == 0 ? @leading_offset : offset + @leading_offset + @accumulated_margin[start_line]
271   transposed_length = length +
272     @accumulated_margin[end_line] - @accumulated_margin[start_line] +    # the margins between start and end (0 is line 1)
273     (offset_on_line(offset) == 0 ? margin_per_line[start_line - 1] : 0)  # include start's margin in position 0
274   [transposed_offset, transposed_length]
275 end