signature IFF_SOLVER =+ −
sig+ −
val decide : string -> bool+ −
end+ −
+ −
+ −
structure IffSolver : IFF_SOLVER =+ −
struct+ −
+ −
exception FAIL+ −
+ −
datatype formula = Atom of string | Iff of formula * formula+ −
+ −
fun scan s =+ −
let+ −
+ −
fun push yss = [] :: yss + −
+ −
fun add x (ys :: yss) = (x :: ys) :: yss+ −
| add _ _ = raise FAIL+ −
+ −
fun pop ([a, b] :: yss) = add (Iff (b, a)) yss+ −
| pop _ = raise FAIL+ −
+ −
fun formula [] acc = acc+ −
| formula ("(" :: xs) acc = formula xs (push acc)+ −
| formula (")" :: xs) acc = formula xs (pop acc)+ −
| formula ("<=>" :: xs) acc = formula xs acc+ −
| formula (x :: xs) acc = formula xs (add (Atom x) acc)+ −
+ −
val tokens = String.tokens (fn c => c = #" ") s+ −
in+ −
(case formula tokens [[]] of+ −
[[f]] => f+ −
| _ => raise FAIL)+ −
end+ −
+ −
+ −
fun decide s =+ −
let+ −
fun fold_atoms f (Atom n) = f s+ −
| fold_atoms f (Iff (p, q)) = fold_atoms f p #> fold_atoms f q+ −
+ −
fun collect s tab =+ −
(case Symtab.lookup tab s of+ −
NONE => Symtab.update (s, false) tab+ −
| SOME v => Symtab.update (s, not v) tab)+ −
+ −
fun check tab = Symtab.fold (fn (_, v) => fn b => b andalso v) tab true+ −
in + −
(case try scan s of+ −
NONE => false+ −
| SOME f => check (fold_atoms collect f Symtab.empty))+ −
end+ −
+ −
end+ −