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
|
(* parse IRC logs *)
type datetime = {
year: int;
month: int;
day: int;
hour: int;
min: int;
sec: int;
}
let pp_datetime out d =
let { year; month; day; hour; min; sec } = d in
CCFormat.(
fprintf out "{y=%d;M=%d;d=%d;h=%d;m=%d;s=%d}" year month day hour min sec)
type msg = {
timestamp: datetime;
user: string;
msg: string;
}
let pp_msg out m =
CCFormat.fprintf out "{@[time=%a;@ user=%S;@ msg=%S@]}" pp_datetime
m.timestamp m.user m.msg
open CCParse
let p_datetime : datetime t =
let int = U.int in
let* date, time = split_2 ~on_char:' ' in
let* y, m, d = recurse date (split_3 ~on_char:'-') in
let* year = recurse y int in
let* month = recurse m int in
let* day = recurse d int in
let* hour, min, sec =
recurse time
(let* hour = int in
char ':'
*> let* min = int in
char ':'
*> let+ sec = int in
hour, min, sec)
in
let dt = { year; month; day; hour; min; sec } in
return dt
let p_line =
let* line = lookahead all in
if Slice.is_empty line then
return None
else
let* fields = split_list ~on_char:'\t' in
match fields with
| [ date; user; rest ] ->
let+ timestamp = recurse date p_datetime
and+ user =
recurse user
(chars_if (function
| '>' -> false
| _ -> true))
and+ msg = recurse rest (all_str >|= String.trim) in
Some { timestamp; user; msg }
| _ ->
failf "expected 3 fields, got [%s]"
(String.concat ";" @@ List.map String.escaped
@@ List.map Slice.to_string fields)
let p_file = each_line (parsing "line" p_line) >|= CCList.keep_some
let () =
let s = CCIO.File.read_exn Sys.argv.(1) in
match parse_string p_file s with
| Ok l ->
Format.printf "parsed:@.";
List.iter (Format.printf "%a@." pp_msg) l
| Error e ->
Format.printf "parse error: %s@." e;
exit 1
|