package containers
A modular, clean and powerful extension of the OCaml standard library
Install
Dune Dependency
Authors
Maintainers
Sources
containers-3.13.1.tbz
sha256=eb9b26eb2c3cf04fc5157d256eb49c43552ccb5c59c568772d70315db9669784
sha512=7f4cf5112c8047fd789c04129745dbe9783aa94390e8983f86408053b0af637e2a9cfce1559ce466b1b6ff7c01fd52d8685f5db1d1c0dda2c0aa138f90606a50
doc/src/containers/CCSexp.ml.html
Source file CCSexp.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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
(* This file is free software, part of containers. See file "license" for more details. *) (** {1 Simple S-expression parsing/printing} *) type 'a or_error = ('a, string) result type 'a gen = unit -> 'a option module type SEXP = CCSexp_intf.SEXP module type S = CCSexp_intf.S let equal_string (a : string) b = Stdlib.( = ) a b let compare_string (a : string) b = Stdlib.compare a b 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 module Make (Sexp : SEXP) = struct type t = Sexp.t type sexp = t type loc = Sexp.loc let atom = Sexp.atom let list = Sexp.list let of_int x = Sexp.atom (string_of_int x) let of_float x = Sexp.atom (string_of_float x) let of_bool x = Sexp.atom (string_of_bool x) let of_unit = Sexp.list [] let of_list l = Sexp.list l let of_rev_list l = Sexp.list (List.rev l) let of_pair (x, y) = Sexp.list [ x; y ] let of_triple (x, y, z) = Sexp.list [ x; y; z ] let of_quad (x, y, z, u) = Sexp.list [ x; y; z; u ] let of_variant name args = Sexp.list (Sexp.atom name :: args) let of_field name t = Sexp.list [ Sexp.atom name; t ] let of_record l = Sexp.list (List.map (fun (n, x) -> of_field n x) l) (** {3 Printing} *) (* shall we escape the string because of one of its chars? *) let _must_escape s = try for i = 0 to String.length s - 1 do let c = String.unsafe_get s i in match c with | ' ' | ')' | '(' | '"' | ';' | '\\' | '\n' | '\t' | '\r' -> raise Exit | _ when Char.code c > 127 -> raise Exit (* non-ascii *) | _ -> () done; false with Exit -> true (* empty atoms must be escaped *) let _must_escape s = String.length s = 0 || _must_escape s let rec to_buf b t = Sexp.match_ t ~atom:(fun s -> if _must_escape s then Printf.bprintf b "\"%s\"" (String.escaped s) else Buffer.add_string b s) ~list:(function | [] -> Buffer.add_string b "()" | [ x ] -> Printf.bprintf b "(%a)" to_buf x | l -> Buffer.add_char b '('; List.iteri (fun i t' -> if i > 0 then Buffer.add_char b ' '; to_buf b t') l; Buffer.add_char b ')') let to_string t = let b = Buffer.create 128 in to_buf b t; Buffer.contents b let rec pp fmt t = Sexp.match_ t ~atom:(fun s -> if _must_escape s then Format.fprintf fmt "\"%s\"" (String.escaped s) else Format.pp_print_string fmt s) ~list:(function | [] -> Format.pp_print_string fmt "()" | [ x ] -> Format.fprintf fmt "@[<hov2>(%a)@]" pp x | l -> Format.fprintf fmt "@[<hov1>("; List.iteri (fun i t' -> if i > 0 then Format.fprintf fmt "@ "; pp fmt t') l; Format.fprintf fmt ")@]") let rec pp_noindent fmt t = Sexp.match_ t ~atom:(fun s -> if _must_escape s then Format.fprintf fmt "\"%s\"" (String.escaped s) else Format.pp_print_string fmt s) ~list:(function | [] -> Format.pp_print_string fmt "()" | [ x ] -> Format.fprintf fmt "(%a)" pp_noindent x | l -> Format.pp_print_char fmt '('; List.iteri (fun i t' -> if i > 0 then Format.pp_print_char fmt ' '; pp_noindent fmt t') l; Format.pp_print_char fmt ')') let to_chan oc t = let fmt = Format.formatter_of_out_channel oc in pp fmt t; Format.pp_print_flush fmt () let to_file_iter filename seq = _with_out filename (fun oc -> seq (fun t -> to_chan oc t; output_char oc '\n')) let to_file filename t = to_file_iter filename (fun k -> k t) (** {2 Parsing} *) (** A parser of ['a] can return [Yield x] when it parsed a value, or [Fail e] when a parse error was encountered, or [End] if the input was empty *) type 'a parse_result = Yield of 'a | Fail of string | End module Decoder = struct module L = CCSexp_lex type t = { buf: Lexing.lexbuf; mutable cur_tok: L.token option; (* current token *) } let cur (t : t) : L.token = match t.cur_tok with | Some L.EOI -> assert false | Some t -> t | None -> (* fetch token *) let tok = L.token t.buf in t.cur_tok <- Some tok; tok let junk t = t.cur_tok <- None let of_lexbuf buf = { buf; cur_tok = None } exception E_end exception E_error of int * int * string let pair_of_pos_ p = let open Lexing in p.pos_lnum, p.pos_cnum - p.pos_bol let loc_of_buf_with_ ?start buf f = let open Lexing in let start = match start with | Some p -> p | None -> buf.lex_start_p in f (pair_of_pos_ start) (pair_of_pos_ buf.lex_curr_p) buf.lex_curr_p.pos_fname let[@inline] loc_of_buf_ (self : t) : loc option = match Sexp.make_loc with | None -> None | Some f -> Some (loc_of_buf_with_ self.buf f) let last_loc = loc_of_buf_ let error_ lexbuf msg = let start = Lexing.lexeme_start_p lexbuf in let line, col = pair_of_pos_ start in raise (E_error (line, col, msg)) let next (t : t) = let open Lexing in let rec expr () = match cur t with | L.EOI -> raise E_end | L.SEXP_COMMENT -> junk t; let _u = expr () in (* discard next sexp *) expr () | L.ATOM s -> junk t; (match Sexp.make_loc with | None -> Sexp.atom s | Some f -> (* build a position for this token *) let loc = loc_of_buf_with_ t.buf f in Sexp.atom_with_loc ~loc s) | L.LIST_OPEN -> let pos_start = t.buf.lex_curr_p in junk t; let l = lst [] in (match cur t with | L.LIST_CLOSE -> junk t; (match Sexp.make_loc with | None -> Sexp.list l | Some f -> let loc = loc_of_buf_with_ ~start:pos_start t.buf f in Sexp.list_with_loc ~loc l) | _ -> error_ t.buf "expected ')'") | L.LIST_CLOSE -> error_ t.buf "expected expression" and lst acc = match cur t with | L.LIST_CLOSE -> List.rev acc | L.LIST_OPEN | L.ATOM _ | L.SEXP_COMMENT -> let sub = expr () in lst (sub :: acc) | L.EOI -> error_ t.buf "unexpected EOI" in try Yield (expr ()) with | E_end -> End | E_error (line, col, msg) | CCSexp_lex.Error (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 -> Ok (List.rev acc) | Yield x -> iter (x :: acc) | Fail e -> Error e in try iter [] with e -> Error (Printexc.to_string e) end let dec_next_ (d : Decoder.t) : _ or_error = match Decoder.next d with | End -> Error "unexpected end of file" | Yield x -> Ok x | Fail s -> 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 open Lexing in match file with | Some s -> buf.lex_start_p <- { buf.lex_start_p with pos_fname = s } | None -> () let parse_chan_ ?file ic : sexp or_error = let buf = Lexing.from_channel ic in set_file_ ?file buf; let d = Decoder.of_lexbuf buf in dec_next_ d let parse_chan_list_ ?file ic = let buf = Lexing.from_channel ic in set_file_ ?file buf; let d = Decoder.of_lexbuf buf in Decoder.to_list d let parse_chan ic = parse_chan_ ic let parse_chan_list ic = parse_chan_list_ ic let parse_chan_gen ic = let buf = Lexing.from_channel ic in let d = Decoder.of_lexbuf buf in fun () -> match Decoder.next d with | End -> None | Fail e -> Some (Error e) | Yield x -> Some (Ok x) let parse_file filename = _with_in filename (parse_chan_ ~file:filename) let parse_file_list filename = _with_in filename (parse_chan_list_ ~file:filename) end type t = [ `Atom of string | `List of t list ] let rec equal a b = match a, b with | `Atom s1, `Atom s2 -> equal_string s1 s2 | `List l1, `List l2 -> (try List.for_all2 equal l1 l2 with Invalid_argument _ -> false) | `Atom _, _ | `List _, _ -> false let rec compare_list a b = match a, b with | [], [] -> 0 | [], _ :: _ -> -1 | _ :: _, [] -> 1 | x :: xs, y :: ys -> (match compare x y with | 0 -> compare_list xs ys | c -> c) and compare a b = match a, b with | `Atom s1, `Atom s2 -> compare_string s1 s2 | `List l1, `List l2 -> compare_list l1 l2 | `Atom _, _ -> -1 | `List _, _ -> 1 module Basic_ = struct type nonrec t = t type loc = unit let make_loc = None let atom x = `Atom x let list x = `List x let atom_with_loc ~loc:_ s = atom s let list_with_loc ~loc:_ l = list l let match_ x ~atom ~list = match x with | `Atom x -> atom x | `List l -> list l end include (Make (Basic_) : S with type t := t and type loc = unit) let atom s : t = `Atom s
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>