module Lecture1
where
import qualified NFAe as Ne
import NFAe (eclosure)
import qualified NFA as N
import qualified DFA as D
import PP
import PrintDFA
import PrintNFA
import PrintNFAe
import List

unionDFA :: (Eq q1, Eq q2) => D.DFA q1 s -> D.DFA q2 s -> D.DFA (q1, q2) s
unionDFA (D.DFA { D.states = bigQ1, D.symbols = sigma, D.delta = d1, D.start = q10, D.final = f1})
         (D.DFA { D.states = bigQ2, D.delta = d2, D.start = q20, D.final = f2})  
    = D.DFA { D.states = [(q1,q2) | q1 <- bigQ1, q2 <- bigQ2],
              D.symbols = sigma,
              D.delta = \ (q1,q2) a -> (d1 q1 a, d2 q2 a),
              D.start = (q10,q20),
              D.final = nub $ [(q1,q2) | q1 <- f1, q2 <- bigQ2] ++ 
                              [(q1,q2) | q1 <- bigQ1, q2 <- f2]}


powerSet :: [a] -> [[a]]
powerSet [] = [[]]
powerSet (a:l) = let pl = powerSet l
              in pl ++ map (a:) pl

nfaToDfa :: (Eq q) => N.NFA q s -> D.DFA [q] s
nfaToDfa (N.NFA {N.states = bigQ,
                 N.symbols = sigma,
                 N.delta = d,
                 N.start = q0,
                 N.final = f}) 
    = D.DFA { D.states = powerSet bigQ,
              D.symbols = sigma,
              D.delta = \ps a -> unions $ [d p a | p <- ps],
              D.start = [q0],
              D.final = [qs | qs <- powerSet bigQ, not $ null $ intersect qs f]}

nfaeToDfa :: (Eq q) => Ne.NFAe q s -> D.DFA [q] s
nfaeToDfa (Ne.NFAe {Ne.states = bigQ,
                    Ne.symbols = sigma,
                    Ne.delta = d,
                    Ne.start = q0,
                    Ne.final = f}) 
    = D.DFA { D.states = powerSet bigQ,
              D.symbols = sigma,
              D.delta = \ps a -> eclosure bigQ d $ unions $ [d p (Just a) | p <- ps],
              D.start = eclosure bigQ d [q0],
              D.final = [qs | qs <- powerSet bigQ, not $ null $ intersect qs f]}

