sidekick/util/parsedimacs.ml
2014-11-09 23:39:54 +01:00

74 lines
1.6 KiB
OCaml

(*
MSAT is free software, using the Apache license, see file LICENSE
Copyright 2014 Guillaume Bury
Copyright 2014 Simon Cruanes
*)
exception Syntax_error of int
type line =
| Empty
| Comment
| Pcnf of int * int
| Clause of int list
let rec _read_word s acc i len =
assert (len>0);
if i+len=String.length s
then String.sub s i len :: acc
else match s.[i+len] with
| ' ' | '\t' ->
let acc = String.sub s i len :: acc in
_skip_space s acc (i+len+1)
| _ -> _read_word s acc i (len+1)
and _skip_space s acc i =
if i=String.length s
then acc
else match s.[i] with
| ' ' | '\t' -> _skip_space s acc (i+1)
| _ -> _read_word s acc i 1
let ssplit s = List.rev (_skip_space s [] 0)
let of_input f =
match ssplit (input_line f) with
| [] -> Empty
| "c" :: _ -> Comment
| "p" :: "cnf" :: i :: j :: [] ->
begin try
Pcnf (int_of_string i, int_of_string j)
with Failure _ ->
raise (Syntax_error (-1))
end
| l ->
begin try
begin match List.rev_map int_of_string l with
| 0 :: r -> Clause r
| _ -> raise (Syntax_error (-1))
end
with Failure _ -> raise (Syntax_error (-1))
end
let parse_with todo file =
let f = open_in file in
let line = ref 0 in
try
while true do
incr line;
todo (of_input f)
done
with
| Syntax_error _ ->
raise (Syntax_error !line)
| End_of_file ->
close_in f
let cnf = ref []
let parse_line = function
| Empty | Comment | Pcnf _ -> ()
| Clause l -> cnf := l :: !cnf
let parse f =
cnf := [];
parse_with parse_line f;
!cnf