diff --git a/src/tyre.ml b/src/tyre.ml index c892955..ce0ce43 100644 --- a/src/tyre.ml +++ b/src/tyre.ml @@ -42,8 +42,6 @@ module Gen = struct end -let map_3 f (x,y,z) = (x, y, f z) - (** {2 The various types} *) type 'a gen = unit -> 'a option @@ -51,13 +49,13 @@ type 'a gen = unit -> 'a option module T = struct type ('a, 'b) conv = { - to_ : 'a -> 'b ; - from_ : 'b -> 'a ; + to_ : ('a -> 'b) expr ; + from_ : ('b -> 'a) expr ; } type 'a raw = (* We store a compiled regex to efficiently check string when unparsing. *) - | Regexp : Re.t * Re.re Lazy.t -> string raw + | Regexp : Re.t expr * Re.re Lazy.t expr -> string raw | Conv : 'a raw * ('a, 'b) conv -> 'b raw | Opt : 'a raw -> ('a option) raw | Alt : 'a raw * 'b raw -> [`Left of 'a | `Right of 'b] raw @@ -65,24 +63,24 @@ module T = struct | Prefix : 'b raw * 'a raw -> 'a raw | Suffix : 'a raw * 'b raw -> 'a raw | Rep : 'a raw -> 'a gen raw - | Mod : (Re.t -> Re.t) * 'a raw -> 'a raw + | Mod : (Re.t -> Re.t) expr * 'a raw -> 'a raw type _ wit = | Lit : int -> string wit | Conv : 'a wit * ('a, 'b) conv -> 'b wit - | Opt : Re.markid * 'a wit -> 'a option wit - | Alt : Re.markid * 'a wit * 'b wit + | Opt : Re.markid expr * 'a wit -> 'a option wit + | Alt : Re.markid expr * 'a wit * 'b wit -> [`Left of 'a | `Right of 'b] wit | Seq : 'a wit * 'b wit -> ('a * 'b) wit - | Rep : int * 'a wit * Re.re -> 'a gen wit + | Rep : int * 'a wit * Re.re expr -> 'a gen wit end type 'a t = 'a T.raw -let regex x : _ t = - let re = lazy Re.(compile @@ whole_string @@ no_group x) in +macro regex x : _ t = + let re = << lazy Re.(compile (whole_string (no_group $x))) >> in Regexp (x, re) (* Converters @@ -93,54 +91,56 @@ let regex x : _ t = *) exception ConverterFailure of exn -let conv_fail to_ from_ x : _ t = - let fail exn = - raise (ConverterFailure exn) - in - let to_ x = match to_ x with - | Result.Ok x -> x - | Result.Error exn -> fail exn - | exception exn -> fail exn +let fail exn = + raise (ConverterFailure exn) + +macro conv_fail to_ from_ x : _ t = + let to_ = + << fun x -> match $to_ x with + | Result.Ok x -> x + | Result.Error exn -> fail exn + | exception exn -> fail exn + >> in Conv (x, {to_; from_}) -let conv to_ from_ x : _ t = +static conv to_ from_ x : _ t = Conv (x, {to_; from_}) -let seq a b : _ t = Seq (a, b) -let alt a b : _ t = Alt (a, b) +static seq a b : _ t = Seq (a, b) +static alt a b : _ t = Alt (a, b) -let prefix x a : _ t = Prefix (x, a) -let suffix a x : _ t = Suffix (a, x) -let opt a : _ t = Opt a +static prefix x a : _ t = Prefix (x, a) +static suffix a x : _ t = Suffix (a, x) +static opt a : _ t = Opt a module Infix = struct - let (<|>) = alt - let (<&>) = seq + static (<|>) = alt + static (<&>) = seq - let ( *>) = prefix - let (<* ) = suffix + static ( *>) = prefix + static (<* ) = suffix end include Infix -let rep x : _ t = Rep x -let rep1 x = x <&> rep x +static rep x : _ t = Rep x +static rep1 x = x <&> rep x (* [modifier] is unsafe in general (for example [modifier Re.group]). It shouldn't be exposed to the user. *) -let modifier f re : _ t = Mod (f, re) +static modifier f re : _ t = Mod (f, re) -let word re = modifier Re.word re -let whole_string re = modifier Re.whole_string re -let longest re = modifier Re.longest re -let shortest re = modifier Re.shortest re -let first re = modifier Re.first re -let greedy re = modifier Re.greedy re -let non_greedy re = modifier Re.non_greedy re -let nest re = modifier Re.nest re +macro word re = modifier <> re +macro whole_string re = modifier <> re +macro longest re = modifier <> re +macro shortest re = modifier <> re +macro first re = modifier <> re +macro greedy re = modifier <> re +macro non_greedy re = modifier <> re +macro nest re = modifier <> re module Regex = struct open! Re @@ -162,43 +162,43 @@ module Regex = struct end -let unit s re = +macro unit s re = conv - (fun _ -> ()) - (fun () -> s) + <<(fun _ -> ())>> + <<(fun () -> $s)>> (regex re) -let start = unit "" Re.start -let stop = unit "" Re.stop +macro start = unit <<"">> <> +macro stop = unit <<"">> <> -let str s = unit s (Re.str s) +macro str s = unit s <> -let char c = - let s = String.make 1 c in - unit s (Re.char c) +macro char c = + let s = << String.make 1 $c >> in + unit s <> -let blanks = unit "" (Re.rep Re.blank) +macro blanks = unit <<"">> <> -let pos_int = - conv int_of_string string_of_int (regex Regex.pos_int) +macro pos_int = + conv <> <> (regex <>) -let int = - conv int_of_string string_of_int (regex Regex.int) +macro int = + conv <> <> (regex <>) -let float = - conv float_of_string string_of_float (regex Regex.float) +macro float = + conv <> <> (regex <>) -let bool = - conv bool_of_string string_of_bool (regex Regex.bool) +macro bool = + conv <> <> (regex <>) -let list e = - conv Gen.to_list Gen.of_list (rep e) +macro list e = + conv <> <> (rep e) -let terminated_list ~sep e = list (e <* sep) -let separated_list ~sep e = +static terminated_list ~sep e = list (e <* sep) +macro separated_list ~sep e = let e = opt (e <&> list (sep *> e)) in - let to_ = function None -> [] | Some (h, t) -> (h :: t) - and from_ = function [] -> None | h :: t -> Some (h, t) + let to_ = < [] | Some (h, t) -> (h :: t)>> + and from_ = < None | h :: t -> Some (h, t)>> in conv to_ from_ e @@ -212,65 +212,65 @@ let separated_list ~sep e = It is used in [eval] for the part of the regex that are ignored. *) -let rec witnesspp - : type a . Format.formatter -> a t -> unit - = fun ppf tre -> let open T in match tre with - | Regexp (re, _) -> Format.pp_print_string ppf @@ Re.witness re - | Conv (tre, _) -> witnesspp ppf tre - | Opt _ -> () - | Alt (tre1, _) -> witnesspp ppf tre1 - | Seq (tre1, tre2) -> - witnesspp ppf tre1 ; - witnesspp ppf tre2 - | Prefix (tre1,tre2) -> - witnesspp ppf tre1 ; - witnesspp ppf tre2 - | Suffix (tre1,tre2) -> - witnesspp ppf tre1 ; - witnesspp ppf tre2 - | Rep _ -> () - | Mod (_,tre) -> - witnesspp ppf tre +(* static rec witnesspp *) +(* : type a . Format.formatter -> a t -> unit *) +(* = fun ppf tre -> let open T in match tre with *) +(* | Regexp (re, _) -> ~Format.pp_print_string ppf (R.witness re) *) +(* | Conv (tre, _) -> witnesspp ppf tre *) +(* | Opt _ -> () *) +(* | Alt (tre1, _) -> witnesspp ppf tre1 *) +(* | Seq (tre1, tre2) -> *) +(* witnesspp ppf tre1 ; *) +(* witnesspp ppf tre2 *) +(* | Prefix (tre1,tre2) -> *) +(* witnesspp ppf tre1 ; *) +(* witnesspp ppf tre2 *) +(* | Suffix (tre1,tre2) -> *) +(* witnesspp ppf tre1 ; *) +(* witnesspp ppf tre2 *) +(* | Rep _ -> () *) +(* | Mod (_,tre) -> *) +(* witnesspp ppf tre *) (** {2 Evaluation functions} *) (** Evaluation is the act of filling the holes. *) -let pstr = Format.pp_print_string -let rec pprep f ppf gen = match gen () with - | None -> () - | Some x -> f ppf x ; pprep f ppf gen - -let rec evalpp - : type a . a t -> Format.formatter -> a -> unit - = fun tre ppf -> let open T in match tre with - | Regexp (_, lazy cre) -> begin function v -> - if not @@ Re.execp cre v then - invalid_arg @@ - Printf.sprintf "Tyre.eval: regexp not respected by \"%s\"." v ; - pstr ppf v - end - | Conv (tre, conv) -> fun v -> evalpp tre ppf (conv.from_ v) - | Opt p -> begin function - | None -> pstr ppf "" - | Some x -> evalpp p ppf x - end - | Seq (tre1,tre2) -> fun (x1, x2) -> - evalpp tre1 ppf x1 ; - evalpp tre2 ppf x2 ; - | Prefix(tre_l,tre) -> - fun v -> witnesspp ppf tre_l ; evalpp tre ppf v - | Suffix(tre,tre_g) -> - fun v -> evalpp tre ppf v ; witnesspp ppf tre_g - | Alt (treL, treR) -> begin function - | `Left x -> evalpp treL ppf x - | `Right x -> evalpp treR ppf x - end - | Rep tre -> - pprep (evalpp tre) ppf - | Mod (_, tre) -> evalpp tre ppf - -let eval tre = Format.asprintf "%a" (evalpp tre) +(* static pstr = ~Format.pp_print_string *) +(* static rec pprep f ppf gen = match gen () with *) +(* | None -> () *) +(* | Some x -> f ppf x ; pprep f ppf gen *) + +(* static rec evalpp *) +(* : type a . a t -> (Format.formatter -> a -> unit) expr *) +(* = fun tre -> let open T in match tre with *) +(* | Regexp (_, lazy cre) -> << fun ppf v -> *) +(* if not @@ Re.execp cre v then *) +(* invalid_arg @@ *) +(* ~Printf.sprintf "Tyre.eval: regexp not respected by \"%s\"." v ; *) +(* pstr ppf v *) +(* >> *) +(* | Conv (tre, conv) -> << fun ppf v -> evalpp tre ppf (conv.from_ v) >> *) +(* | Opt p -> begin function *) +(* | None -> pstr ppf "" *) +(* | Some x -> evalpp p ppf x *) +(* end *) +(* | Seq (tre1,tre2) -> fun (x1, x2) -> *) +(* evalpp tre1 ppf x1 ; *) +(* evalpp tre2 ppf x2 ; *) +(* | Prefix(tre_l,tre) -> *) +(* fun v -> witnesspp ppf tre_l ; evalpp tre ppf v *) +(* | Suffix(tre,tre_g) -> *) +(* fun v -> evalpp tre ppf v ; witnesspp ppf tre_g *) +(* | Alt (treL, treR) -> begin function *) +(* | `Left x -> evalpp treL ppf x *) +(* | `Right x -> evalpp treR ppf x *) +(* end *) +(* | Rep tre -> *) +(* pprep (evalpp tre) ppf *) +(* | Mod (_, tre) -> evalpp tre ppf *) + +(* static eval tre = Format.asprintf "%a" (evalpp tre) *) (** {2 matching} *) @@ -283,40 +283,47 @@ let eval tre = Format.asprintf "%a" (evalpp tre) to be able to guess the branch matched. *) -let rec build - : type a. int -> a t -> int * a T.wit * Re.t +macro map_mark (x,y,z) = + let a = <> in + (x, y, <>, <>) + + +macro rec build + : type a. int -> a t -> int * a T.wit * Re.t expr = let open! Re in let open T in + let (+) = ~Pervasives.(+) in + let (@!) = ~Pervasives.(@@) in fun i -> function | Regexp (re, _) -> - (i+1), Lit i, group @@ no_group re + (i+1), Lit i, << group @@ no_group $re >> | Conv (e, conv) -> let i', w, re = build i e in i', Conv (w, conv), re | Opt e -> - let i', w, (id, re) = map_3 mark @@ build i e in - i', Opt (id,w), opt re + let i', w, id, re = map_mark @! build i e in + i', Opt (id,w), <> | Alt (e1,e2) -> - let i', w1, (id1, re1) = map_3 mark @@ build i e1 in + let i', w1, id1, re1 = map_mark @! build i e1 in let i'', w2, re2 = build i' e2 in - i'', Alt (id1, w1, w2), alt [re1 ; re2] + i'', Alt (id1, w1, w2), <> | Prefix (e_ign,e) -> let i', w, re = build i e in let _, _, re_ign = build 1 e_ign in - i', w, seq [no_group re_ign ; re] + i', w, <> | Suffix (e,e_ign) -> let i', w, re = build i e in let _, _, re_ign = build 1 e_ign in - i', w, seq [re ; no_group re_ign] + i', w, << seq [$re ; no_group $re_ign] >> | Seq (e1,e2) -> let i', w1, re1 = build i e1 in let i'', w2, re2 = build i' e2 in - i'', Seq (w1, w2), seq [re1; re2] + i'', Seq (w1, w2), << seq [$re1; $re2] >> | Rep e -> let _, w, re = build 1 e in - (i+1), Rep (i,w,Re.compile re), group @@ rep @@ no_group re + (i+1), Rep (i,w,<>), << group @@ rep @@ no_group $re >> | Mod (f, e) -> let i', w, re = build i e in - i', w, f re + i', w, << $f $re >> (** {3 Extraction.} *) @@ -325,26 +332,31 @@ let rec build To avoid copy, we pass around the original string (and we use positions). *) -let rec extract - : type a. original:string -> a T.wit -> Re.substrings -> a +macro rec extract + : type a. original:(string expr) -> a T.wit -> Re.substrings expr -> a expr = fun ~original rea s -> let open T in match rea with - | Lit i -> Re.get s i + | Lit i -> << Re.get $s $(Expr.of_int i) >> | Conv (w, conv) -> - let v = extract ~original w s in - conv.to_ v + let code = extract ~original w s in + << $(conv.to_) $code >> | Opt (id,w) -> - if not @@ Re.marked s id then None - else Some (extract ~original w s) + let code = extract ~original w s in << + if not @@ Re.marked $s $id then None + else Some $code + >> | Alt (i1,w1,w2) -> - if Re.marked s i1 then - `Left (extract ~original w1 s) - else - (* Invariant: Alt produces [Re.alt [e1 ; e2]] *) - `Right (extract ~original w2 s) + let code1 = extract ~original w1 s in + let code2 = extract ~original w2 s in + << if Re.marked $s $i1 then + `Left $code1 + else + (* Invariant: Alt produces [Re.alt [e1 ; e2]] *) + `Right $code2 + >> | Seq (e1,e2) -> - let v1 = extract ~original e1 s in - let v2 = extract ~original e2 s in - (v1, v2) + let code1 = extract ~original e1 s in + let code2 = extract ~original e2 s in + << ($code1, $code2) >> | Rep (i,e,re) -> extract_list ~original e re i s (** We need to re-match the string for lists, in order to extract @@ -354,46 +366,49 @@ let rec extract possible as it would be equivalent to counting in an automaton). *) and extract_list - : type a. original:string -> a T.wit -> Re.re -> int -> Re.substrings -> a gen + : type a. original:string expr -> a T.wit -> Re.re expr -> int -> Re.substrings expr -> a gen expr = fun ~original e re i s -> - let aux = extract ~original e in - let (pos, pos') = Re.get_ofs s i in - let len = pos' - pos in - Gen.map aux @@ Re.all_gen ~pos ~len re original + let aux = << fun subs -> $(extract ~original e <>) >> in + << + let (pos, pos') = Re.get_ofs $s $(Expr.of_int i) in + let len = pos' - pos in + Gen.map $aux @@ Re.all_gen ~pos ~len $re $original + >> (** {4 Multiple match} *) -type +'r route = Route : 'a t * ('a -> 'r) -> 'r route +type +'r route = Route : 'a t * ('a -> 'r) expr -> 'r route -let route re f = Route (re, f) +static route re f = Route (re, f) -let (-->) = route +static (-->) = route type 'r wit_route = - WRoute : Re.markid * 'a T.wit * ('a -> 'r) -> 'r wit_route + WRoute : Re.markid expr * 'a T.wit * ('a -> 'r) expr -> 'r wit_route (* It's important to keep the order here, since Re will choose the first regexp if there is ambiguity. *) -let rec build_route_aux i rel wl = function - | [] -> List.rev rel, List.rev wl +macro rec build_route_aux i rel wl = function + | [] -> << List.rev $rel >>, ~List.rev wl | Route (tre, f) :: l -> - let i', wit, re = build i tre in - let id, re = Re.mark re in + let i', wit, id, re = map_mark (build i tre) in let w = WRoute (id, wit, f) in - build_route_aux i' (re::rel) (w::wl) l + build_route_aux i' << $re :: $rel >> (w::wl) l -let build_route l = build_route_aux 1 [] [] l +macro build_route l = build_route_aux 1 <<[]>> [] l -let rec extract_route ~original wl subs = match wl with +macro rec extract_route ~original wl subs = match wl with | [] -> (* Invariant: At least one of the regexp of the alternative matches. *) assert false | WRoute (id, wit, f) :: wl -> - if Re.Mark.test subs id then - f (extract ~original wit subs) - else - extract_route ~original wl subs + let code = extract ~original wit subs in + let code_rest = extract_route ~original wl subs in + << if Re.Mark.test $subs $id + then $f $code + else $code_rest + >> (** {4 Compilation and execution} *) @@ -401,96 +416,97 @@ type 'r info = | One of 'r T.wit | Routes of 'r wit_route list -type 'a re = { info : 'a info ; cre : Re.re } +type 'a re = { info : 'a info ; cre : Re.re expr } -let compile tre = +macro compile tre = let _, wit, re = build 1 tre in - let cre = Re.compile re in + let cre = << Re.compile $re >> in { info = One wit ; cre } -let route l = +macro route l = let rel, wl = build_route l in - let cre = Re.compile @@ Re.alt rel in + let cre = << Re.compile @@ Re.alt $rel >> in { info = Routes wl ; cre } type 'a error = [ - | `NoMatch of 'a re * string + | `NoMatch of string | `ConverterFailure of exn ] -let exec ?pos ?len ({ info ; cre } as tcre) original = - match Re.exec_opt ?pos ?len cre original with - | None -> Result.Error (`NoMatch (tcre, original)) - | Some subs -> - let f = match info with - | One wit -> extract ~original wit - | Routes wl -> extract_route ~original wl - in - try - Result.Ok (f subs) - with ConverterFailure exn -> - Result.Error (`ConverterFailure exn) - -let execp ?pos ?len {cre ; _ } original = - Re.execp ?pos ?len cre original +macro exec { info ; cre } = + let f original subs = match info with + | One wit -> extract ~original wit subs + | Routes wl -> extract_route ~original wl subs + in + << fun ?pos ?len original -> + match Re.exec_opt ?pos ?len $cre original with + | None -> Result.Error (`NoMatch original) + | Some subs -> + try + Result.Ok $(f <> <>) + with ConverterFailure exn -> + Result.Error (`ConverterFailure exn) >> + +macro execp {cre ; _ } = + << fun ?pos ?len s -> Re.execp ?pos ?len $cre s >> (** Pretty printers *) -let sexp ppf s fmt = Format.fprintf ppf ("@[<3>(%s@ "^^fmt^^")@]") s - -(* Only in the stdlib since 4.02, so we copy. *) -let rec pp_list pp ppf = function - | [] -> () - | [v] -> pp ppf v - | v :: vs -> - pp ppf v; - Format.pp_print_space ppf (); - pp_list pp ppf vs - -let rec pp - : type a. _ -> a t -> unit - = fun ppf -> let open T in function - | Regexp (re,_) -> sexp ppf "Re" "%a" Re.pp re - | Conv (tre,_) -> sexp ppf "Conv" "%a" pp tre - | Opt tre -> sexp ppf "Opt" "%a" pp tre - | Alt (tre1, tre2) -> sexp ppf "Alt" "%a@ %a" pp tre1 pp tre2 - | Seq (tre1 ,tre2) -> sexp ppf "Seq" "%a@ %a" pp tre1 pp tre2 - | Prefix (tre1, tre2) -> - sexp ppf "Prefix" "%a@ %a" pp tre1 pp tre2 - | Suffix (tre1, tre2) -> - sexp ppf "Suffix" "%a@ %a" pp tre1 pp tre2 - | Rep tre -> sexp ppf "Rep" "%a" pp tre - | Mod (_,tre) -> sexp ppf "Mod" "%a" pp tre - -let rec pp_wit - : type a. _ -> a T.wit -> unit - = fun ppf -> let open T in function - | Lit i -> sexp ppf "Lit" "%i" i - | Conv (tre,_) -> sexp ppf "Conv" "%a" pp_wit tre - | Opt (_, tre) -> sexp ppf "Opt" "%a" pp_wit tre - | Alt (_, tre1, tre2) -> sexp ppf "Alt" "%a@ %a" pp_wit tre1 pp_wit tre2 - | Seq (tre1 ,tre2) -> sexp ppf "Seq" "%a@ %a" pp_wit tre1 pp_wit tre2 - | Rep (i, w, re) -> sexp ppf "Rep" "%i@ %a@ %a" i pp_wit w Re.pp_re re - -let pp_wit_route - : type a. _ -> a wit_route -> unit - = fun ppf (WRoute (_,w,_)) -> pp_wit ppf w - -let pp_re ppf = function - | { info = One w; cre } -> - sexp ppf "One" "%a@ %a" Re.pp_re cre pp_wit w - | { info = Routes wl; cre } -> - sexp ppf "Route" "%a@ %a" Re.pp_re cre (pp_list pp_wit_route) wl - -module Internal = struct - include T - - let to_t x = x - let from_t x = x - - exception ConverterFailure = ConverterFailure - - let build = build - let extract = extract -end +(* static sexp ppf s fmt = Format.fprintf ppf ("@[<3>(%s@ "^^fmt^^")@]") s *) + +(* (\* Only in the stdlib since 4.02, so we copy. *\) *) +(* static rec pp_list pp ppf = function *) +(* | [] -> () *) +(* | [v] -> pp ppf v *) +(* | v :: vs -> *) +(* pp ppf v; *) +(* Format.pp_print_space ppf (); *) +(* pp_list pp ppf vs *) + +(* static rec pp *) +(* : type a. _ -> a t -> unit *) +(* = fun ppf -> let open T in function *) +(* | Regexp (re,_) -> sexp ppf "Re" "%a" Re.pp re *) +(* | Conv (tre,_) -> sexp ppf "Conv" "%a" pp tre *) +(* | Opt tre -> sexp ppf "Opt" "%a" pp tre *) +(* | Alt (tre1, tre2) -> sexp ppf "Alt" "%a@ %a" pp tre1 pp tre2 *) +(* | Seq (tre1 ,tre2) -> sexp ppf "Seq" "%a@ %a" pp tre1 pp tre2 *) +(* | Prefix (tre1, tre2) -> *) +(* sexp ppf "Prefix" "%a@ %a" pp tre1 pp tre2 *) +(* | Suffix (tre1, tre2) -> *) +(* sexp ppf "Suffix" "%a@ %a" pp tre1 pp tre2 *) +(* | Rep tre -> sexp ppf "Rep" "%a" pp tre *) +(* | Mod (_,tre) -> sexp ppf "Mod" "%a" pp tre *) + +(* static rec pp_wit *) +(* : type a. _ -> a T.wit -> unit *) +(* = fun ppf -> let open T in function *) +(* | Lit i -> sexp ppf "Lit" "%i" i *) +(* | Conv (tre,_) -> sexp ppf "Conv" "%a" pp_wit tre *) +(* | Opt (_, tre) -> sexp ppf "Opt" "%a" pp_wit tre *) +(* | Alt (_, tre1, tre2) -> sexp ppf "Alt" "%a@ %a" pp_wit tre1 pp_wit tre2 *) +(* | Seq (tre1 ,tre2) -> sexp ppf "Seq" "%a@ %a" pp_wit tre1 pp_wit tre2 *) +(* | Rep (i, w, re) -> sexp ppf "Rep" "%i@ %a@ %a" i pp_wit w Re.pp_re re *) + +(* static pp_wit_route *) +(* : type a. _ -> a wit_route -> unit *) +(* = fun ppf (WRoute (_,w,_)) -> pp_wit ppf w *) + +(* static pp_re ppf = function *) +(* | { info = One w; cre } -> *) +(* sexp ppf "One" "%a@ %a" Re.pp_re cre pp_wit w *) +(* | { info = Routes wl; cre } -> *) +(* sexp ppf "Route" "%a@ %a" Re.pp_re cre (pp_list pp_wit_route) wl *) + +(* module Internal = struct *) +(* include T *) + +(* static to_t x = x *) +(* static from_t x = x *) + +(* exception ConverterFailure = ConverterFailure *) + +(* static build = build *) +(* static extract = extract *) +(* end *) diff --git a/src/tyre.mli b/src/tyre.mli index 5153493..df57ce1 100644 --- a/src/tyre.mli +++ b/src/tyre.mli @@ -31,12 +31,12 @@ type 'a t (** {2 Combinators} *) -val regex : Re.t -> string t +static val regex : Re.t expr -> string t (** [regex re] is a tyregex that matches [re] and return the corresponding string. Groups inside [re] are erased. *) -val conv : ('a -> 'b) -> ('b -> 'a) -> 'a t -> 'b t +static val conv : ('a -> 'b) expr -> ('b -> 'a) expr -> 'a t -> 'b t (** [conv ~name to_ from_ tyre] matches the same text as [tyre], but converts back and forth to a different data type. For example, this is the implementation of {!pos_int}: @@ -49,16 +49,16 @@ let pos_int = ]} *) -val conv_fail : - ('a -> ('b, exn) Result.result) -> ('b -> 'a) -> 'a t -> 'b t +static val conv_fail : + ('a -> ('b, exn) Result.result) expr -> ('b -> 'a) expr -> 'a t -> 'b t (** [conv_fail to_ from_ tyre] is similar to [conv to_ from_ tyre] excepts [to_] is allowed to fail by returning [Error] or raising an exception. If it does, {!exec} will return [`ConverterFailure exn] where [exn] is the returned exception. *) -val opt : 'a t -> 'a option t +static val opt : 'a t -> 'a option t (** [opt tyre] matches either [tyre] or the empty string. Similar to {!Re.opt}. *) -val alt : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t +static val alt : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t (** [alt tyreL tyreR] matches either [tyreL] (and will then return [`Left v]) or [tyreR] (and will then return [`Right v]). *) @@ -67,131 +67,131 @@ val alt : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t type 'a gen = unit -> 'a option (** A generator [g] will return a new value each time it's called, until it returns [None]. See {{:https://github.com/c-cube/gen/}gen}. *) -val rep : 'a t -> 'a gen t +static val rep : 'a t -> 'a gen t (** [rep tyre] matches [tyre] zero or more times. Similar to {!Re.rep}. For {{!matching}matching}, [rep tyre] will matches the string a first time, then [tyre] will be used to walk the matched part to extract values. *) -val rep1 : 'a t -> ('a * 'a gen) t +static val rep1 : 'a t -> ('a * 'a gen) t (** [rep1 tyre] is [seq tyre (rep tyre)]. Similar to {!Re.rep1}. *) (** {3 Sequences} *) -val seq : 'a t -> 'b t -> ('a * 'b) t +static val seq : 'a t -> 'b t -> ('a * 'b) t (** [seq tyre1 tyre2] matches [tyre1] then [tyre2] and return both values. *) -val prefix : _ t -> 'a t -> 'a t +static val prefix : _ t -> 'a t -> 'a t (** [prefix tyre_i tyre] matches [tyre_i], ignores the result, and then matches [tyre] and returns its result. *) -val suffix : 'a t -> _ t -> 'a t +static val suffix : 'a t -> _ t -> 'a t (** Same as [prefix], but reversed. *) (** {3 Infix operators} *) -val (<|>) : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t +static val (<|>) : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t (** [t <|> t'] is [alt t t']. *) -val (<&>) : 'a t -> 'b t -> ('a * 'b) t +static val (<&>) : 'a t -> 'b t -> ('a * 'b) t (** [t <&> t'] is [seq t t']. *) -val ( *>) : _ t -> 'a t -> 'a t +static val ( *>) : _ t -> 'a t -> 'a t (** [ ti *> t ] is [prefix ti t]. *) -val (<* ) : 'a t -> _ t -> 'a t +static val (<* ) : 'a t -> _ t -> 'a t (** [ t <* ti ] is [suffix t ti]. *) module Infix : sig - val (<|>) : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t + static val (<|>) : 'a t -> 'b t -> [`Left of 'a | `Right of 'b] t (** [t <|> t'] is [alt t t']. *) - val (<&>) : 'a t -> 'b t -> ('a * 'b) t + static val (<&>) : 'a t -> 'b t -> ('a * 'b) t (** [t <&> t'] is [seq t t']. *) - val ( *>) : _ t -> 'a t -> 'a t + static val ( *>) : _ t -> 'a t -> 'a t (** [ ti *> t ] is [prefix ti t]. *) - val (<* ) : 'a t -> _ t -> 'a t + static val (<* ) : 'a t -> _ t -> 'a t (** [ t <* ti ] is [suffix t ti]. *) end (** {3 Useful combinators} *) -val str : string -> unit t +static val str : string expr -> unit t (** [str s] matches [s] and evaluates to [s]. *) -val char : char -> unit t +static val char : char expr -> unit t (** [char c] matches [c] and evaluates to [c]. *) -val blanks : unit t +static val blanks : unit t (** [blanks] matches [Re.(rep blank)] and doesn't return anything. *) -val int : int t +static val int : int t (** [int] matches [-?[0-9]+] and returns the matched integer. Integers that do not fit in an [int] will fail. *) -val pos_int : int t +static val pos_int : int t (** [pos_int] matches [[0-9]+] and returns the matched positive integer. Integers that do not fit in an [int] will fail. *) -val float : float t +static val float : float t (** [float] matches [-?[0-9]+( .[0-9]* )?] and returns the matched floating point number. Floating point numbers that do not fit in a [float] returns {!infinity} or {!neg_infinity}. *) -val bool : bool t +static val bool : bool t (** [bool] matches [true|false] and returns the matched boolean. *) -val list : 'a t -> 'a list t +static val list : 'a t -> 'a list t (** [list e] is similar to [rep e], but returns a list. *) -val terminated_list : sep:_ t -> 'a t -> 'a list t +static val terminated_list : sep:_ t -> 'a t -> 'a list t (** [terminated_list ~sep tyre] is [ list (tyre <* sep) ]. *) -val separated_list : sep:_ t -> 'a t -> 'a list t +static val separated_list : sep:_ t -> 'a t -> 'a list t (** [separated_list ~sep tyre] is equivalent to [opt (e <&> list (sep *> e))]. *) (** {3 Other combinators} See {!Re} for details on the semantics of those combinators. *) -val start : unit t -val stop : unit t +static val start : unit t +static val stop : unit t -val word : 'a t -> 'a t -val whole_string : 'a t -> 'a t -val longest : 'a t -> 'a t -val shortest : 'a t -> 'a t -val first : 'a t -> 'a t -val greedy : 'a t -> 'a t -val non_greedy : 'a t -> 'a t -val nest : 'a t -> 'a t +static val word : 'a t -> 'a t +static val whole_string : 'a t -> 'a t +static val longest : 'a t -> 'a t +static val shortest : 'a t -> 'a t +static val first : 'a t -> 'a t +static val greedy : 'a t -> 'a t +static val non_greedy : 'a t -> 'a t +static val nest : 'a t -> 'a t (** {2:matching Matching} *) type 'a re (** A compiled typed regular expression. *) -val compile : 'a t -> 'a re +static val compile : 'a t -> 'a re (** [compile tyre] is the compiled tyregex representing [tyre]. *) type 'a error = [ - | `NoMatch of 'a re * string + | `NoMatch of string | `ConverterFailure of exn ] -val exec : ?pos:int -> ?len:int -> 'a re -> string -> ('a, 'a error) Result.result +static val exec : 'a re -> (?pos:int -> ?len:int -> string -> ('a, 'a error) Result.result) expr (** [exec ctyre s] matches the string [s] using the compiled tyregex [ctyre] and returns the extracted value. @@ -202,7 +202,7 @@ val exec : ?pos:int -> ?len:int -> 'a re -> string -> ('a, 'a error) Result.resu @param len length of the substring of [str] that can be matched (default to the end of the string) *) -val execp : ?pos:int -> ?len:int -> 'a re -> string -> bool +static val execp : 'a re -> (?pos:int -> ?len:int -> string -> bool) expr (** [execp ctyre s] returns [true] if [ctyre] matches [s]. @param pos optional beginning of the string (default 0) @@ -213,16 +213,16 @@ val execp : ?pos:int -> ?len:int -> 'a re -> string -> bool (** {3:routing Routing} *) -type +'a route = Route : 'x t * ('x -> 'a) -> 'a route +type +'a route = Route : 'x t * ('x -> 'a) expr -> 'a route (** A route is a pair of a tyregex and a handler. When the tyregex is matched, the function is called with the result of the matching. *) -val (-->) : 'x t -> ('x -> 'a) -> 'a route +static val (-->) : 'x t -> ('x -> 'a) expr -> 'a route (** [tyre --> f] is [Route (tyre, f)]. *) -val route : 'a route list -> 'a re +static val route : 'a route list -> 'a re (** [route [ tyre1 --> f1 ; tyre2 --> f2 ]] produces a compiled tyregex such that, if [tyre1] matches, [f1] is called, and so on. @@ -232,63 +232,63 @@ val route : 'a route list -> 'a re (** {2:eval Evaluating} *) -val eval : 'a t -> 'a -> string -(** [eval tyre v] returns a string [s] such that [exec (compile tyre) s = v]. +(* val eval : 'a t -> 'a -> string *) +(* (\** [eval tyre v] returns a string [s] such that [exec (compile tyre) s = v]. *) - Note that such string [s] is not unique. [eval] will usually returns a very simple witness. *) +(* Note that such string [s] is not unique. [eval] will usually returns a very simple witness. *\) *) -val evalpp : 'a t -> Format.formatter -> 'a -> unit -(** [evalpp tyre ppf v] is equivalent to [Format.fprintf ppf "%s" (eval tyre v)], but more efficient. +(* val evalpp : 'a t -> Format.formatter -> 'a -> unit *) +(* (\** [evalpp tyre ppf v] is equivalent to [Format.fprintf ppf "%s" (eval tyre v)], but more efficient. *) - Is is generally used with ["%a"]: -{[ -let my_pp = Tyre.evalpp tyre in -Format.printf "%a@." my_pp v -]} -*) +(* Is is generally used with ["%a"]: *) +(* {[ *) +(* let my_pp = Tyre.evalpp tyre in *) +(* Format.printf "%a@." my_pp v *) +(* ]} *) +(* *\) *) (** {2:pp Pretty printing} *) -val pp : Format.formatter -> 'a t -> unit - -val pp_re : Format.formatter -> 'a re -> unit - -(** Internal types *) -module Internal : sig - - exception ConverterFailure of exn - - type ('a, 'b) conv = { - to_ : 'a -> 'b ; - from_ : 'b -> 'a ; - } - - type 'a raw = - (* We store a compiled regex to efficiently check string when unparsing. *) - | Regexp : Re.t * Re.re Lazy.t -> string raw - | Conv : 'a raw * ('a, 'b) conv -> 'b raw - | Opt : 'a raw -> ('a option) raw - | Alt : 'a raw * 'b raw -> [`Left of 'a | `Right of 'b] raw - | Seq : 'a raw * 'b raw -> ('a * 'b) raw - | Prefix : 'b raw * 'a raw -> 'a raw - | Suffix : 'a raw * 'b raw -> 'a raw - | Rep : 'a raw -> 'a gen raw - | Mod : (Re.t -> Re.t) * 'a raw -> 'a raw - - val from_t : 'a t -> 'a raw - val to_t : 'a raw -> 'a t - - type _ wit = - | Lit : int -> string wit - | Conv : 'a wit * ('a, 'b) conv -> 'b wit - | Opt : Re.markid * 'a wit -> 'a option wit - | Alt : Re.markid * 'a wit * 'b wit - -> [`Left of 'a | `Right of 'b] wit - | Seq : - 'a wit * 'b wit -> ('a * 'b) wit - | Rep : int * 'a wit * Re.re -> 'a gen wit - - val build : int -> 'a raw -> int * 'a wit * Re.t - val extract : original:string -> 'a wit -> Re.substrings -> 'a - -end +(* val pp : Format.formatter -> 'a t -> unit *) + +(* val pp_re : Format.formatter -> 'a re -> unit *) + +(* (\** Internal types *\) *) +(* module Internal : sig *) + +(* exception ConverterFailure of exn *) + +(* type ('a, 'b) conv = { *) +(* to_ : 'a -> 'b ; *) +(* from_ : 'b -> 'a ; *) +(* } *) + +(* type 'a raw = *) +(* (\* We store a compiled regex to efficiently check string when unparsing. *\) *) +(* | Regexp : Re.t * Re.re Lazy.t -> string raw *) +(* | Conv : 'a raw * ('a, 'b) conv -> 'b raw *) +(* | Opt : 'a raw -> ('a option) raw *) +(* | Alt : 'a raw * 'b raw -> [`Left of 'a | `Right of 'b] raw *) +(* | Seq : 'a raw * 'b raw -> ('a * 'b) raw *) +(* | Prefix : 'b raw * 'a raw -> 'a raw *) +(* | Suffix : 'a raw * 'b raw -> 'a raw *) +(* | Rep : 'a raw -> 'a gen raw *) +(* | Mod : (Re.t -> Re.t) * 'a raw -> 'a raw *) + +(* val from_t : 'a t -> 'a raw *) +(* val to_t : 'a raw -> 'a t *) + +(* type _ wit = *) +(* | Lit : int -> string wit *) +(* | Conv : 'a wit * ('a, 'b) conv -> 'b wit *) +(* | Opt : Re.markid * 'a wit -> 'a option wit *) +(* | Alt : Re.markid * 'a wit * 'b wit *) +(* -> [`Left of 'a | `Right of 'b] wit *) +(* | Seq : *) +(* 'a wit * 'b wit -> ('a * 'b) wit *) +(* | Rep : int * 'a wit * Re.re -> 'a gen wit *) + +(* val build : int -> 'a raw -> int * 'a wit * Re.t *) +(* val extract : original:string -> 'a wit -> Re.substrings -> 'a *) + +(* end *)