module L = Dimacs_lexer type t = { buf: Lexing.lexbuf; mutable header: (int * int) option; } let create (ic:in_channel) : t = let buf = Lexing.from_channel ic in {buf; header=None} let parse_header self = match self.header with | Some tup -> tup | None -> let i, j = try (match L.token self.buf with | L.P -> (match L.token self.buf with | L.CNF -> (match L.token self.buf with | L.LIT i -> (match L.token self.buf with | L.LIT j -> i,j | _ -> raise Exit) | _ -> raise Exit) | _ -> raise Exit) | _ -> raise Exit ) with Exit -> Error.errorf "expected file to start with header" in self.header <- Some (i,j); i,j let next_clause self : _ option = let rec loop acc = match L.token self.buf with | L.EOF when acc=[] -> None | L.EOF -> Error.errorf "unexpected EOF in a clause" | L.ZERO -> Some (List.rev acc) | L.LIT i -> loop (i::acc) | _ -> Error.errorf "expected clause" in loop [] let iter self k = ignore (parse_header self : _*_); let rec loop () = match next_clause self with | None -> () | Some c -> k c; loop () in loop ()