Class: Puppet::Pops::Parser::Locator::SubLocator
- Inherits:
-
AbstractLocator
- Object
- Puppet::Pops::Parser::Locator
- AbstractLocator
- Puppet::Pops::Parser::Locator::SubLocator
- Defined in:
- lib/puppet/pops/parser/locator.rb
Overview
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.
Instance Attribute Summary collapse
- #has_margin ⇒ Object readonly
- #leading_line_count ⇒ Object readonly
- #leading_offset ⇒ Object readonly
- #locator ⇒ Object readonly
- #margin_per_line ⇒ Object readonly
Attributes inherited from AbstractLocator
Instance Method Summary collapse
-
#char_length(offset, end_offset) ⇒ Object
Do not call this method.
-
#char_offset(offset) ⇒ Object
Do not call this method.
- #file ⇒ Object
-
#initialize(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line) ⇒ SubLocator
constructor
A new instance of SubLocator.
-
#to_global(offset, length) ⇒ Object
Returns array with transposed (local) offset and (local) length.
Methods inherited from AbstractLocator
#ary_bsearch_i, #eql?, #hash, #line_for_offset, #pos_on_line, #to_location_hash
Methods inherited from Puppet::Pops::Parser::Locator
compute_line_index, #extract_text, #extract_tree_text, #line_for_offset, #line_index, locator, #offset_on_line, #pos_on_line, #string, #to_s, #to_uri
Constructor Details
#initialize(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line) ⇒ SubLocator
Returns a new instance of SubLocator.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/puppet/pops/parser/locator.rb', line 227 def initialize(locator, str, leading_line_count, leading_offset, has_margin, margin_per_line) super(str, locator.file) @locator = locator @leading_line_count = leading_line_count @leading_offset = leading_offset @has_margin = has_margin @margin_per_line = margin_per_line # Since lines can have different margin - accumulated margin per line must be computed # and since this accumulated margin adjustment is needed more than once; both for start offset, # and for end offset (to compute global length) it is computed up front here. # The accumulated_offset holds the sum of all removed margins before a position on line n (line index is 1-n, # and (unused) position 0 is always 0). # The last entry is duplicated since there will be the line "after last line" that would otherwise require # conditional logic. # @accumulated_margin = margin_per_line.each_with_object([0]) { |val, memo| memo << memo[-1] + val; } @accumulated_margin << @accumulated_margin[-1] end |
Instance Attribute Details
#has_margin ⇒ Object (readonly)
224 225 226 |
# File 'lib/puppet/pops/parser/locator.rb', line 224 def has_margin @has_margin end |
#leading_line_count ⇒ Object (readonly)
222 223 224 |
# File 'lib/puppet/pops/parser/locator.rb', line 222 def leading_line_count @leading_line_count end |
#leading_offset ⇒ Object (readonly)
223 224 225 |
# File 'lib/puppet/pops/parser/locator.rb', line 223 def leading_offset @leading_offset end |
#locator ⇒ Object (readonly)
221 222 223 |
# File 'lib/puppet/pops/parser/locator.rb', line 221 def locator @locator end |
#margin_per_line ⇒ Object (readonly)
225 226 227 |
# File 'lib/puppet/pops/parser/locator.rb', line 225 def margin_per_line @margin_per_line end |
Instance Method Details
#char_length(offset, end_offset) ⇒ Object
Do not call this method
287 288 289 |
# File 'lib/puppet/pops/parser/locator.rb', line 287 def char_length(offset, end_offset) raise "Should not be called" end |
#char_offset(offset) ⇒ Object
Do not call this method
282 283 284 |
# File 'lib/puppet/pops/parser/locator.rb', line 282 def char_offset(offset) raise "Should not be called" end |
#file ⇒ Object
247 248 249 |
# File 'lib/puppet/pops/parser/locator.rb', line 247 def file @locator.file end |
#to_global(offset, length) ⇒ Object
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.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/puppet/pops/parser/locator.rb', line 265 def to_global(offset, length) # simple case, no margin return [offset + @leading_offset, length] unless @has_margin # compute local start and end line start_line = line_for_offset(offset) end_line = line_for_offset(offset + length) # complex case when there is a margin transposed_offset = offset == 0 ? @leading_offset : offset + @leading_offset + @accumulated_margin[start_line] transposed_length = length + @accumulated_margin[end_line] - @accumulated_margin[start_line] + # the margins between start and end (0 is line 1) (offset_on_line(offset) == 0 ? margin_per_line[start_line - 1] : 0) # include start's margin in position 0 [transposed_offset, transposed_length] end |