MParser tutorial
Introduction
string parsing have two step
- build a parser
- parse string use that parser
parse a float number
there is alreay a token (parser) we can use,
utop # #require "mparser";;
utop # MParser.parse_string MParser.Tokens.float "12.5" ();;
- : float MParser.result = MParser.Success 12.5
parse a list of float
let list_of_float = let open MParser in
    sep_by Tokens.float (char ';');; 
utop # MParser.parse_string list_of_float "1.24;1.45;1.23" ();;
- : float MParser.result = MParser.Success 1.24
parse float in brackets
let float_between_brackets = let open MParser in
    between ( char '[') ( char ']') Tokens.float;; 
utop # MParser.parse_string float_between_brackets "[1.24]" ();;
- : float MParser.result = MParser.Success 1.24
let float_between_brackets = let open MParser in
    Tokens.squares Tokens.float;; 
utop # MParser.parse_string float_between_brackets "[1.24]" ();;
- : float MParser.result = MParser.Success 1.24
parse a list of float in bracket
parsing string data
utop # MParser.parse_string MParser.(many (char 'a' <|> char 'b')) "abba" ();;
- : char list MParser.result = MParser.Success [a; b; b; a]
parse a list of float
Final version
open Core.Std;;
(* define ocaml type *)
type product =
  | Mouse
  | Keyboard
  | Monitor
  | Speakers ;;
let product_of_string = function
  | "mouse" -> Mouse
  | "keyboard" -> Keyboard
  | "monitor" -> Monitor
  | "speakers" -> Speakers
  | _ -> failwith "wrong input";;
type log_entry = { entry_time : Time.t;
                   entry_ip   : UnixLabels.inet_addr; 
                   entry_product: product
                 };; 
let log_entry_time_to_string entry = Time.to_string entry.entry_time;;
(* parse rule *) 
let date_rule = let open MParser in
  many_chars_until any_char (char ' ');;
let time_rule = let open MParser in
  many_chars_until any_char (char ' ');;
let ip_rule = let open MParser in
  many_chars_until any_char (char ' ');;
let product_rule = let open MParser in 
  (MParser.string "mouse")  <|>
  (MParser.string "keyboard")  <|>
  (MParser.string "monitor") <|>
  (MParser.string "speakers");; 
let log_rule = let open MParser in
  pipe4 date_rule time_rule ip_rule product_rule
    (fun date time ip prod -> { entry_time =  Time.of_string (date ^ " " ^ time) ;
                                entry_ip = UnixLabels.inet_addr_of_string ip;
                                entry_product =  product_of_string prod 
                              }
    );;
let logs_rule = let open MParser in
  end_by log_rule newline;;
(* extract the time of each one *)
let extract_parser_result presult =
  match presult with
  | MParser.Success(result)   -> String.concat ~sep:"\n" @@ 
    List.map result ~f:log_entry_time_to_string
  | MParser.Failed(error_msg, _) ->  error_msg;;
let () = 
  let txt = String.drop_suffix (In_channel.read_all "log.txt") 1 in 
  MParser.parse_string logs_rule txt () |> extract_parser_result  |> print_string;;