changed the Sexp api (renamed parsing/printing functions)

This commit is contained in:
Simon Cruanes 2014-09-17 23:42:59 +02:00
parent daf06196c0
commit 9ca56d8046
3 changed files with 125 additions and 69 deletions

View file

@ -3,7 +3,7 @@
let () = let () =
if Array.length Sys.argv <> 2 then failwith "usage: id_sexp file"; if Array.length Sys.argv <> 2 then failwith "usage: id_sexp file";
let f = Sys.argv.(1) in let f = Sys.argv.(1) in
let s = Sexp.parse_l_file f in let s = Sexp.L.of_file f in
match s with match s with
| `Ok l -> | `Ok l ->
List.iter List.iter

View file

@ -33,14 +33,35 @@ type t =
| Atom of string | Atom of string
| List of t list | List of t list
let eq a b = a = b let equal a b = a = b
let compare a b = Pervasives.compare a b let compare a b = Pervasives.compare a b
let hash a = Hashtbl.hash a let hash a = Hashtbl.hash a
let _with_in filename f =
let ic = open_in filename in
try
let x = f ic in
close_in ic;
x
with e ->
close_in ic;
`Error (Printexc.to_string e)
let _with_out filename f =
let oc = open_out filename in
try
let x = f oc in
close_out oc;
x
with e ->
close_out oc;
raise e
(** {2 Serialization (encoding)} *) (** {2 Serialization (encoding)} *)
(* shall we escape the string because of one of its chars? *)
let _must_escape s = let _must_escape s =
try try
for i = 0 to String.length s - 1 do for i = 0 to String.length s - 1 do
@ -101,17 +122,13 @@ let to_chan oc t =
print fmt t; print fmt t;
Format.pp_print_flush fmt () Format.pp_print_flush fmt ()
let seq_to_file filename seq = let to_file_seq filename seq =
let oc = open_out filename in _with_out filename
try (fun oc ->
seq seq (fun t -> to_chan oc t; output_char oc '\n')
(fun t -> to_chan oc t; output_char oc '\n'); )
close_out oc
with e ->
close_out oc;
raise e
let to_file filename t = seq_to_file filename (fun k -> k t) let to_file filename t = to_file_seq filename (fun k -> k t)
(** {2 Deserialization (decoding)} *) (** {2 Deserialization (decoding)} *)
@ -472,35 +489,49 @@ let parse_chan ?bufsize ic =
(** {6 Blocking} *) (** {6 Blocking} *)
let parse1_chan ic = let of_chan ic =
ParseGen.head (parse_chan ic) ParseGen.head (parse_chan ic)
let parse1_string s = let of_string s =
ParseGen.head (parse_string s) ParseGen.head (parse_string s)
let parse_l_chan ?bufsize ic = let of_file f =
_with_in f of_chan
module L = struct
let to_buf b l =
List.iter (to_buf b) l
let to_string l =
let b = Buffer.create 32 in
to_buf b l;
Buffer.contents b
let to_chan oc l =
let fmt = Format.formatter_of_out_channel oc in
List.iter (Format.fprintf fmt "%a@." print) l;
Format.pp_print_flush fmt ()
let to_file filename l =
_with_out filename (fun oc -> to_chan oc l)
let of_chan ?bufsize ic =
ParseGen.to_list (parse_chan ?bufsize ic) ParseGen.to_list (parse_chan ?bufsize ic)
let parse_l_file ?bufsize filename = let of_file ?bufsize filename =
let ic = open_in filename in _with_in filename
try (fun ic -> of_chan ?bufsize ic)
let l = parse_l_chan ?bufsize ic in
close_in ic;
l
with e ->
close_in ic;
`Error (Printexc.to_string e)
let parse_l_string s = let of_string s =
ParseGen.to_list (parse_string s) ParseGen.to_list (parse_string s)
let parse_l_gen g = let of_gen g =
ParseGen.to_list (parse_gen g) ParseGen.to_list (parse_gen g)
exception OhNoes of string exception OhNoes of string
exception StopNaow exception StopNaow
let parse_l_seq seq = let of_seq seq =
let src = Source.Manual.make () in let src = Source.Manual.make () in
let ps = mk_ps (Source.Manual.to_src src) in let ps = mk_ps (Source.Manual.to_src src) in
let l = ref [] in let l = ref [] in
@ -520,3 +551,4 @@ let parse_l_seq seq =
with with
| OhNoes msg -> `Error msg | OhNoes msg -> `Error msg
| StopNaow -> `Ok (List.rev !l) | StopNaow -> `Ok (List.rev !l)
end

View file

@ -23,7 +23,9 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*) *)
(** {1 Simple S-expression parsing/printing} *) (** {1 Simple and efficient S-expression parsing/printing}
@since NEXT_RELEASE *)
type 'a or_error = [ `Ok of 'a | `Error of string ] type 'a or_error = [ `Ok of 'a | `Error of string ]
type 'a sequence = ('a -> unit) -> unit type 'a sequence = ('a -> unit) -> unit
@ -35,15 +37,21 @@ type t =
| Atom of string | Atom of string
| List of t list | List of t list
val eq : t -> t -> bool val equal : t -> t -> bool
val compare : t -> t -> int val compare : t -> t -> int
val hash : t -> int val hash : t -> int
(** {2 Serialization (encoding)} *) (** {2 Serialization (encoding)} *)
val to_buf : Buffer.t -> t -> unit val to_buf : Buffer.t -> t -> unit
val to_string : t -> string val to_string : t -> string
val to_file : string -> t -> unit val to_file : string -> t -> unit
val to_file_seq : string -> t sequence -> unit
(** Print the given sequence of expressions to a file *)
val to_chan : out_channel -> t -> unit val to_chan : out_channel -> t -> unit
val print : Format.formatter -> t -> unit val print : Format.formatter -> t -> unit
@ -52,16 +60,12 @@ val print : Format.formatter -> t -> unit
val print_noindent : Format.formatter -> t -> unit val print_noindent : Format.formatter -> t -> unit
(** Raw, direct printing as compact as possible *) (** Raw, direct printing as compact as possible *)
val seq_to_file : string -> t sequence -> unit
(** Print the given sequence of expressions to a file *)
(** {2 Deserialization (decoding)} *) (** {2 Deserialization (decoding)} *)
type 'a parse_result = ['a or_error | `End ] type 'a parse_result = ['a or_error | `End ]
type 'a partial_result = [ 'a parse_result | `Await ] type 'a partial_result = [ 'a parse_result | `Await ]
(** {6 Streaming Parsing} *) (** {6 Source of characters} *)
module Source : sig module Source : sig
type individual_char = type individual_char =
| NC_yield of char | NC_yield of char
@ -105,6 +109,8 @@ module Source : sig
val of_gen : string gen -> t val of_gen : string gen -> t
end end
(** {6 Streaming Lexer}
splits the input into opening parenthesis, closing ones, and atoms *)
module Lexer : sig module Lexer : sig
type t type t
(** A streaming lexer, that parses atomic chunks of S-expressions (atoms (** A streaming lexer, that parses atomic chunks of S-expressions (atoms
@ -148,7 +154,8 @@ module ParseGen : sig
val take : int -> 'a t -> 'a t val take : int -> 'a t -> 'a t
end end
(** {6 Stream Parser} *) (** {6 Stream Parser}
Returns a lazy stream of S-expressions. *)
val parse_string : string -> t ParseGen.t val parse_string : string -> t ParseGen.t
(** Parse a string *) (** Parse a string *)
@ -159,20 +166,37 @@ val parse_chan : ?bufsize:int -> in_channel -> t ParseGen.t
val parse_gen : string gen -> t ParseGen.t val parse_gen : string gen -> t ParseGen.t
(** Parse chunks of string *) (** Parse chunks of string *)
(** {6 Blocking} *) (** {6 Blocking API}
Parse one S-expression from some source. *)
val parse1_chan : in_channel -> t or_error val of_chan : in_channel -> t or_error
(** 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.
to read something else {b after} the S-exp) *)
val parse1_string : string -> t or_error val of_string : string -> t or_error
val parse_l_chan : ?bufsize:int -> in_channel -> t list or_error val of_file : string -> t or_error
(** Parse values from a channel. *) (** Open the file and read a S-exp from it *)
val parse_l_file : ?bufsize:int -> string -> t list or_error (** {6 Lists of S-exps} *)
(** Parse a file *)
val parse_l_string : string -> t list or_error module L : sig
val to_buf : Buffer.t -> t list -> unit
val parse_l_gen : string gen -> t list or_error val to_string : t list -> string
val parse_l_seq : string sequence -> t list or_error val to_file : string -> t list -> unit
val to_chan : out_channel -> t list -> unit
val of_chan : ?bufsize:int -> in_channel -> t list or_error
val of_file : ?bufsize:int -> string -> t list or_error
val of_string : string -> t list or_error
val of_gen : string gen -> t list or_error
val of_seq : string sequence -> t list or_error
end