File: ccparse_irclogs_real.cond.ml

package info (click to toggle)
ocaml-containers 3.15%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 2,412 kB
  • sloc: ml: 33,221; sh: 122; makefile: 32
file content (80 lines) | stat: -rw-r--r-- 1,918 bytes parent folder | download
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