aboutsummaryrefslogtreecommitdiff
path: root/gramlib/ploc.ml
diff options
context:
space:
mode:
Diffstat (limited to 'gramlib/ploc.ml')
-rw-r--r--gramlib/ploc.ml217
1 files changed, 217 insertions, 0 deletions
diff --git a/gramlib/ploc.ml b/gramlib/ploc.ml
new file mode 100644
index 0000000000..30ae4eaa21
--- /dev/null
+++ b/gramlib/ploc.ml
@@ -0,0 +1,217 @@
+(* camlp5r *)
+(* ploc.ml,v *)
+(* Copyright (c) INRIA 2007-2017 *)
+
+#load "pa_macro.cmo";
+
+type t =
+ { fname : string;
+ line_nb : int;
+ bol_pos : int;
+ line_nb_last : int;
+ bol_pos_last : int;
+ bp : int;
+ ep : int;
+ comm : string;
+ ecomm : string }
+;
+
+value make_loc fname line_nb bol_pos (bp, ep) comm =
+ {fname = fname; line_nb = line_nb; bol_pos = bol_pos;
+ line_nb_last = line_nb; bol_pos_last = bol_pos;
+ bp = bp; ep = ep; comm = comm; ecomm = ""}
+;
+
+value make_unlined (bp, ep) =
+ {fname = ""; line_nb = 1; bol_pos = 0; line_nb_last = -1; bol_pos_last = 0;
+ bp = bp; ep = ep; comm = ""; ecomm = ""}
+;
+
+value dummy =
+ {fname = ""; line_nb = 1; bol_pos = 0; line_nb_last = -1; bol_pos_last = 0;
+ bp = 0; ep = 0; comm = ""; ecomm = ""}
+;
+
+value file_name loc = loc.fname;
+value first_pos loc = loc.bp;
+value last_pos loc = loc.ep;
+value line_nb loc = loc.line_nb;
+value bol_pos loc = loc.bol_pos;
+value line_nb_last loc = loc.line_nb_last;
+value bol_pos_last loc = loc.bol_pos_last;
+value comment loc = loc.comm;
+value comment_last loc = loc.ecomm;
+
+IFDEF OCAML_VERSION <= OCAML_1_07 OR COMPATIBLE_WITH_OLD_OCAML THEN
+ value with_bp_ep l bp ep =
+ {fname = l.fname; line_nb = l.line_nb; bol_pos = l.bol_pos;
+ line_nb_last = l.line_nb_last; bol_pos_last = l.bol_pos_last; bp = bp;
+ ep = ep; comm = l.comm; ecomm = l.ecomm}
+ ;
+ value with_comm l comm =
+ {fname = l.fname; line_nb = l.line_nb; bol_pos = l.bol_pos;
+ line_nb_last = l.line_nb_last; bol_pos_last = l.bol_pos_last; bp = l.bp;
+ ep = l.ep; comm = comm; ecomm = l.ecomm}
+ ;
+END;
+
+value encl loc1 loc2 =
+ if loc1.bp < loc2.bp then
+ if loc1.ep < loc2.ep then
+ {fname = loc1.fname; line_nb = loc1.line_nb; bol_pos = loc1.bol_pos;
+ line_nb_last = loc2.line_nb_last; bol_pos_last = loc2.bol_pos_last;
+ bp = loc1.bp; ep = loc2.ep; comm = loc1.comm; ecomm = loc2.comm}
+ else
+ loc1
+ else
+ if loc2.ep < loc1.ep then
+ {fname = loc2.fname; line_nb = loc2.line_nb; bol_pos = loc2.bol_pos;
+ line_nb_last = loc1.line_nb_last; bol_pos_last = loc1.bol_pos_last;
+ bp = loc2.bp; ep = loc1.ep; comm = loc2.comm; ecomm = loc1.comm}
+ else
+ loc2
+;
+value shift sh loc = {(loc) with bp = sh + loc.bp; ep = sh + loc.ep};
+value sub loc sh len = {(loc) with bp = loc.bp + sh; ep = loc.bp + sh + len};
+value after loc sh len =
+ {(loc) with bp = loc.ep + sh; ep = loc.ep + sh + len}
+;
+value with_comment loc comm = {(loc) with comm = comm};
+
+value name = ref "loc";
+
+value from_file fname loc =
+ let (bp, ep) = (first_pos loc, last_pos loc) in
+ try
+ let ic = open_in_bin fname in
+ let strm = Stream.of_channel ic in
+ let rec loop fname lin =
+ let rec not_a_line_dir col =
+ parser cnt
+ [ [: `c; s :] ->
+ if cnt < bp then
+ if c = '\n' then loop fname (lin + 1)
+ else not_a_line_dir (col + 1) s
+ else
+ let col = col - (cnt - bp) in
+ (fname, lin, col, col + ep - bp)
+ | [: :] ->
+ (fname, lin, col, col + 1) ]
+ in
+ let rec a_line_dir str n col =
+ parser
+ [ [: `'\n' :] -> loop str n
+ | [: `_; s :] -> a_line_dir str n (col + 1) s ]
+ in
+ let rec spaces col =
+ parser
+ [ [: `' '; s :] -> spaces (col + 1) s
+ | [: :] -> col ]
+ in
+ let rec check_string str n col =
+ parser
+ [ [: `'"'; col = spaces (col + 1); s :] -> a_line_dir str n col s
+ | [: `c when c <> '\n'; s :] ->
+ check_string (str ^ String.make 1 c) n (col + 1) s
+ | [: a = not_a_line_dir col :] -> a ]
+ in
+ let check_quote n col =
+ parser
+ [ [: `'"'; s :] -> check_string "" n (col + 1) s
+ | [: a = not_a_line_dir col :] -> a ]
+ in
+ let rec check_num n col =
+ parser
+ [ [: `('0'..'9' as c); s :] ->
+ check_num (10 * n + Char.code c - Char.code '0') (col + 1) s
+ | [: col = spaces col; s :] -> check_quote n col s ]
+ in
+ let begin_line =
+ parser
+ [ [: `'#'; col = spaces 1; s :] -> check_num 0 col s
+ | [: a = not_a_line_dir 0 :] -> a ]
+ in
+ begin_line strm
+ in
+ let r =
+ try loop fname 1 with
+ [ Stream.Failure ->
+ let bol = bol_pos loc in
+ (fname, line_nb loc, bp - bol, ep - bol) ]
+ in
+ do { close_in ic; r }
+ with
+ [ Sys_error _ -> (fname, 1, bp, ep) ]
+;
+
+value second_line fname ep0 (line, bp) ep = do {
+ let ic = open_in fname in
+ seek_in ic bp;
+ loop line bp bp where rec loop line bol p =
+ if p = ep then do {
+ close_in ic;
+ if bol = bp then (line, ep0)
+ else (line, ep - bol)
+ }
+ else do {
+ let (line, bol) =
+ match input_char ic with
+ [ '\n' -> (line + 1, p + 1)
+ | _ -> (line, bol) ]
+ in
+ loop line bol (p + 1)
+ }
+};
+
+value get loc = do {
+ if loc.fname = "" || loc.fname = "-" then do {
+ (loc.line_nb, loc.bp - loc.bol_pos, loc.line_nb, loc.ep - loc.bol_pos,
+ loc.ep - loc.bp)
+ }
+ else do {
+ let (bl, bc, ec) =
+ (loc.line_nb, loc.bp - loc.bol_pos, loc.ep - loc.bol_pos)
+ in
+ let (el, eep) = second_line loc.fname ec (bl, loc.bp) loc.ep in
+ (bl, bc, el, eep, ec - bc)
+ }
+};
+
+value call_with r v f a =
+ let saved = r.val in
+ try do {
+ r.val := v;
+ let b = f a in
+ r.val := saved;
+ b
+ }
+ with e -> do { r.val := saved; raise e }
+;
+
+exception Exc of t and exn;
+
+value raise loc exc =
+ match exc with
+ [ Exc _ _ -> raise exc
+ | _ -> raise (Exc loc exc) ]
+;
+
+type vala 'a =
+ [ VaAnt of string
+ | VaVal of 'a ]
+;
+
+value warned = ref True;
+value warning_deprecated_since_6_00 name =
+ if not warned.val then do {
+ Printf.eprintf "<W> %s deprecated since version 6.00" name;
+ warned.val := True
+ }
+ else ()
+;
+
+value make line_nb bol_pos (bp, ep) =
+ let _ = warning_deprecated_since_6_00 "Ploc.make" in
+ {fname = ""; line_nb = line_nb; bol_pos = bol_pos; line_nb_last = line_nb;
+ bol_pos_last = bol_pos; bp = bp; ep = ep; comm = ""; ecomm = ""}
+;