Class: Parslet::Source::LineCache

Inherits:
Object
  • Object
show all
Defined in:
lib/parslet/source/line_cache.rb

Overview

A cache for line start positions.

Instance Method Summary collapse

Constructor Details

#initializeLineCache

Returns a new instance of LineCache.



7
8
9
10
11
12
13
# File 'lib/parslet/source/line_cache.rb', line 7

def initialize
  # Stores line endings as a simple position number. The first line always
  # starts at 0; numbers beyond the biggest entry are on any line > size, 
  # but probably make a scan to that position neccessary.
  @line_ends = []
  @line_ends.extend RangeSearch
end

Instance Method Details

#line_and_column(pos) ⇒ Object

Returns a <line, column> tuple for the given input position.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/parslet/source/line_cache.rb', line 17

def line_and_column(pos)
  eol_idx = @line_ends.lbound(pos)

  if eol_idx
    # eol_idx points to the offset that ends the current line.
    # Let's try to find the offset that starts it: 
    offset = eol_idx>0 && @line_ends[eol_idx-1] || 0
    return [eol_idx+1, pos-offset+1]
  else
    # eol_idx is nil, that means that we're beyond the last line end that
    # we know about. Pretend for now that we're just on the last line.
    offset = @line_ends.last || 0
    return [@line_ends.size+1, pos-offset+1]
  end
end

#scan_for_line_endings(start_pos, buf) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/parslet/source/line_cache.rb', line 33

def scan_for_line_endings(start_pos, buf)
  return unless buf
  return unless buf.index("\n")
  cur = -1

  # If we have already read part or all of buf, we already know about
  # line ends in that portion. remove it and correct cur (search index)
  if @last_line_end && start_pos < @last_line_end
    # Let's not search the range from start_pos to last_line_end again.
    cur = @last_line_end - start_pos -1
  end

  # Scan the string for line endings; store the positions of all endings
  # in @line_ends. 
  while buf && cur = buf.index("\n", cur+1)
    @last_line_end = (start_pos + cur+1)
    @line_ends << @last_line_end
  end 
end