summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml')
-rw-r--r--ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml307
1 files changed, 307 insertions, 0 deletions
diff --git a/ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml b/ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml
new file mode 100644
index 0000000000..ac42d4b1c4
--- /dev/null
+++ b/ocaml-binary-annot/camlp4/Camlp4/Struct/Loc.ml
@@ -0,0 +1,307 @@
+(****************************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* INRIA Rocquencourt *)
+(* *)
+(* Copyright 2006 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed under *)
+(* the terms of the GNU Library General Public License, with the special *)
+(* exception on linking described in LICENSE at the top of the Objective *)
+(* Caml source tree. *)
+(* *)
+(****************************************************************************)
+
+(* Authors:
+ * - Daniel de Rauglaudre: initial version
+ * - Nicolas Pouillard: refactoring
+ *)
+(* camlp4r *)
+
+open Format;
+
+(* FIXME
+ Study these 2 others implementations which change the ghost
+ handling:
+
+ type pos = ... the same ...
+
+ 1/
+
+ type loc = {
+ file_name : string;
+ start : pos;
+ stop : pos
+ };
+
+ type t =
+ [ Nowhere
+ | Ghost of loc (* the closest non ghost loc *)
+ | Concrete of loc ];
+
+ 2/
+
+ type loc = {
+ file_name : string;
+ start : pos;
+ stop : pos
+ };
+
+ type t = option loc;
+
+ 3/
+
+ type t = {
+ file_name : option string;
+ start : pos;
+ stop : pos
+ };
+
+*)
+
+type pos = {
+ line : int;
+ bol : int;
+ off : int
+};
+
+type t = {
+ file_name : string;
+ start : pos;
+ stop : pos;
+ ghost : bool
+};
+
+(* Debug section *)
+value dump_sel f x =
+ let s =
+ match x with
+ [ `start -> "`start"
+ | `stop -> "`stop"
+ | `both -> "`both"
+ | _ -> "<not-printable>" ]
+ in pp_print_string f s;
+value dump_pos f x =
+ fprintf f "@[<hov 2>{ line = %d ;@ bol = %d ;@ off = %d } : pos@]"
+ x.line x.bol x.off;
+value dump_long f x =
+ fprintf f
+ "@[<hov 2>{ file_name = %s ;@ start = %a (%d-%d);@ stop = %a (%d);@ ghost = %b@ } : Loc.t@]"
+ x.file_name dump_pos x.start (x.start.off - x.start.bol)
+ (x.stop.off - x.start.bol) dump_pos x.stop
+ (x.stop.off - x.stop.bol) x.ghost;
+value dump f x =
+ fprintf f "[%S: %d:%d-%d %d:%d%t]"
+ x.file_name x.start.line (x.start.off - x.start.bol)
+ (x.stop.off - x.start.bol) x.stop.line (x.stop.off - x.stop.bol)
+ (fun o -> if x.ghost then fprintf o " (ghost)" else ());
+
+value start_pos = { line = 1 ; bol = 0 ; off = 0 };
+
+value ghost =
+ { file_name = "ghost-location";
+ start = start_pos;
+ stop = start_pos;
+ ghost = True };
+
+value mk file_name =
+ debug loc "mk %s@\n" file_name in
+ { file_name = file_name;
+ start = start_pos;
+ stop = start_pos;
+ ghost = False };
+
+value of_tuple (file_name, start_line, start_bol, start_off,
+ stop_line, stop_bol, stop_off, ghost) =
+ { file_name = file_name;
+ start = { line = start_line ; bol = start_bol ; off = start_off };
+ stop = { line = stop_line ; bol = stop_bol ; off = stop_off };
+ ghost = ghost };
+
+value to_tuple
+ { file_name = file_name;
+ start = { line = start_line ; bol = start_bol ; off = start_off };
+ stop = { line = stop_line ; bol = stop_bol ; off = stop_off };
+ ghost = ghost } =
+ (file_name, start_line, start_bol, start_off,
+ stop_line, stop_bol, stop_off, ghost);
+
+value pos_of_lexing_position p =
+ let pos =
+ { line = p.Lexing.pos_lnum ;
+ bol = p.Lexing.pos_bol ;
+ off = p.Lexing.pos_cnum } in
+ debug loc "pos_of_lexing_position: %a@\n" dump_pos pos in
+ pos;
+
+value pos_to_lexing_position p file_name =
+ (* debug loc "pos_to_lexing_position: %a@\n" dump_pos p in *)
+ { Lexing.
+ pos_fname = file_name;
+ pos_lnum = p.line ;
+ pos_bol = p.bol ;
+ pos_cnum = p.off };
+
+value better_file_name a b =
+ match (a, b) with
+ [ ("", "") -> a
+ | ("", x) -> x
+ | (x, "") -> x
+ | ("-", x) -> x
+ | (x, "-") -> x
+ | (x, _) -> x ];
+
+value of_lexbuf lb =
+ let start = Lexing.lexeme_start_p lb
+ and stop = Lexing.lexeme_end_p lb in
+ let loc =
+ { file_name = better_file_name start.Lexing.pos_fname stop.Lexing.pos_fname;
+ start = pos_of_lexing_position start;
+ stop = pos_of_lexing_position stop;
+ ghost = False } in
+ debug loc "of_lexbuf: %a@\n" dump loc in
+ loc;
+
+value of_lexing_position pos =
+ let loc =
+ { file_name = pos.Lexing.pos_fname;
+ start = pos_of_lexing_position pos;
+ stop = pos_of_lexing_position pos;
+ ghost = False } in
+ debug loc "of_lexing_position: %a@\n" dump loc in
+ loc;
+
+value to_ocaml_location x =
+ debug loc "to_ocaml_location: %a@\n" dump x in
+ { Camlp4_import.Location.
+ loc_start = pos_to_lexing_position x.start x.file_name;
+ loc_end = pos_to_lexing_position x.stop x.file_name;
+ loc_ghost = x.ghost };
+
+value of_ocaml_location { Camlp4_import.Location.loc_start = a; loc_end = b; loc_ghost = g } =
+ let res =
+ { file_name = better_file_name a.Lexing.pos_fname b.Lexing.pos_fname;
+ start = pos_of_lexing_position a;
+ stop = pos_of_lexing_position b;
+ ghost = g } in
+ debug loc "of_ocaml_location: %a@\n" dump res in
+ res;
+
+value start_pos x = pos_to_lexing_position x.start x.file_name;
+value stop_pos x = pos_to_lexing_position x.stop x.file_name;
+
+value merge a b =
+ if a == b then
+ debug loc "trivial merge@\n" in
+ a
+ else
+ let r =
+ match (a.ghost, b.ghost) with
+ [ (False, False) ->
+ (* FIXME if a.file_name <> b.file_name then
+ raise (Invalid_argument
+ (sprintf "Loc.merge: Filenames must be equal: %s <> %s"
+ a.file_name b.file_name)) *)
+ (* else *)
+ { (a) with stop = b.stop }
+ | (True, True) -> { (a) with stop = b.stop }
+ | (True, _) -> { (a) with stop = b.stop }
+ | (_, True) -> { (b) with start = a.start } ]
+ in debug loc "@[<hov 6>merge %a@ %a@ %a@]@\n" dump a dump b dump r in r;
+
+value join x = { (x) with stop = x.start };
+
+value map f start_stop_both x =
+ match start_stop_both with
+ [ `start -> { (x) with start = f x.start }
+ | `stop -> { (x) with stop = f x.stop }
+ | `both -> { (x) with start = f x.start; stop = f x.stop } ];
+
+value move_pos chars x = { (x) with off = x.off + chars };
+
+value move s chars x =
+ debug loc "move %a %d %a@\n" dump_sel s chars dump x in
+ map (move_pos chars) s x;
+
+value move_line lines x =
+ debug loc "move_line %d %a@\n" lines dump x in
+ let move_line_pos x =
+ { (x) with line = x.line + lines ; bol = x.off }
+ in map move_line_pos `both x;
+
+value shift width x =
+ { (x) with start = x.stop ; stop = move_pos width x.stop };
+
+value file_name x = x.file_name;
+value start_line x = x.start.line;
+value stop_line x = x.stop.line;
+value start_bol x = x.start.bol;
+value stop_bol x = x.stop.bol;
+value start_off x = x.start.off;
+value stop_off x = x.stop.off;
+value is_ghost x = x.ghost;
+
+value set_file_name s x =
+ debug loc "set_file_name: %a@\n" dump x in
+ { (x) with file_name = s };
+
+value ghostify x =
+ debug loc "ghostify: %a@\n" dump x in
+ { (x) with ghost = True };
+
+value make_absolute x =
+ debug loc "make_absolute: %a@\n" dump x in
+ let pwd = Sys.getcwd () in
+ if Filename.is_relative x.file_name then
+ { (x) with file_name = Filename.concat pwd x.file_name }
+ else x;
+
+value strictly_before x y =
+ let b = x.stop.off < y.start.off && x.file_name = y.file_name in
+ debug loc "%a [strictly_before] %a => %b@\n" dump x dump y b in
+ b;
+
+value to_string x = do {
+ let (a, b) = (x.start, x.stop) in
+ let res = sprintf "File \"%s\", line %d, characters %d-%d"
+ x.file_name a.line (a.off - a.bol) (b.off - a.bol) in
+ if x.start.line <> x.stop.line then
+ sprintf "%s (end at line %d, character %d)"
+ res x.stop.line (b.off - b.bol)
+ else res
+};
+
+value print out x = pp_print_string out (to_string x);
+
+value check x msg =
+ if ((start_line x) > (stop_line x) ||
+ (start_bol x) > (stop_bol x) ||
+ (start_off x) > (stop_off x) ||
+ (start_line x) < 0 || (stop_line x) < 0 ||
+ (start_bol x) < 0 || (stop_bol x) < 0 ||
+ (start_off x) < 0 || (stop_off x) < 0)
+ (* Here, we don't check
+ (start_off x) < (start_bol x) || (stop_off x) < (start_bol x)
+ since the lexer is called on antiquotations, with off=0, but line and bolpos
+ have "correct" values *)
+ then do {
+ eprintf "*** Warning: (%s) strange positions ***\n%a@\n" msg print x;
+ False
+ }
+ else True;
+
+exception Exc_located of t and exn;
+
+ErrorHandler.register
+ (fun ppf ->
+ fun [ Exc_located loc exn ->
+ fprintf ppf "%a:@\n%a" print loc ErrorHandler.print exn
+ | exn -> raise exn ]);
+
+value name = ref "_loc";
+
+value raise loc exc =
+ match exc with
+ [ Exc_located _ _ -> raise exc
+ | _ -> raise (Exc_located loc exc) ]
+;