struct
type cp =
| String of string
| Int of int
| Float of float
| List of cp list
| Tuple of cp list
| Section of (string * cp) list
module Parse = struct
let lexer = Genlex.make_lexer ["="; "{"; "}"; "["; "]"; ";"; "("; ")"; ","]
let rec file l (strm__ : _ Stream.t) = match try Some (ident strm__) with Stream.Failure -> None with Some id -> begin match Stream.peek strm__ with Some (Genlex.Kwd "=") -> Stream.junk strm__; let v = try value strm__ with Stream.Failure -> raise (Stream.Error "") in begin try file ((id, v) :: l) strm__ with Stream.Failure -> raise (Stream.Error "") end | _ -> raise (Stream.Error "") end | _ -> List.rev l
and value (strm__ : _ Stream.t) = match Stream.peek strm__ with Some (Genlex.Kwd "{") -> Stream.junk strm__; let v = try file [] strm__ with Stream.Failure -> raise (Stream.Error "") in begin match Stream.peek strm__ with Some (Genlex.Kwd "}") -> Stream.junk strm__; Section v | _ -> raise (Stream.Error "") end | Some (Genlex.Ident s) -> Stream.junk strm__; String s | Some (Genlex.String s) -> Stream.junk strm__; String s | Some (Genlex.Int i) -> Stream.junk strm__; Int i | Some (Genlex.Float f) -> Stream.junk strm__; Float f | Some (Genlex.Char c) -> Stream.junk strm__; String (String.make 1 c) | Some (Genlex.Kwd "[") -> Stream.junk strm__; let v = try list [] strm__ with Stream.Failure -> raise (Stream.Error "") in List v | Some (Genlex.Kwd "(") -> Stream.junk strm__; let v = try list [] strm__ with Stream.Failure -> raise (Stream.Error "") in Tuple v | _ -> raise Stream.Failure
and ident (strm__ : _ Stream.t) = match Stream.peek strm__ with Some (Genlex.Ident s) -> Stream.junk strm__; s | Some (Genlex.String s) -> Stream.junk strm__; s | _ -> raise Stream.Failure
and list l (strm__ : _ Stream.t) = match Stream.peek strm__ with Some (Genlex.Kwd ";") -> Stream.junk strm__; begin try list l strm__ with Stream.Failure -> raise (Stream.Error "") end | Some (Genlex.Kwd ",") -> Stream.junk strm__; begin try list l strm__ with Stream.Failure -> raise (Stream.Error "") end | _ -> match try Some (value strm__) with Stream.Failure -> None with Some v -> begin try list (v :: l) strm__ with Stream.Failure -> raise (Stream.Error "") end | _ -> match Stream.peek strm__ with Some (Genlex.Kwd "]") -> Stream.junk strm__; List.rev l | Some (Genlex.Kwd ")") -> Stream.junk strm__; List.rev l | _ -> raise Stream.Failure
end
open Format
let rec save formatter = function
| String s -> fprintf formatter "%s" (safe_string s)
| Int i -> fprintf formatter "%d" i
| Float f -> fprintf formatter "%g" f
| List l ->
fprintf formatter "[@[<b0>";
list_iter_between
(fun v -> fprintf formatter "@[<b2>"; save formatter v; fprintf formatter "@]")
(fun () -> fprintf formatter ";@ ")
l;
fprintf formatter "@]]"
| Tuple l ->
fprintf formatter "(@[<b0>";
list_iter_between
(fun v -> fprintf formatter "@[<b2>"; save formatter v; fprintf formatter "@]")
(fun () -> fprintf formatter ",@ ")
l;
fprintf formatter "@])"
| Section l ->
fprintf formatter "{@;<0 2>@[<hv0>";
list_iter_between
(fun (name,value) ->
fprintf formatter "@[<hov2>%s =@ @[<b2>" name;
save formatter value;
fprintf formatter "@]@]";)
(fun () -> fprintf formatter "@;<2 0>")
l;
fprintf formatter "@]}"
let to_channel out_channel r =
let f = formatter_of_out_channel out_channel in
fprintf f "@[<b2>"; save f r; fprintf f "@]@?"
let of_string s = s |> Stream.of_string |> Parse.lexer |> Parse.value
let of_channel in_channel =
let result = in_channel |> Stream.of_channel |> Parse.lexer |> Parse.file [] in
close_in in_channel;
result
end