Added small lexer/parser for dimacs (work in progress).

This commit is contained in:
Guillaume Bury 2014-11-01 21:43:58 +01:00
parent 709ea9740e
commit df524375a7
6 changed files with 105 additions and 29 deletions

View file

@ -20,7 +20,7 @@ doc:
$(COMP) $(FLAGS) $(DIRS) $(DOC) $(COMP) $(FLAGS) $(DIRS) $(DOC)
test: $(TEST) test: $(TEST)
./tests/main ./tests/main tests/test-0.d
$(TEST): $(LIB) $(TEST): $(LIB)
$(COMP) $(FLAGS) $(DIRS) $(TEST) $(COMP) $(FLAGS) $(DIRS) $(TEST)

View file

@ -1,6 +1,7 @@
(* Copyright 2014 Guillaume Bury *) (* Copyright 2014 Guillaume Bury *)
module Fsat = struct module Fsat = struct
exception Dummy
exception Out_of_int exception Out_of_int
(* Until the constant true_ and false_ are not needed anymore, (* Until the constant true_ and false_ are not needed anymore,
@ -10,6 +11,8 @@ module Fsat = struct
let max_lit = min max_int (- min_int) let max_lit = min max_int (- min_int)
let max_index = ref 0 let max_index = ref 0
let make i = if i <> 0 then i else raise Dummy
let dummy = 0 let dummy = 0
let neg a = - a let neg a = - a
@ -64,6 +67,8 @@ end
module Make(Dummy : sig end) = struct module Make(Dummy : sig end) = struct
module SatSolver = Solver.Make(Fsat)(Stypes)(Exp)(Tsat) module SatSolver = Solver.Make(Fsat)(Stypes)(Exp)(Tsat)
exception Bad_atom
type res = type res =
| Sat | Sat
| Unsat | Unsat
@ -73,8 +78,19 @@ module Make(Dummy : sig end) = struct
type atom = Fsat.t type atom = Fsat.t
type state = SatSolver.t type state = SatSolver.t
let new_atom () =
try
Fsat.create ()
with Fsat.Out_of_int ->
raise Bad_atom
let make i =
try
Fsat.make i
with Fsat.Dummy ->
raise Bad_atom
let neg = Fsat.neg let neg = Fsat.neg
let new_atom = Fsat.create
let hash = Fsat.hash let hash = Fsat.hash
let equal = Fsat.equal let equal = Fsat.equal

View file

@ -3,14 +3,22 @@
module Make(Dummy: sig end) : sig module Make(Dummy: sig end) : sig
(** Fonctor to make a pure SAT Solver module with built-in literals. *) (** Fonctor to make a pure SAT Solver module with built-in literals. *)
type atom exception Bad_atom
(** Abstract type for atoms, i.e boolean literals. *) (** Exception raised when a problem with atomic formula encoding is detected. *)
type atom = private int
(** Type for atoms, i.e boolean literals. *)
type res = Sat | Unsat type res = Sat | Unsat
(** Type of results returned by the solve function. *) (** Type of results returned by the solve function. *)
val new_atom : unit -> atom val new_atom : unit -> atom
(** [new_atom ()] returns a fresh literal. *) (** [new_atom ()] returns a fresh literal.
@raise Bad_atom if there are no more integer available to represent new atoms. *)
val make : int -> atom
(** Returns the literal corresponding to the integer.
@raise bad_atom if given [0] as argument.*)
val neg : atom -> atom val neg : atom -> atom
(** [neg a] returns the negation of a literal. Involutive, i.e [neg (neg a) = a]. *) (** [neg a] returns the negation of a literal. Involutive, i.e [neg (neg a) = a]. *)

16
util/lexdimacs.mll Normal file
View file

@ -0,0 +1,16 @@
(* Copyright 2005 INRIA *)
{
open Lexing;;
open Parsedimacs;;
}
let number = ['0' - '9']+
rule token = parse
| ' ' { token lexbuf }
| 'c' [^ '\n']* '\n' { token lexbuf }
| 'p' { P }
| "cnf" { CNF }
| '\n' { EOL }
| ['-']? number { LIT (int_of_string (Lexing.lexeme lexbuf)) }
| eof { EOF }

29
util/parsedimacs.mly Normal file
View file

@ -0,0 +1,29 @@
/* Copyright 2005 INRIA */
%{
exception Clause_ending of int
%}
%token <int> LIT
%token P CNF EOL EOF
%start file
%type <int list list> file
%%
/* DIMACS syntax */
file:
| EOF { [] }
| P CNF LIT LIT EOL clause_list { $6 }
;
clause_list:
| EOF { [] }
| clause clause_list { $1 :: $2 }
;
clause:
/* Clause always ends with a '0' */
| LIT EOL { if $1 = 0 then [] else raise (Clause_ending $1) }
| LIT clause { $1 :: $2 }
;

View file

@ -1,25 +1,32 @@
module S = Sat.Make(struct end) module S = Sat.Make(struct end)
let anon_fun = fun _ -> () (* Arguments parsing *)
let usage = "Coming soon..." let file = ref ""
let argspec = [
let input_file = fun s -> file := s
let usage = "Usage : main [options] <file>"
let argspec = Arg.align [
"-v", Arg.Int (fun i -> Log.set_debug i), "-v", Arg.Int (fun i -> Log.set_debug i),
"Sets the debug verbose level"; "<lvl> Sets the debug verbose level";
] ]
(* Temp until lexer/parsezr is set up *) (* Entry file parsing *)
let init () = let get_cnf () =
let v = Array.init 5 (fun _ -> S.new_atom ()) in let chan = open_in !file in
[ [ let lexbuf = Lexing.from_channel chan in
[v.(0); v.(1)]; let l = Parsedimacs.file Lexdimacs.token lexbuf in
[S.neg v.(0); v.(2)]; List.map (List.map S.make) l
[S.neg v.(1); v.(2)];
[v.(3); v.(4)]; let print_cnf cnf =
[S.neg v.(3); S.neg v.(2)]; Format.printf "CNF :@\n";
[S.neg v.(4); S.neg v.(2)]; List.iter (fun c ->
] Format.fprintf Format.std_formatter "%a;@\n"
] (fun fmt -> List.iter (fun a ->
Format.fprintf fmt "%a@ " S.print_atom a
)
) c
) cnf
(* Iterate over all variables created *) (* Iterate over all variables created *)
let print_assign fmt () = let print_assign fmt () =
@ -30,14 +37,14 @@ let print_assign fmt () =
) )
let main () = let main () =
Arg.parse argspec anon_fun usage; Arg.parse argspec input_file usage;
List.iter (fun l -> if !file = "" then begin
List.iter (fun c -> Format.printf "Adding : %a@." Arg.usage argspec usage;
(fun _ -> List.iter (fun a -> Format.printf "%a " S.print_atom a)) c) l; exit 2
S.assume l; end;
match S.solve () with let cnf = get_cnf () in
| S.Sat -> Format.printf "Sat@\n%a@." print_assign () print_cnf cnf;
| S.Unsat -> Format.printf "Unsat@.") (init ()); ()
;; ;;
main () main ()