1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
module KPeg
module Position
# STANDALONE START
def current_column(target=pos)
if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1)
return target - c
elsif c = string.rindex("\n", target)
return target - c
end
target + 1
end
def position_line_offsets
unless @position_line_offsets
@position_line_offsets = []
total = 0
string.each_line do |line|
total += line.size
@position_line_offsets << total
end
end
@position_line_offsets
end
if [].respond_to? :bsearch_index
def current_line(target=pos)
if line = position_line_offsets.bsearch_index {|x| x > target }
return line + 1
end
raise "Target position #{target} is outside of string"
end
else
def current_line(target=pos)
if line = position_line_offsets.index {|x| x > target }
return line + 1
end
raise "Target position #{target} is outside of string"
end
end
def current_character(target=pos)
if target < 0 || target >= string.size
raise "Target position #{target} is outside of string"
end
string[target, 1]
end
KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char)
def current_pos_info(target=pos)
l = current_line target
c = current_column target
ln = get_line(l-1)
chr = string[target,1]
KpegPosInfo.new(target, l, c, ln, chr)
end
def lines
string.lines
end
def get_line(no)
loff = position_line_offsets
if no < 0
raise "Line No is out of range: #{no} < 0"
elsif no >= loff.size
raise "Line No is out of range: #{no} >= #{loff.size}"
end
lend = loff[no]-1
lstart = no > 0 ? loff[no-1] : 0
string[lstart..lend]
end
# STANDALONE END
end
end
|