(*
*)
use "../assignments/assign4Prelude.html";
val a = Char #"a"
val b = Char #"b"
val e = Epsilon
val nfa1 = map Edge
[(0,e,1),(0,e,3),(0,e,7),(0,e,9)
,(1,a,2)
,(3,a,4)
,(7,a,7),(7,b,8)
,(9,a,10)
,(4,b,5)
,(5,b,6)
,(8,b,8)
,(10,b,11)
,(11,a,12)
,(12,b,13)]
fun edgesOnFrom c n edges =
let fun p (Edge(s,cc,f)) = s=n andalso c=cc
in filter p edges end;
fun nodesOnFrom c n es =
let fun final (Edge(s,e,f)) = f
in map final (edgesOnFrom c n es) end;
fun nodesOnFromMany c xs es = concat(map (fn x => nodesOnFrom c x es) xs)
fun oneStep es xs = norm(xs @ nodesOnFromMany Epsilon xs es);
fun eclosure edges xs =
let val ys = oneStep edges xs
in if xs=ys then xs else eclosure edges ys end;
fun arcs ns edges =
let fun p (Edge(s,Char c,f)) = exists (fn x => x=s) ns
| p _ = false
fun char (Edge(s,Char c,f)) = c
in map char (filter p edges) end;
fun sigma edges =
let fun p (Edge(s,Char c,f)) = [c]
| p _ = []
in concat (map p edges) end;
fun nodup [] = []
| nodup [x] = [x]
| nodup(x::xs) = if exists (fn y => y=x) xs
then nodup xs
else x::(nodup xs);
val chars = nodup(sigma nfa1);
val s0 = eclosure nfa1 [0]
val s0a = nodesOnFromMany (Char #"a") s0 nfa1;
val s0b = nodesOnFromMany (Char #"b") s0 nfa1;
val s8 = eclosure nfa1 s0b
val s2 = eclosure nfa1 s0a
val s8a = nodesOnFromMany (Char #"a") s8 nfa1;
val s8b = nodesOnFromMany (Char #"b") s8 nfa1;
val s2a = nodesOnFromMany (Char #"a") s2 nfa1;
val s2b = nodesOnFromMany (Char #"b") s2 nfa1;
val s7 = eclosure nfa1 s2a
val s5 = eclosure nfa1 s2b
val s7a = nodesOnFromMany (Char #"a") s7 nfa1;
val s7b = nodesOnFromMany (Char #"b") s7 nfa1;
val s5a = nodesOnFromMany (Char #"a") s5 nfa1;
val s5b = nodesOnFromMany (Char #"b") s5 nfa1;
val s12 = eclosure nfa1 s5a;
val s6 = eclosure nfa1 s5b;
val s6a = nodesOnFromMany (Char #"a") s6 nfa1;
val s6b = nodesOnFromMany (Char #"b") s6 nfa1;
val s12a = nodesOnFromMany (Char #"a") s12 nfa1;
val s12b = nodesOnFromMany (Char #"b") s12 nfa1;
val s13 = eclosure nfa1 s12b
val s13a = nodesOnFromMany (Char #"a") s13 nfa1;
val s13b = nodesOnFromMany (Char #"b") s13 nfa1;
fun showL f start xs sep finish =
let fun help [] = ""
| help [x] = f x
| help (x::xs) = (f x)^sep^help xs
in start ^ (help xs) ^ finish end
fun printL message xs = print (message^(showL Int.toString "[" xs "," "]"))
fun printLL message xs =
let fun f xs = showL Int.toString "[" xs "," "]"
in print (message^(showL f "" xs "; " "\n")) end
fun printLc state xs =
let fun g (c,[]) = ""
| g (c,xs) = (showL Int.toString "[" state "," "]")^" --"^c^"--> "^(showL Int.toString "[" xs "," "]\n ")
in print (showL g " " xs "" "\n") end
fun snd(x,y) = y;
fun nfa2dfa start edges =
let val chars = nodup(sigma edges)
val s0 = eclosure edges [start]
val worklist = ref [s0]
val work = ref []
val old = ref []
val newEdges = ref []
in while (not (null (!worklist))) do
( work := hd(!worklist)
; old := (!work) :: (!old)
; worklist := tl(!worklist)
; let fun nextOn c = (Char.toString c,eclosure edges (nodesOnFromMany (Char c) (!work) edges))
val possible = map nextOn chars
fun add ((c,[])::xs) es = add xs es
| add ((c,ss)::xs) es = add xs ((!work,c,ss)::es)
| add [] es = es
fun ok [] = false
| ok xs = not(exists (fn ys => xs=ys) (!old)) andalso
not(exists (fn ys => xs=ys) (!worklist))
val new = filter ok (map snd possible)
in worklist := new @ (!worklist);
newEdges := add possible (!newEdges)
end
);
(s0,!old,!newEdges)
end;
fun nfa2dfa2 start edges =
let val chars = nodup(sigma edges)
val s0 = eclosure edges [start]
fun help [] old newEdges = (s0,old,newEdges)
| help (work::worklist) old newEdges =
let val processed = work::old
fun nextOn c = (Char.toString c
,eclosure edges (nodesOnFromMany (Char c) work edges))
val possible = map nextOn chars
fun add ((c,[])::xs) es = add xs es
| add ((c,ss)::xs) es = add xs ((work,c,ss)::es)
| add [] es = es
fun ok [] = false
| ok xs = not(exists (fn ys => xs=ys) processed) andalso
not(exists (fn ys => xs=ys) worklist)
val new = filter ok (map snd possible)
in help (new @ worklist) processed
(add possible newEdges) end
in help [s0] [] [] end;
(* *)