Class: Parslet::Source::LineCache
- Inherits:
-
Object
- Object
- Parslet::Source::LineCache
- Defined in:
- lib/parslet/source/line_cache.rb
Overview
A cache for line start positions.
Instance Method Summary collapse
-
#initialize ⇒ LineCache
constructor
A new instance of LineCache.
-
#line_and_column(pos) ⇒ Object
Returns a <line, column> tuple for the given input position.
- #scan_for_line_endings(start_pos, buf) ⇒ Object
Constructor Details
#initialize ⇒ LineCache
Returns a new instance of LineCache.
7 8 9 10 11 12 13 14 |
# 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 @last_line_end = nil end |
Instance Method Details
#line_and_column(pos) ⇒ Object
Returns a <line, column> tuple for the given input position. Input position must be given as byte offset into original string.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/parslet/source/line_cache.rb', line 19 def line_and_column(pos) pos = pos.bytepos if pos.respond_to? :bytepos 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
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/parslet/source/line_cache.rb', line 36 def scan_for_line_endings(start_pos, buf) return unless buf buf = StringScanner.new(buf) return unless buf.exist?(/\n/) ## 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. buf.pos = @last_line_end - start_pos end ## Scan the string for line endings; store the positions of all endings ## in @line_ends. while buf.skip_until(/\n/) @last_line_end = start_pos + buf.pos @line_ends << @last_line_end end end |