mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
feat(sexp): expose parse_string_list and the list decoder
This commit is contained in:
parent
08f333ffa8
commit
0ef454c6dc
2 changed files with 38 additions and 13 deletions
|
|
@ -231,16 +231,33 @@ module Make(Sexp : SEXP) = struct
|
||||||
| E_error (line,col,msg)
|
| E_error (line,col,msg)
|
||||||
| CCSexp_lex.Error (line,col,msg) ->
|
| CCSexp_lex.Error (line,col,msg) ->
|
||||||
Fail (Printf.sprintf "parse error at %d:%d: %s" line col msg)
|
Fail (Printf.sprintf "parse error at %d:%d: %s" line col msg)
|
||||||
|
|
||||||
|
let to_list (d:t) : _ or_error =
|
||||||
|
let rec iter acc = match next d with
|
||||||
|
| End -> Result.Ok (List.rev acc)
|
||||||
|
| Yield x -> iter (x::acc)
|
||||||
|
| Fail e -> Result.Error e
|
||||||
|
in
|
||||||
|
try iter []
|
||||||
|
with e -> Error (Printexc.to_string e)
|
||||||
end
|
end
|
||||||
|
|
||||||
let parse_string s : t or_error =
|
let dec_next_ (d:Decoder.t) : _ or_error =
|
||||||
let buf = Lexing.from_string s in
|
|
||||||
let d = Decoder.of_lexbuf buf in
|
|
||||||
match Decoder.next d with
|
match Decoder.next d with
|
||||||
| End -> Result.Error "unexpected end of file"
|
| End -> Result.Error "unexpected end of file"
|
||||||
| Yield x -> Result.Ok x
|
| Yield x -> Result.Ok x
|
||||||
| Fail s -> Result.Error s
|
| Fail s -> Result.Error s
|
||||||
|
|
||||||
|
let parse_string s : t or_error =
|
||||||
|
let buf = Lexing.from_string s in
|
||||||
|
let d = Decoder.of_lexbuf buf in
|
||||||
|
dec_next_ d
|
||||||
|
|
||||||
|
let parse_string_list s : t list or_error =
|
||||||
|
let buf = Lexing.from_string s in
|
||||||
|
let d = Decoder.of_lexbuf buf in
|
||||||
|
Decoder.to_list d
|
||||||
|
|
||||||
let set_file_ ?file buf =
|
let set_file_ ?file buf =
|
||||||
let open Lexing in
|
let open Lexing in
|
||||||
match file with
|
match file with
|
||||||
|
|
@ -251,21 +268,13 @@ module Make(Sexp : SEXP) = struct
|
||||||
let buf = Lexing.from_channel ic in
|
let buf = Lexing.from_channel ic in
|
||||||
set_file_ ?file buf;
|
set_file_ ?file buf;
|
||||||
let d = Decoder.of_lexbuf buf in
|
let d = Decoder.of_lexbuf buf in
|
||||||
match Decoder.next d with
|
dec_next_ d
|
||||||
| End -> Result.Error "unexpected end of file"
|
|
||||||
| Yield x -> Result.Ok x
|
|
||||||
| Fail e -> Result.Error e
|
|
||||||
|
|
||||||
let parse_chan_list_ ?file ic =
|
let parse_chan_list_ ?file ic =
|
||||||
let buf = Lexing.from_channel ic in
|
let buf = Lexing.from_channel ic in
|
||||||
set_file_ ?file buf;
|
set_file_ ?file buf;
|
||||||
let d = Decoder.of_lexbuf buf in
|
let d = Decoder.of_lexbuf buf in
|
||||||
let rec iter acc = match Decoder.next d with
|
Decoder.to_list d
|
||||||
| End -> Result.Ok (List.rev acc)
|
|
||||||
| Yield x -> iter (x::acc)
|
|
||||||
| Fail e -> Result.Error e
|
|
||||||
in
|
|
||||||
iter []
|
|
||||||
|
|
||||||
let parse_chan ic = parse_chan_ ic
|
let parse_chan ic = parse_chan_ ic
|
||||||
let parse_chan_list ic = parse_chan_list_ ic
|
let parse_chan_list ic = parse_chan_list_ ic
|
||||||
|
|
@ -340,6 +349,14 @@ include (Make(struct
|
||||||
(parse_string "#; (a b) 1") (Result.Ok (`Atom "1"))
|
(parse_string "#; (a b) 1") (Result.Ok (`Atom "1"))
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
(*$= & ~printer:(function Result.Ok x -> String.concat ";" @@ List.map to_string x | Result.Error e -> "error " ^ e)
|
||||||
|
(parse_string_list "(a b)(c)") (Result.Ok [`List [`Atom "a"; `Atom "b"]; `List [`Atom "c"]])
|
||||||
|
(parse_string_list " ") (Result.Ok [])
|
||||||
|
(parse_string_list "(a\n ;coucou\n b)") (Result.Ok [`List [`Atom "a"; `Atom "b"]])
|
||||||
|
(parse_string_list "#; (a b) (c d) e ") (Result.Ok [`List [`Atom "c"; `Atom "d"]; `Atom "e"])
|
||||||
|
(parse_string_list "#; (a b) 1") (Result.Ok [`Atom "1"])
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
(*$inject
|
(*$inject
|
||||||
let sexp_gen =
|
let sexp_gen =
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,19 @@ module type S = sig
|
||||||
val next : t -> sexp parse_result
|
val next : t -> sexp parse_result
|
||||||
(** Parse the next S-expression or return an error if the input isn't
|
(** Parse the next S-expression or return an error if the input isn't
|
||||||
long enough or isn't a proper S-expression. *)
|
long enough or isn't a proper S-expression. *)
|
||||||
|
|
||||||
|
val to_list : t -> sexp list or_error
|
||||||
|
(** Read all the values from this decoder.
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
end
|
end
|
||||||
|
|
||||||
val parse_string : string -> t or_error
|
val parse_string : string -> t or_error
|
||||||
(** Parse a string. *)
|
(** Parse a string. *)
|
||||||
|
|
||||||
|
val parse_string_list : string -> t list or_error
|
||||||
|
(** Parse a string into a list of S-exprs.
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val parse_chan : in_channel -> t or_error
|
val parse_chan : in_channel -> t or_error
|
||||||
(** Parse a S-expression from the given channel. Can read more data than
|
(** Parse a S-expression from the given channel. Can read more data than
|
||||||
necessary, so don't use this if you need finer-grained control (e.g.
|
necessary, so don't use this if you need finer-grained control (e.g.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue