Introduction

string parsing have two step

  1. build a parser
  2. 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;;