ligo/vendors/ligo-utils/simple-utils/pos.ml

147 lines
3.8 KiB
OCaml
Raw Normal View History

2019-05-13 00:46:25 +04:00
type t = <
byte : Lexing.position;
point_num : int;
point_bol : int;
file : string;
line : int;
set_file : string -> t;
set_line : int -> t;
set_offset : int -> t;
set : file:string -> line:int -> offset:int -> t;
new_line : string -> t;
add_nl : t;
shift_bytes : int -> t;
shift_one_uchar : int -> t;
offset : [`Byte | `Point] -> int;
column : [`Byte | `Point] -> int;
line_offset : [`Byte | `Point] -> int;
byte_offset : int;
is_ghost : bool;
2020-01-20 13:57:07 +04:00
to_string :
?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
compact :
?file:bool -> ?offsets:bool -> [`Byte | `Point] -> string;
2019-05-13 00:46:25 +04:00
>
type pos = t
(* Constructors *)
let sprintf = Printf.sprintf
let make ~byte ~point_num ~point_bol =
let () = assert (point_num >= point_bol) in
object (self)
val byte = byte
method byte = byte
val point_num = point_num
method point_num = point_num
val point_bol = point_bol
method point_bol = point_bol
method set_file file =
{< byte = Lexing.{byte with pos_fname = file} >}
method set_line line =
{< byte = Lexing.{byte with pos_lnum = line} >}
method set_offset offset =
{< byte = Lexing.{byte with pos_cnum = byte.pos_bol + offset} >}
method set ~file ~line ~offset =
let pos = self#set_file file in
2019-05-13 00:46:25 +04:00
let pos = pos#set_line line in
let pos = pos#set_offset offset
in pos
method shift_bytes len =
{< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len};
point_num = point_num + len >}
method shift_one_uchar len =
{< byte = Lexing.{byte with pos_cnum = byte.pos_cnum + len};
point_num = point_num + 1 >}
method add_nl =
{< byte = Lexing.{byte with
pos_lnum = byte.pos_lnum + 1;
pos_bol = byte.pos_cnum};
point_bol = point_num >}
2020-01-20 13:57:07 +04:00
(* The string must not contain '\n'. See [add_line]. *)
2019-05-13 00:46:25 +04:00
method new_line string =
let len = String.length string
in (self#shift_bytes len)#add_nl
2020-01-20 13:57:07 +04:00
method is_ghost = (byte = Lexing.dummy_pos)
2019-05-13 00:46:25 +04:00
method file = byte.Lexing.pos_fname
method line = byte.Lexing.pos_lnum
method offset = function
`Byte -> Lexing.(byte.pos_cnum - byte.pos_bol)
| `Point -> point_num - point_bol
method column mode = 1 + self#offset mode
method line_offset = function
`Byte -> byte.Lexing.pos_bol
| `Point -> point_bol
method byte_offset = byte.Lexing.pos_cnum
2020-01-20 13:57:07 +04:00
method to_string ?(file=true) ?(offsets=true) mode =
2019-05-13 00:46:25 +04:00
if self#is_ghost then "ghost"
else
let offset = self#offset mode in
2020-01-20 13:57:07 +04:00
let horizontal, value =
if offsets then
"character", offset
else "column", offset + 1 in
if file && self#file <> "" then
sprintf "File \"%s\", line %i, %s %i"
self#file self#line horizontal value
else sprintf "Line %i, %s %i"
self#line horizontal value
method compact ?(file=true) ?(offsets=true) mode =
if self#is_ghost then "ghost"
else
let horizontal =
if offsets then self#offset mode
else self#column mode in
if file && self#file <> "" then
sprintf "%s:%i:%i" self#file self#line horizontal
else
sprintf "%i:%i" self#line horizontal
2019-05-13 00:46:25 +04:00
end
let from_byte byte =
let point_num = byte.Lexing.pos_cnum
and point_bol = byte.Lexing.pos_bol
in make ~byte ~point_num ~point_bol
2019-05-13 00:46:25 +04:00
let ghost = make ~byte:Lexing.dummy_pos ~point_num:(-1) ~point_bol:(-1)
let min ~file =
2020-01-20 13:57:07 +04:00
let pos = make ~byte:Lexing.dummy_pos ~point_num:0 ~point_bol:0
in pos#set_file file
2019-05-13 00:46:25 +04:00
(* Comparisons *)
let equal pos1 pos2 =
pos1#file = pos2#file && pos1#byte_offset = pos2#byte_offset
let lt pos1 pos2 =
pos1#file = pos2#file && pos1#byte_offset < pos2#byte_offset