type t = { text : string; pos : int; right_boundary : int } let overran cursor = cursor.pos >= cursor.right_boundary let next_char cursor = { cursor with pos = cursor.pos + 1 } let char_at cur offset = String.get cur.text (cur.pos + offset) let char cur = String.get cur.text cur.pos let distance a b = b.pos - a.pos let sub ?left ?right cur = { cur with pos = Option.value left ~default:cur.pos; right_boundary = Option.value right ~default:cur.right_boundary } let unwrap num cur = sub ~left:(cur.pos+num) ~right:(cur.right_boundary-num) cur let segment_string cur = String.sub cur.text cur.pos (cur.right_boundary - cur.pos) (*todo: reconsider +1 result and type cursor*) let rec find_end e = function | cur when cur.pos + 1 = String.length cur.text -> Some cur.pos | cur when overran cur -> None | cur when e cur (char cur) -> Some (cur.pos + 1) | cur -> find_end e (next_char cur)