Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
parserMonad.ml1 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 165open Util open Llist type ts = char llist type state = int * int * (char list * char * char list) type error = state * string type 'a t = state -> ts -> ('a * state * ts, error) either exception ParseError of string let lt_pos (l1,p1,_) (l2,p2,_) = if l1 < l2 then true else if l1 = l2 then p1 < p2 else false let eplus (st1,msg1) (st2,msg2) = if lt_pos st1 st2 then (st2,msg2) else (st1,msg1) let showerr ((line,pos,(pre,c,post)),msg) = !%"line %d, %d: %s: pre=%S char=%C post=%S" line pos msg (string_of_chars pre) c (string_of_chars post) let return : 'a -> 'a t = fun x -> fun state code -> Inl (x, state, code) let error msg = fun state _code -> Inr (state, msg) let (>>=) : 'a t -> ('a -> 'b t) -> 'b t = fun p f -> fun state code -> match p state code with | Inl (x, state', ts) -> f x state' ts | Inr err -> Inr err let (>>) : 'a t -> 'b t -> 'b t = fun p1 p2 -> p1 >>= fun _ -> p2 let (<.<) : 'a t -> 'b t -> 'a t = fun p1 p2 -> p1 >>= fun x -> p2 >> return x let ( ^? ) : 'a t -> string -> 'a t = fun p msg -> fun state code -> match p state code with | Inl l -> Inl l | Inr (st,msg0) -> Inr (st,msg ^": "^msg0) (* (<|>) : 'a m -> 'a m -> 'a m *) let (<|>) : 'a t -> 'a t -> 'a t = fun p1 p2 -> fun state code -> match p1 state code with | Inl (x1, state', ts) -> Inl (x1, state', ts) | Inr err1 -> begin match p2 state code with | Inl (x2, state', ts) -> Inl (x2,state',ts) | Inr err2 -> Inr (eplus err1 err2) end (* let (<|?>) p1 p2 = fun state code -> match p1 state code with | Inl (x1, state', ts) -> Inl (x1, state', ts) | Inr err1 -> print_endline err1; begin match p2 state code with | Inl (x2, state', ts) -> Inl (x2,state',ts) | Inr err2 -> Inr (eplus err1 err2) end *) let rec many : 'a t -> ('a list) t = fun p -> (p >>= fun x -> many p >>= fun xs -> return (x::xs)) <|> (return []) let many1 p = p >>= fun x -> many p >>= fun xs -> return (x::xs) let sep separator p = (p >>= fun x -> many (separator >> p) >>= fun xs -> return (x::xs)) <|> (return []) let opt : 'a t -> ('a option) t = fun p -> (p >>= fun x -> return (Some x)) <|> (return None) let _char1_with_debug state = function | Nil -> Inr (state,"(Nil)") | Cons (x,xs) -> let next (pre,x0, _) = let pre' = if List.length pre < 100 then pre @ [x0] else List.tl pre @ [x0] in (pre' , x, Llist.take 100 !$xs) in match x, state with | '\n', (line,_pos,cs) -> Inl (x,(line+1,-1, next cs), !$xs) | _, (line,pos,cs) -> Inl (x,(line, pos+1, next cs),!$xs) let char1_without_debug state = function | Nil -> Inr (state,"(Nil)") | Cons (x,xs) -> Inl (x, state, !$xs) let char1 = char1_without_debug let char_when f = char1 >>= fun c -> if f c then return c else error (!%"(char:'%c')" c) let char c = char_when ((=) c) let keyword w = let rec iter i = if i < String.length w then char w.[i] >> iter (i+1) else return w in iter 0 let make_ident f = many1 (char_when f) >>= fun cs -> return (string_of_chars cs) let int = opt (char '-') >>= fun minus -> make_ident (function '0'..'9' -> true | _ -> false) >>= fun s -> return begin match minus with | None -> int_of_string s | Some _ -> - int_of_string s end let run p state ts = match p state ts with | Inl (x,_state',_xs) -> x | Inr err -> raise (ParseError (showerr err)) let init_state = (1, 0, ([],'_',[])) let run_ch p ch = run p init_state (Llist.of_stream (Stream.of_channel ch)) let run_stdin p = run_ch p stdin let run_file p filename = open_in_with filename (fun ch -> run_ch p ch) let run_string p s = run p init_state (Llist.of_string s) let run_function p f = run p init_state (Llist.of_function f)