169 lines
4.1 KiB
OCaml
169 lines
4.1 KiB
OCaml
|
|
module Sexp = struct
|
||
|
|
type t =
|
||
|
|
| Atom of string
|
||
|
|
| List of t list
|
||
|
|
end
|
||
|
|
|
||
|
|
module Csexp = Csexp.Make (Sexp)
|
||
|
|
open Csexp
|
||
|
|
|
||
|
|
let roundtrip x =
|
||
|
|
let str = to_string x in
|
||
|
|
match parse_string str with
|
||
|
|
| Error (_, msg) -> failwith msg
|
||
|
|
| Ok exp ->
|
||
|
|
assert (exp = x);
|
||
|
|
print_string str
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
roundtrip (Sexp.Atom "foo");
|
||
|
|
[%expect {|3:foo|}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
roundtrip (Sexp.List []);
|
||
|
|
[%expect {|()|}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
roundtrip (Sexp.List [ Sexp.Atom "Hello"; Sexp.Atom "World!" ]);
|
||
|
|
[%expect {|(5:Hello6:World!)|}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
roundtrip
|
||
|
|
(Sexp.List
|
||
|
|
[ Sexp.List
|
||
|
|
[ Sexp.Atom "metadata"
|
||
|
|
; Sexp.List [ Sexp.Atom "foo"; Sexp.Atom "bar" ]
|
||
|
|
]
|
||
|
|
; Sexp.List
|
||
|
|
[ Sexp.Atom "produced-files"
|
||
|
|
; Sexp.List
|
||
|
|
[ Sexp.List
|
||
|
|
[ Sexp.Atom "/tmp/coin"
|
||
|
|
; Sexp.Atom
|
||
|
|
"/tmp/dune-memory/v2/files/b2/b295e63b0b8e8fae971d9c493be0d261.1"
|
||
|
|
]
|
||
|
|
]
|
||
|
|
]
|
||
|
|
]);
|
||
|
|
[%expect
|
||
|
|
{|((8:metadata(3:foo3:bar))(14:produced-files((9:/tmp/coin63:/tmp/dune-memory/v2/files/b2/b295e63b0b8e8fae971d9c493be0d261.1))))|}]
|
||
|
|
|
||
|
|
let print_parsed r =
|
||
|
|
match r with
|
||
|
|
| Error msg -> Printf.printf "Error %S" msg
|
||
|
|
| Ok sexp -> Printf.printf "Ok %S" (Csexp.to_string sexp)
|
||
|
|
|
||
|
|
let parse s =
|
||
|
|
match parse_string s with
|
||
|
|
| Ok x -> print_parsed (Ok x)
|
||
|
|
| Error (_, msg) -> print_parsed (Error msg)
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(3:foo)";
|
||
|
|
[%expect {|
|
||
|
|
Ok "(3:foo)" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "";
|
||
|
|
[%expect {| Error "premature end of input" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(";
|
||
|
|
[%expect {| Error "premature end of input" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(a)";
|
||
|
|
[%expect {| Error "invalid character 'a', expected '(', ')' or '0'..'9'" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(:)";
|
||
|
|
[%expect {| Error "invalid character ':', expected '(', ')' or '0'..'9'" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(4:foo)";
|
||
|
|
[%expect {| Error "premature end of input" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(5:foo)";
|
||
|
|
[%expect {| Error "premature end of input" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(3:foo)";
|
||
|
|
[%expect {| Ok "(3:foo)" |}]
|
||
|
|
|
||
|
|
let sexp_then_stuff s =
|
||
|
|
let fn, oc = Filename.open_temp_file "csexp-test" "" ~mode:[ Open_binary ] in
|
||
|
|
let delete = lazy (Sys.remove fn) in
|
||
|
|
at_exit (fun () -> Lazy.force delete);
|
||
|
|
output_string oc s;
|
||
|
|
close_out oc;
|
||
|
|
let ic = open_in_bin fn in
|
||
|
|
Csexp.input ic |> print_parsed;
|
||
|
|
print_newline ();
|
||
|
|
print_char (input_char ic);
|
||
|
|
close_in ic;
|
||
|
|
Lazy.force delete
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
sexp_then_stuff "(3:foo)(3:foo)";
|
||
|
|
[%expect {|
|
||
|
|
Ok "(3:foo)"
|
||
|
|
( |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
sexp_then_stuff "(3:foo)Additional_stuff";
|
||
|
|
[%expect {|
|
||
|
|
Ok "(3:foo)"
|
||
|
|
A |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(3:foo)(3:foo)";
|
||
|
|
[%expect {| Error "data after canonical S-expression" |}]
|
||
|
|
|
||
|
|
let%expect_test _ =
|
||
|
|
parse "(3:foo)additional_stuff";
|
||
|
|
[%expect {| Error "data after canonical S-expression" |}]
|
||
|
|
|
||
|
|
let parse_many s =
|
||
|
|
match parse_string_many s with
|
||
|
|
| Error (_, msg) -> print_parsed (Error msg)
|
||
|
|
| Ok xs -> xs |> List.iter (fun x -> print_parsed (Ok x))
|
||
|
|
|
||
|
|
let%expect_test "parse_string_many - parse empty string" =
|
||
|
|
parse_many "";
|
||
|
|
[%expect {| |}]
|
||
|
|
|
||
|
|
let%expect_test "parse_string_many - parse a single csexp" =
|
||
|
|
parse_many "(3:foo)";
|
||
|
|
[%expect {| Ok "(3:foo)" |}]
|
||
|
|
|
||
|
|
let%expect_test "parse_string_many - parse many csexp" =
|
||
|
|
parse_many "(3:foo)(3:bar)";
|
||
|
|
[%expect {| Ok "(3:foo)"Ok "(3:bar)" |}]
|
||
|
|
|
||
|
|
let%expect_test "serialised_length" =
|
||
|
|
let csexp = Sexp.Atom "xxx" in
|
||
|
|
print_endline (Csexp.to_string csexp);
|
||
|
|
print_int (Csexp.serialised_length csexp);
|
||
|
|
[%expect {|
|
||
|
|
3:xxx
|
||
|
|
5 |}];
|
||
|
|
let csexp = Sexp.List [] in
|
||
|
|
print_endline (Csexp.to_string csexp);
|
||
|
|
print_int (Csexp.serialised_length csexp);
|
||
|
|
[%expect {|
|
||
|
|
()
|
||
|
|
2 |}];
|
||
|
|
let csexp = Sexp.List [ Atom "xxx" ] in
|
||
|
|
print_endline (Csexp.to_string csexp);
|
||
|
|
print_int (Csexp.serialised_length csexp);
|
||
|
|
[%expect {|
|
||
|
|
(3:xxx)
|
||
|
|
7 |}];
|
||
|
|
let csexp = Sexp.List [ Atom "xxx"; Atom "xxx" ] in
|
||
|
|
print_endline (Csexp.to_string csexp);
|
||
|
|
print_int (Csexp.serialised_length csexp);
|
||
|
|
[%expect {|
|
||
|
|
(3:xxx3:xxx)
|
||
|
|
12 |}]
|