package parsite
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A micro library for simple parsing combinators
Install
dune-project
Dependency
Authors
Maintainers
Sources
parsite-0.1.2.tbz
sha256=15f763e9d98014be41677913974ade7c1346bc5f8cae927b7fd24984c251879c
sha512=9fabb389cc6f68fa8b106a9939d41651824693192a1feb67cfda034e9bb18dd6c7702a43da10943ff462f762b5178349894291596fc1e1384c9b4e161de1551d
doc/src/parsite/combinators.ml.html
Source file combinators.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(* Parsite functions, courtesy of faber-1 This small library mostly provides some simple parsing functions that you can grow as you wish. This is a (hopefully continuous project. I shall add more to this as I find more cool parsing things to add. This library is very string focused. A lot of functions return results with strings, but the result and parser types are provided for custom tinkering. Also, the infix ops are a bit more flexible. Also this library raises errors. Can't decide if that makes the functions impure but I may try to fix the functions up later. happy parsing! *) open Types exception EmptyList of string (* inner reduce function for some shenanigans *) let reduce f lst = match lst with | [] -> None | h::t -> Some (List.fold_left f h t) ;; (* the fact String doesn't have an explode function is sad. *) let explode s = List.init (String.length s) (String.get s) ;; (* Infix concat, returns parser that concats p1 and p2. The return type value of the returned parser will have a tuple of the concatenated matches. *) let ( /> ) (p1 : ('a, 'b) p_func) (p2 : ('a, 'c) p_func) : ('a , 'b * 'c) p_func = fun str -> let open PResultM in p1 str >>= fun (a, s) -> p2 s >>= fun (a', s') -> return ((a, a'), s') ;; (* Infix or, will return parser for first match between p1 and p2 *) let ( >/ ) (p1 : ('a, 'b) p_func) (p2 : ('a, 'b) p_func) : ('a, 'b) p_func= fun str -> let open PResultM in p1 str =<< fun a -> p2 str =<< fun b -> fail (Printf.sprintf "Or Problem: Failed with following errors: (%s) and (%s)" a b) ;; (* Infix map, applies function f to parser output *) let ( />/ ) (p1 : ('a, 'b) p_func) (f : 'b -> 'c): ('a, 'c) p_func = fun (str : 'a) -> let open PResultM in p1 str >>= fun (a, str') -> return (f a, str') ;; (* Parse and ignore left of operator *) let ( @> ) (p1 : ('a, 'b) p_func) (p2 : ('a, 'b) p_func) : ('a, 'b) p_func = fun str -> let open PResultM in p1 str >>= fun (_, s) -> p2 s >>= fun (a', s') -> return (a', s') ;; (* Parse and ignore right of operator *) let ( >@ ) (p1 : ('a, 'b) p_func) (p2 :('a, 'b) p_func) : ('a, 'b) p_func = fun str -> let open PResultM in p1 str >>= fun (a, s) -> p2 s >>= fun (_, s') -> return (a, s') ;; (* Parse middle p2 without parsing p1 and p3 *) let p_middle p1 p2 p3 = p1 @> p2 >@ p3 let p_char (ch : char) : (string, char) p_func = fun str -> if str = "" then Lose "Empty String" else let first, rest = String.get str 0, String.sub str 1 (String.length str - 1) in if first = ch then Win (ch, rest) else Lose (Printf.sprintf "Expected char '%c', got char '%c'" ch first) ;; (* Takes a list of parsers lst, and creates a parser that contains the list of rules for each parser passed in *) let p_list (lst : ('a, 'b) p_func list) : ('a, 'b list) p_func = let concat p1 p2 = p1 /> p2 />/ fun (x, y) -> x @ y in let ps = lst |> List.map (fun a -> a />/ (fun e -> [e])) |> reduce concat in match ps with | Some p -> p | None -> raise (EmptyList "p_list cannot be called with empty list") ;; (* Gets list of parsers, creates parser that accepts input from any match *) let p_either (lst : ('a, 'b) p_func list) : ('a, 'b) p_func = match reduce (>/) lst with | Some a -> a | None -> raise (EmptyList "p_either cannot be called with empty list") ;; (* Creates parser for string str *) let p_string (str : string) : (string, string) p_func = let p_inner = (str |> explode |> List.map p_char |> p_list ) />/ (fun a -> String.of_seq (List.to_seq a)) in (fun a -> let open PResultM in p_inner a =<< fun _ -> fail (Printf.sprintf "Expected string '%s', got '%s'" str a)) ;; (* Creates parser for string of p1 concatted to string of p2 *) let p_concat_str (p1 : (string, string) p_func) (p2 : (string, string) p_func) : (string, string) p_func = p1 /> p2 />/ (fun (x,y) -> x ^ y) ;; (* Creates parser from concatenated strings in list *) let p_concat_strs (ps : (string, string) p_func list) : (string, string) p_func = match reduce p_concat_str ps with | Some a -> a | None -> raise (EmptyList "Cannot call p_concat_strs with an empty list.") (* Creates parser for character as a string *) let p_char_as_str (ch : char) : (string, string) p_func = p_string (String.make 1 ch) ;; (* Creates parser for 0 or more matches of p *) let p_many (p : (string, string) p_func) : (string, string) p_func = let rec inner acc str = let open PResultM in let acc' = (p str >>= fun (a, str') -> inner (acc ^ a) str') in acc' =<< fun _ -> return (acc, str) in inner "" ;; (* Creates parser for 1 or more matches of p *) let p_many1 (p : (string, string) p_func) : (string, string) p_func = p_concat_str p (p_many p) ;; (* Takes parsers list and delimiter, creates parser with delim in between parsers in ps *) let rec p_lister (ps : (string, string) p_func list) (delim : (string, string) p_func) = match ps with | [] -> raise (EmptyList "p_lister cannot be called with an empty ps") | [e] -> e | p::ps -> p_concat_str (p_concat_str p delim) (p_lister ps delim) ;; (* lowercase, uppercase, and digits parsers *) let p_lower : (string, string) p_func = p_either (List.map p_char_as_str (explode "abcdefghijklmnopqrstuvwxyz")) ;; let p_upper : (string, string) p_func = p_either (List.map p_char_as_str (explode "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) ;; let p_digits : (string, string) p_func = p_either (List.map p_char_as_str (explode "0123456789")) ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>