mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
smallish parser for HGraph
This commit is contained in:
parent
aeaedd049a
commit
239f6af59f
3 changed files with 153 additions and 3 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
open Containers;;
|
open Containers;;
|
||||||
open Sequence.Infix;;
|
open Sequence.Infix;;
|
||||||
#install_printer Bencode.pretty;;
|
#install_printer Bencode.pretty;;
|
||||||
|
#install_printer HGraph.Default.fmt;;
|
||||||
#require "CamlGI";;
|
#require "CamlGI";;
|
||||||
#load "containers_cgi.cma";;
|
#load "containers_cgi.cma";;
|
||||||
let pp_html fmt h = Format.pp_print_string fmt (ToWeb.HTML.render h);;
|
let pp_html fmt h = Format.pp_print_string fmt (ToWeb.HTML.render h);;
|
||||||
|
|
|
||||||
134
hGraph.ml
134
hGraph.ml
|
|
@ -78,6 +78,9 @@ module type S = sig
|
||||||
Buffer.t -> edge -> unit
|
Buffer.t -> edge -> unit
|
||||||
(** Print the edge on the buffer. @param printed: sub-edges already
|
(** Print the edge on the buffer. @param printed: sub-edges already
|
||||||
printed. *)
|
printed. *)
|
||||||
|
|
||||||
|
val fmt : Format.formatter -> edge -> unit
|
||||||
|
val to_string : edge -> string
|
||||||
end
|
end
|
||||||
|
|
||||||
module type PARAM = sig
|
module type PARAM = sig
|
||||||
|
|
@ -209,10 +212,19 @@ module Make(P : PARAM) = struct
|
||||||
for i = 0 to Array.length a - 1 do
|
for i = 0 to Array.length a - 1 do
|
||||||
if i > 0 then Buffer.add_char buf ' ';
|
if i > 0 then Buffer.add_char buf ' ';
|
||||||
pp buf a.(i)
|
pp buf a.(i)
|
||||||
done
|
done;
|
||||||
|
Buffer.add_char buf ']'
|
||||||
end
|
end
|
||||||
in
|
in
|
||||||
pp buf e
|
pp buf e
|
||||||
|
|
||||||
|
let to_string e =
|
||||||
|
let buf = Buffer.create 15 in
|
||||||
|
pp buf e;
|
||||||
|
Buffer.contents buf
|
||||||
|
|
||||||
|
let fmt fmt e =
|
||||||
|
Format.pp_print_string fmt (to_string e)
|
||||||
end
|
end
|
||||||
|
|
||||||
(** {2 Useful default} *)
|
(** {2 Useful default} *)
|
||||||
|
|
@ -241,4 +253,122 @@ module DefaultParam = struct
|
||||||
let s s = S s
|
let s s = S s
|
||||||
end
|
end
|
||||||
|
|
||||||
module Default = Make(DefaultParam)
|
module Default = struct
|
||||||
|
include Make(DefaultParam)
|
||||||
|
|
||||||
|
exception EOI
|
||||||
|
exception Error of string
|
||||||
|
|
||||||
|
module Lexbuf = struct
|
||||||
|
type t = {
|
||||||
|
mutable s : string;
|
||||||
|
mutable i : int;
|
||||||
|
get : (unit -> string option);
|
||||||
|
}
|
||||||
|
|
||||||
|
let of_string s = { s; i=0; get = (fun () -> None); }
|
||||||
|
|
||||||
|
let of_fun get = { s=""; i = 0; get; }
|
||||||
|
|
||||||
|
let of_chan c =
|
||||||
|
let s = String.make 64 ' ' in
|
||||||
|
let get () =
|
||||||
|
try
|
||||||
|
let n = input c s 0 64 in
|
||||||
|
Some (String.sub s 0 n)
|
||||||
|
with End_of_file -> None
|
||||||
|
in
|
||||||
|
{ s = ""; i = 0; get; }
|
||||||
|
end
|
||||||
|
|
||||||
|
let rec _get_rec lb =
|
||||||
|
if lb.Lexbuf.i >= String.length lb.Lexbuf.s
|
||||||
|
then match lb.Lexbuf.get () with
|
||||||
|
| None -> raise EOI
|
||||||
|
| Some s' ->
|
||||||
|
lb.Lexbuf.s <- s';
|
||||||
|
lb.Lexbuf.i <- 0;
|
||||||
|
_get_rec lb
|
||||||
|
else lb.Lexbuf.s.[lb.Lexbuf.i]
|
||||||
|
|
||||||
|
let _get lb =
|
||||||
|
if lb.Lexbuf.i >= String.length lb.Lexbuf.s
|
||||||
|
then _get_rec lb
|
||||||
|
else lb.Lexbuf.s.[lb.Lexbuf.i]
|
||||||
|
|
||||||
|
let _skip lb = lb.Lexbuf.i <- lb.Lexbuf.i + 1
|
||||||
|
|
||||||
|
(* skip whitespace *)
|
||||||
|
let rec _white lb =
|
||||||
|
match _get lb with
|
||||||
|
| ' ' | '\t' | '\n' -> _skip lb; _white lb
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
|
(* read lb, expecting the given char *)
|
||||||
|
let _expect lb c =
|
||||||
|
if _get lb = c
|
||||||
|
then _skip lb
|
||||||
|
else raise (Error (Printf.sprintf "expected %c" c))
|
||||||
|
|
||||||
|
let rec __parse_edge g lb =
|
||||||
|
_white lb;
|
||||||
|
match _get lb with
|
||||||
|
| '[' ->
|
||||||
|
_skip lb;
|
||||||
|
let sub = __parse_edges g [] lb in
|
||||||
|
let sub = match sub with
|
||||||
|
| [] -> raise (Error "parsed an empty list of sub-edges")
|
||||||
|
| _ -> Array.of_list sub
|
||||||
|
in
|
||||||
|
_white lb;
|
||||||
|
_expect lb ']';
|
||||||
|
make_edge g sub
|
||||||
|
| '0' .. '9' ->
|
||||||
|
let i = _parse_int 0 lb in
|
||||||
|
make_const g (DefaultParam.I i)
|
||||||
|
| '_' ->
|
||||||
|
_skip lb;
|
||||||
|
fresh g
|
||||||
|
| _ ->
|
||||||
|
let s = _parse_str (Buffer.create 15) lb in
|
||||||
|
make_const g (DefaultParam.S s)
|
||||||
|
|
||||||
|
and __parse_edges g acc lb =
|
||||||
|
_white lb;
|
||||||
|
match _get lb with
|
||||||
|
| ']' -> List.rev acc (* done *)
|
||||||
|
| _ ->
|
||||||
|
let e = __parse_edge g lb in
|
||||||
|
__parse_edges g (e::acc) lb
|
||||||
|
|
||||||
|
and _parse_int i lb =
|
||||||
|
match _get lb with
|
||||||
|
| ('0' .. '9') as c ->
|
||||||
|
let n = Char.code c - Char.code '0' in
|
||||||
|
_skip lb;
|
||||||
|
_parse_int ((i * 10) + n) lb
|
||||||
|
| _ -> i
|
||||||
|
|
||||||
|
and _parse_str buf lb =
|
||||||
|
match _get lb with
|
||||||
|
| ' ' | '\t' | '\n' | ']' -> Buffer.contents buf (* done *)
|
||||||
|
| '\\' ->
|
||||||
|
(* must read next char *)
|
||||||
|
_skip lb;
|
||||||
|
Buffer.add_char buf (_get lb);
|
||||||
|
_skip lb;
|
||||||
|
_parse_str buf lb
|
||||||
|
| c ->
|
||||||
|
Buffer.add_char buf c;
|
||||||
|
_skip lb;
|
||||||
|
_parse_str buf lb
|
||||||
|
|
||||||
|
(* parse one edge *)
|
||||||
|
let parse_edge g lb =
|
||||||
|
try `Ok (__parse_edge g lb)
|
||||||
|
with
|
||||||
|
| EOI -> `Error "unexpected end of input"
|
||||||
|
| Error e -> `Error e
|
||||||
|
|
||||||
|
let edge_of_string g s = parse_edge g (Lexbuf.of_string s)
|
||||||
|
end
|
||||||
|
|
|
||||||
21
hGraph.mli
21
hGraph.mli
|
|
@ -80,6 +80,9 @@ module type S = sig
|
||||||
Buffer.t -> edge -> unit
|
Buffer.t -> edge -> unit
|
||||||
(** Print the edge on the buffer. @param printed: sub-edges already
|
(** Print the edge on the buffer. @param printed: sub-edges already
|
||||||
printed. *)
|
printed. *)
|
||||||
|
|
||||||
|
val fmt : Format.formatter -> edge -> unit
|
||||||
|
val to_string : edge -> string
|
||||||
end
|
end
|
||||||
|
|
||||||
module type PARAM = sig
|
module type PARAM = sig
|
||||||
|
|
@ -105,4 +108,20 @@ module DefaultParam : sig
|
||||||
val s : string -> const
|
val s : string -> const
|
||||||
end
|
end
|
||||||
|
|
||||||
module Default : S with type const = DefaultParam.const
|
module Default : sig
|
||||||
|
include S with type const = DefaultParam.const
|
||||||
|
|
||||||
|
module Lexbuf : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val of_string : string -> t
|
||||||
|
|
||||||
|
val of_fun : (unit -> string option) -> t
|
||||||
|
|
||||||
|
val of_chan : in_channel -> t
|
||||||
|
end
|
||||||
|
|
||||||
|
val parse_edge : t -> Lexbuf.t -> [ `Ok of edge | `Error of string ]
|
||||||
|
|
||||||
|
val edge_of_string : t -> string -> [ `Ok of edge | `Error of string ]
|
||||||
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue