summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml')
-rw-r--r--ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml167
1 files changed, 167 insertions, 0 deletions
diff --git a/ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml b/ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml
new file mode 100644
index 0000000000..65202c8751
--- /dev/null
+++ b/ocaml-binary-annot/camlp4/Camlp4/Struct/Quotation.ml
@@ -0,0 +1,167 @@
+(* camlp4r *)
+(****************************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* INRIA Rocquencourt *)
+(* *)
+(* Copyright 2002-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
+ *)
+
+
+
+module Make (Ast : Sig.Camlp4Ast)
+: Sig.Quotation with module Ast = Ast
+= struct
+ module Ast = Ast;
+ module DynAst = DynAst.Make Ast;
+ module Loc = Ast.Loc;
+ open Format;
+ open Sig;
+
+ type expand_fun 'a = Loc.t -> option string -> string -> 'a;
+
+ module Exp_key = DynAst.Pack(struct
+ type t 'a = unit;
+ end);
+
+ module Exp_fun = DynAst.Pack(struct
+ type t 'a = expand_fun 'a;
+ end);
+
+ value expanders_table =
+ (ref [] : ref (list ((string * Exp_key.pack) * Exp_fun.pack)));
+
+ value default = ref "";
+ value translate = ref (fun x -> x);
+
+ value expander_name name =
+ match translate.val name with
+ [ "" -> default.val
+ | name -> name ];
+
+ value find name tag =
+ let key = (expander_name name, Exp_key.pack tag ()) in
+ Exp_fun.unpack tag (List.assoc key expanders_table.val);
+
+ value add name tag f =
+ let elt = ((name, Exp_key.pack tag ()), Exp_fun.pack tag f) in
+ expanders_table.val := [elt :: expanders_table.val];
+
+ value dump_file = ref None;
+
+ module Error = struct
+ type error =
+ [ Finding
+ | Expanding
+ | ParsingResult of Loc.t and string
+ | Locating ];
+ type t = (string * string * error * exn);
+ exception E of t;
+
+ value print ppf (name, position, ctx, exn) =
+ let name = if name = "" then default.val else name in
+ let pp x = fprintf ppf "@?@[<2>While %s %S in a position of %S:" x name position in
+ let () =
+ match ctx with
+ [ Finding -> begin
+ pp "finding quotation";
+ if expanders_table.val = [] then
+ fprintf ppf "@ There is no quotation expander available."
+ else
+ begin
+ fprintf ppf "@ @[<hv2>Available quotation expanders are:@\n";
+ List.iter begin fun ((s,t),_) ->
+ fprintf ppf "@[<2>%s@ (in@ a@ position@ of %a)@]@ "
+ s Exp_key.print_tag t
+ end expanders_table.val;
+ fprintf ppf "@]"
+ end
+ end
+ | Expanding -> pp "expanding quotation"
+ | Locating -> pp "parsing"
+ | ParsingResult loc str ->
+ let () = pp "parsing result of quotation" in
+ match dump_file.val with
+ [ Some dump_file ->
+ let () = fprintf ppf " dumping result...\n" in
+ try
+ let oc = open_out_bin dump_file in
+ begin
+ output_string oc str;
+ output_string oc "\n";
+ flush oc;
+ close_out oc;
+ fprintf ppf "%a:" Loc.print (Loc.set_file_name dump_file loc);
+ end
+ with _ ->
+ fprintf ppf
+ "Error while dumping result in file %S; dump aborted"
+ dump_file
+ | None ->
+ fprintf ppf
+ "\n(consider setting variable Quotation.dump_file, or using the -QD option)"
+ ]
+ ]
+ in fprintf ppf "@\n%a@]@." ErrorHandler.print exn;
+
+ value to_string x =
+ let b = Buffer.create 50 in
+ let () = bprintf b "%a" print x in Buffer.contents b;
+ end;
+ let module M = ErrorHandler.Register Error in ();
+ open Error;
+
+ value expand_quotation loc expander pos_tag quot =
+ debug quot "expand_quotation: name: %s, str: %S@." quot.q_name quot.q_contents in
+ let loc_name_opt = if quot.q_loc = "" then None else Some quot.q_loc in
+ try expander loc loc_name_opt quot.q_contents with
+ [ Loc.Exc_located _ (Error.E _) as exc ->
+ raise exc
+ | Loc.Exc_located iloc exc ->
+ let exc1 = Error.E (quot.q_name, pos_tag, Expanding, exc) in
+ raise (Loc.Exc_located iloc exc1)
+ | exc ->
+ let exc1 = Error.E (quot.q_name, pos_tag, Expanding, exc) in
+ raise (Loc.Exc_located loc exc1) ];
+
+ value parse_quotation_result parse loc quot pos_tag str =
+ try parse loc str with
+ [ Loc.Exc_located iloc (Error.E (n, pos_tag, Expanding, exc)) ->
+ let ctx = ParsingResult iloc quot.q_contents in
+ let exc1 = Error.E (n, pos_tag, ctx, exc) in
+ raise (Loc.Exc_located iloc exc1)
+ | Loc.Exc_located iloc (Error.E _ as exc) ->
+ raise (Loc.Exc_located iloc exc)
+ | Loc.Exc_located iloc exc ->
+ let ctx = ParsingResult iloc quot.q_contents in
+ let exc1 = Error.E (quot.q_name, pos_tag, ctx, exc) in
+ raise (Loc.Exc_located iloc exc1) ];
+
+ value expand loc quotation tag =
+ let pos_tag = DynAst.string_of_tag tag in
+ let name = quotation.q_name in
+ debug quot "handle_quotation: name: %s, str: %S@." name quotation.q_contents in
+ let expander =
+ try find name tag
+ with
+ [ Loc.Exc_located _ (Error.E _) as exc -> raise exc
+ | Loc.Exc_located qloc exc ->
+ raise (Loc.Exc_located qloc (Error.E (name, pos_tag, Finding, exc)))
+ | exc ->
+ raise (Loc.Exc_located loc (Error.E (name, pos_tag, Finding, exc))) ]
+ in
+ let loc = Loc.join (Loc.move `start quotation.q_shift loc) in
+ expand_quotation loc expander pos_tag quotation;
+
+end;