Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
qinap.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
open Base (* Helper functions for working with lists of characters. -------------------- *) module Clist = struct type t = char list let to_string cs = List.map cs ~f:Char.to_string |> String.concat let of_string s = let rec loop idx acc = if idx < 0 then acc else loop (idx - 1) (s.[idx] :: acc) in loop (String.length s - 1) [] end (* Helper functions for working with strings. -------------------------------- *) module Ext_string = struct let hd s = if String.length s = 0 then None else Some s.[0] let tl s = let n = String.length s in if n = 0 then "" else String.suffix s (n - 1) end (* Type of parsers. ---------------------------------------------------------- *) type 'a parser = string -> ('a * string) option (* Primitive parsers. -------------------------------------------------------- *) let result x = fun s -> Some (x, s) let zero = fun _ -> None let item = fun s -> match Ext_string.hd s with | None -> None | Some c -> Some (c, Ext_string.tl s) (* Primitive combinators. ---------------------------------------------------- *) let ( => ) p f = fun s -> match p s with | None -> None | Some (x, s') -> Some (f x, s') let ( let* ) p f = fun s -> match p s with | None -> None | Some (x, s') -> f x s' let ( <|> ) p q = fun s -> match p s with | None -> q s | Some _ as x -> x (* Derived combinators. ------------------------------------------------------ *) let ( >> ) p q = let* _ = p in q let ( << ) p q = let* x = p in let* _ = q in result x let ( <~> ) p ps = let* x = p in let* xs = ps in result (x :: xs) (* Note: this can't be rewritten as (p <~> many p) <|> result []. OCaml is not lazy, so that generates an infinite loop. *) let rec many p = let any = let* x = p in let* xs = many p in result (x :: xs) in any <|> result [] let many1 p = p <~> many p (* Derived parsers. ---------------------------------------------------------- *) let satisfy ~f = let* x = item in if f x then result x else zero let char c = satisfy ~f:(Char.equal c) let rec clist = function | [] -> result [] | c :: cs -> char c <~> clist cs let string s = Clist.of_string s |> clist => Clist.to_string let rec one_of = function | [] -> zero | c :: cs -> char c <|> one_of cs let between p ~l ~r = l >> p << r (* Parsers and combinators for dealing with whitespace. ---------------------- *) let sep_by1 p ~sep = let p' = let* _ = sep in p in let* x = p in let* xs = many p' in result (x :: xs) let sep_by p ~sep = (sep_by1 p ~sep) <|> result [] let space = satisfy ~f:Char.is_whitespace let spaces = many1 space (* Parsers and combinators for dealing with numbers. ------------------------- *) let digit = satisfy ~f:Char.is_digit let digits = many digit => Clist.to_string let digits1 = many1 digit => Clist.to_string let natural = digits1 => Int.of_string let integer = let un_op = ((char '-') >> result Int.neg) <|> (result (fun x -> x)) in let* op = un_op in let* x = natural in result (op x) let float = let un_op = ((char '-') >> result Float.neg) <|> (result (fun x -> x)) and maybe_dot = ((char '.') => Char.to_string) <|> (result "") in let* op = un_op in let* whole = digits1 in let* sep = maybe_dot in let* decimal = digits1 in result [whole; sep; decimal] => String.concat => Float.of_string => op