module Main where
--import IO ( stdin, hGetContents )
--import System ( getArgs, getProgName )
import System.IO
import System.Environment
import Data.Map
import Lexjava
import Parjava
import Skeljava
import Printjava
import Absjava
import GuiX
import SlicingX
import Data.List
import Data.Char
import ErrM
splitString :: String -> [String]
splitString s = let res = Data.List.filter (notElem ' ') $ groupBy fGroup s
res1 = Data.List.filter (notElem ',') res
res2 = ["\""++e++"\""|e<-res1]
in res2
fGroup :: Char -> Char -> Bool
fGroup c1 c2 | c1 /= ',' && c1 /= ' ' && c2 /= ',' && c2 /= ' ' = True
| otherwise = False
ffff :: String -> [(Int,(String,[[String]],Int,Int,[(Int,Int)]))]
ffff s = read s
actionsAnalyse :: IO [(Int,(String,Bool))]
actionsAnalyse = do s <- runFile "actionsEnum.txt"
let act = [(a,concat c) | (a,(b,c,d,e,f)) <- ffff s]
let act1 = [(a,slicen c "HsIdent")| (a,c) <- act]
writeFile "lixo10.txt" (show act1)
let act1a = [(a,[e | e <-(b!!0), e /= '"', e/= '\\'],b!!1)| (a,b) <- act1,length b == 2,(b!!0)=="\"enabled\""]
writeFile "lixo11.txt" (show act1a)
let act2 = [(a,(b,True))|(a,b,c)<-act1a,(c=="\"True\"")]++[(a,(b,False))|(a,b,c)<-act1a,(c=="\"False\"")]
return act2
actionsAnalyse1 :: IO [Int]
actionsAnalyse1 = do s <- runFile "actionsEnum.txt"
let act = [(a,concat c) | (a,(b,c,d,e,f)) <- ffff s]
let act1 = [(a,slicen c "HsIdent")| (a,c) <- act]
let act1a = [a| (a,b) <- act1,Data.List.elem "\"exitSuccess\"" b]
return act1a
actionsAnalyse3 :: [String] -> IO [(Int,String)]
actionsAnalyse3 l = do s <- runFile "actionsEnum.txt"
putStrLn s
let act = [(a,concat c) | (a,(b,c,d,e,f)) <- ffff s]
let act1 = [(a,sliceAll c "HsQualifier")| (a,c) <- act]
let act2 = [(a,sliceAll b "HsIdent")| (a,b) <- act1]
--let act5 = [(a,sliceAll b "\"start\"")| (a,b) <- act2]
--putStrLn act2
writeFile "lixo" (show act2)
let act3 = [(a,[e|e<-b!!1, e /= '"', e /= '\\']) | (a,b) <- act2 , length b > 0, (b!!0) == "\"start\"", elem (b!!1) l]
--let act3 = [(a,[e|e<-(b!!0), e /= '"', e /= '\\']) | (a,b) <- act5, elem (b!!0) l]
--putStrLn act3
return act3
actionsAnalyse4 :: IO [Int]
actionsAnalyse4 = do s <- runFile "actionsEnum.txt"
let act = [(a,concat c) | (a,(b,c,d,e,f)) <- ffff s]
let act1 = [(a,slicen c "HsIdent")| (a,c) <- act]
writeFile "lixo.txt" (show act1)
let act1a = [a| (a,b) <- act1, Data.List.elem "\"close\"" b] --(b!!0)=="\"dispose\""]
return act1a
ff :: String -> [((String,[[String]],Int,Int,[(Int,Int)]),[(String,[[String]],Int,Int,[(Int,Int)])])]
ff s = read s
fff :: String -> [(String,[[String]],Int,Int,[(Int,Int)])]
fff s = read s
runFile :: FilePath -> IO String
runFile f = putStrLn f >> readFile f
-- putStrV v $ "\n[Abstract Syntax]\n\n" ++ show tree
-- putStrV v $ "\n[Linearized tree]\n\n" ++ printTree tree
-- writeFile "res2.lixo" (show $ (executedCode (mainMethod (show tree)) (show tree) (-1) (-1)))
-- writeFile "res3.lixo" (show $ (statementAddActionListener (show tree) ))
-- writeFile "res4.lixo" (show $ (slice (show tree) "Emth" 1 2))
-- writeFile "res5.lixo" (show $ initState (show tree))
-- writeFile "res6.lixo" (show $ eventsFromInitState (show tree))
-- writeFile "res8.lixo" (show $ initAdd (show tree))
-- putStrV v $ "\n[Linearized tree]\n\n" ++ printTree (Ffvar (Cthis SSthis) (Ident "mark1"))
splitEvents [] n = ([],[])
splitEvents ((e1,e2):t) n = let (a,b) = splitEvents t (n+1)
in ([("event"++show n,e2)]++a,[("event"++show n,e1)]++b)
splitCond [] n = ([],[])
splitCond ((e1,e2,e3):t) n = let (a,b) = splitCond t (n+1)
in ([(e1,"cond"++show n,e3)]++a,[("cond"++show n,e2)]++b)
splitCondInit [] n = ([],[])
splitCondInit ((e1,e2,e3):t) n = let (a,b) = splitCondInit t (n+1)
in ([(e1,"condInit"++show n,e3)]++a,[("condInit"++show n,e2)]++b)
-- 1 befor, 0 after, -1 x1 in x2, -2 x2 in x1
firstTerm :: (String,[[String]],Int,Int,[(Int,Int)]) -> (String,[[String]],Int,Int,[(Int,Int)]) -> Int
firstTerm (x1,y1,z1,v1,[]) (x2,y2,z2,v2,[]) | v1 < z2 = 1
| z1 > v2 = 0
| z1 > z2 && v1 < v2 = -1
| otherwise = -2
firstTerm (x1,y1,z1,v1,((a,b):t1)) (x2,y2,z2,v2,((c,d):t2)) | a==c && b==d = firstTerm (x1,y1,z1,v1,t1) (x2,y2,z2,v2,t2)
| b <c = 1
| otherwise = 0
firstTerm (x1,y1,z1,v1,[]) (x2,y2,z2,v2,((c,d):t2)) | v1 < c = 1
| z1 > d = 0
| z1 < c && v1 > d = -2
| otherwise = -1
firstTerm (x1,y1,z1,v1,(c,d):t1) (x2,y2,z2,v2,[]) | v2 < c = 0
| z2 > d = 1
| z2 < c && v2 > d = -1
| otherwise = -2
--orderCond :: [(String,[[String]],Int,Int,[(Int,Int)])] -> [[(String,[[String]],Int,Int,[(Int,Int)])]]
--orderCond l = let firstCond
--recebe uma lista de cond ordenadas e uma cond e coloca a cond na lista ordenada
ordIf [] ifcond = [ifcond]
ordIf (h:t) ifcond
| firstTerm h ifcond == -2 = (h:(ordIf t ifcond))
| firstTerm h ifcond == -1 = (ifcond:(h:t))
| firstTerm h ifcond == 0 = (ifcond:(h:t))
| firstTerm h ifcond == 1 = (h:(ordIf t ifcond)) -- (ifcond:(h:t))
| otherwise = []
--ordList :: [a] -> [[a]] -- all cond list
ordList [] = []
ordList [e] = [[e]]
ordList (h:(g:t)) | firstTerm h g == -2 = [h:e | e <- ordList (g:t)]
| firstTerm h g == -1 = [g:e | e <- ordList (h:t)] -- ????
| firstTerm h g == 0 = (ordList (h:t))++(ordList (g:t))
| firstTerm h g == 1 = (ordList (h:t))++(ordList (g:t))
| otherwise = []
-- recebe lista de todas as cond e devolve lista ordenada de cond
ordifaux [] l = l
ordifaux (h:t) l = let res = (ordIf l h)
in ordifaux t (res) --ordifaux t (res++l) -- ????
-- -> recebe duas listas de cond iguais e devolve lista de listas ordenadas de cond
ordIfs lifcond [] = []
ordIfs lifcond (h:t) = (nub $ ordifaux lifcond [h]) ++ (ordIfs lifcond t)
ordIfs2 l = let a1 = [(a,b,c,d,e)|(a,b,c,d,e)<-l,a/="If2"]
a2 = [(a,b,c,d,e)|(a,b,c,d,e)<-l,a/="If1"]
in [a1] ++ [a2]
-- -> listcond liststat --statements list
lAllaux l1 l2 = let
lenCond = length l1
in
[(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2, length [1|(a2,b2,c2,d2,f2)<-l1,(firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond]
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="If1" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond] ++
--c1>c2 && d1 <d2] /=0 ] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="If2" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond]++
--c1>c2 && d1 <d2] /=0 ] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="Ifone" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="Try" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="Tryfinally" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="Catch1" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1,a2=="Catch2" && (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) ==(-1))] == lenCond]
--c1>c2 && d1 <d2] /=0 ] ++
-- [(a1,b1,c1,d1,f1)|(a1,b1,c1,d1,f1)<-l2,length [1|(a2,b2,c2,d2,f2)<-l1, (firstTerm (a1,b1,c1,d1,f1) (a2,b2,c2,d2,f2) /=(-1))] == length l1]
--not (c1>c2 && d1 <d2)] == length l1 ]
--condList :: [(String,[[String]],Int,Int,[(Int,Int)])] -> [([(String,[[String]],Int,Int,[(Int,Int)])], [(String,[[String]],Int,Int,[(Int,Int)])])]
-- devolve lista de pares, cada par composto por lista cond e lista statement
condList [] = []
condList l = let lCond = [(a,b,c,d,l)|(a,b,c,d,l)<-l,a=="If1"||a=="If2"||a=="Ifone"]
lStat = [(a,b,c,d,l)|(a,b,c,d,l)<-l,a/="If1"&&a/="If2"&&a/="Ifone"]
-- lOrdIfs = nub $ ordIfs lCond lCond
lOrdIfs = nub $ ordifaux lCond []
lOrdList = ordList lOrdIfs
lAll = if (lOrdList /= []) then [(e,lAllaux e lStat)| e <- lOrdList] -- lista pares condList statList
else [([],lAllaux [] lStat)]
-- ordCond = orderCond lCond
-- res = orderList ordCond lStat
in lAll
actionsC [] = []
actionsC ((a,[]):t) = (a,[],[]):(actionsC t)
actionsC ((a,b):t) = actC a b ++ actionsC t
actC a [] = []
actC a ((c,d):t) = (a,c,d):(actC a t)
g :: String -> Int
g s = read s
--condList :: [(String,[[String]],Int,Int,[(Int,Int)])] -> [([(String,[[String]],Int,Int,[(Int,Int)])], [(String,[[String]],Int,Int,[(Int,Int)])])]
-- devolve lista de pares, cada par composto por lista cond e lista statement
condList_ [] = []
condList_ l = let lCond = [(a,b,c,d,l)|(a,b,c,d,l)<-l,a=="HsIf1" || a== "HsIf2"] -- ||a=="If2"||a=="Ifone"||a=="Try"||a=="Tryfinally"||a=="Catch1"||a=="Catch2"]
lStat = [(a,b,c,d,l)|(a,b,c,d,l)<-l,a/="HsIf1" && a/= "HsIf2"] -- &&a/="If2"&&a/="Ifone"&&a/="Try"&&a/="Tryfinally"&&a/="Catch1"&&a/="Catch2"]
grupos = nub [fecho e lCond |e <- lCond] -- lista com lista de cond aninhadas
gruposatomicos = [g | g <- grupos, fechoatomico g]
gruposordenados = nub [ordenarfecho g [] | g <- gruposatomicos] -- lista de lista de cond ordenados
fechocondlist = nub $ concat [fechocond g [] | g <- gruposordenados]
statForaCond = [e | e<-lStat , [c| c<-lCond ,firstTerm e c == -1]==[]]
lAll = if (fechocondlist /= []) then [(e,nub $ (lAllaux e lStat)++statForaCond)| e <- fechocondlist] -- lista pares condList statList
else [([],nub $ (lAllaux [] lStat)++statForaCond)]
-- ordCond = orderCond lCond
-- res = orderList ordCond lStat
in lAll
--fecho :: a -> [a] -> [a]
fecho e [] = []
fecho e (h:t) | firstTerm e h == -2 = h:(fecho e t)
| firstTerm e h == -1 = h:(fecho e t)
| firstTerm e h == 0 = fecho e t
| firstTerm e h == 1 = fecho e t
| otherwise = []
fechoatomico [] = False
fechoatomico l = (length [1 | e1<-l, e2<-l, (firstTerm e1 e2 /= -1) && (firstTerm e1 e2 /= -2)]) == 0
ordenarfecho [] l = l
--ordenarfecho (h:t) [] = [h]
ordenarfecho (h:t) l = let res = ordenarfechoaux h l
in ordenarfecho t res
ordenarfechoaux h [] = [h]
ordenarfechoaux h (a:b) | firstTerm h a == -2 = (h:(a:b))
| firstTerm h a == -1 = let res = ordenarfechoaux h b
in a:res
| otherwise = (h:(a:b))
fechocond [] l = []
fechocond [h] l = [l++[h]]
fechocond (h:t:s) l | firstTerm h t == -2 = (fechocond (t:s) (l++[h])) -- [l++[h]]++(fechocond (t:s) (l++[h]))
| otherwise = [l++[h]] ++ (fechocond (t:s) l)
listexp [] = []
listexp ((s,c,l):t) = l++(listexp t)
enumlistexp [] _ = []
enumlistexp (h:t) n = (n,h):(enumlistexp t (n+1))
listexpid [] _ = []
listexpid ((s,c,l):t) le = ((s,c, subexp l le):(listexpid t le))
subexp [] _ = []
subexp (h:t) le = (expid h le):(subexp t le)
expid h [] = error "função expid"
expid h ((n,h1):t) | (h==h1) = n
| otherwise = expid h t
formatList [] = "\t[\n" ++ "\t]\n"
formatList l = "\t[\n" ++ (formatListAux l) ++ "\t]\n"
formatListAux [] = ""
formatListAux [h] = "\t" ++ (show h) ++ "\n"
formatListAux (h:t) = "\t" ++ (show h) ++ ",\n" ++ formatListAux t
--mapactionsAll [] = empty
--mapactionsAll ((a,b,c):t) = Data.Map.insert a (b,c) (mapactionsAll t)
-- Graph eventsFromInitState.gui initState.gui 3
main :: IO ()
main =
do args <- getArgs
eventsString <- runFile (args!!0)--fs
let eventsData = [(a,b)|(a,b) <- ff eventsString]-- , b/=[]]
writeFile "actionsNew2" (show eventsData)
let (actionsNew,eventsNew) = splitEvents eventsData 1
let eventsId = fromList [(a,[e | e <-(c!!1)!!28, e /= '"', e/= '\\']) |(a,(b,c,d,e,f)) <- eventsNew]
let actions = [(eventsId ! a,b) | (a,b)<-actionsNew]
writeFile "eventsId" (show eventsId)
writeFile "eventsNew" (show eventsNew)
writeFile "actionsNew1" (show actionsNew)
let events = [(eventsId ! a,b) | (a,b)<-eventsNew]
writeFile "events.txt" (show events)
-- writeFile "eventsId.txt" (show eventsId)
writeFile "actionsAux.txt" (show actions)
let actionsX = [(a, condList_ b) | (a,b) <-actions]
writeFile "actX.txt" (show actionsX)
let act = actionsC actionsX -- [(evento, condiçoes, acções)]
let (actX,cond) = splitCond act 1
writeFile "conds.txt" (show cond)
writeFile "actions.txt" (show actX)
let behav = actX
initString <- runFile (args!!1)--fs
let initData = [("init",fff initString)]-- , b/=[]]
let initactionsX =[(a,condList_ b)|(a,b)<-initData]
let initact = actionsC initactionsX
let (initactX,initcond) = splitCondInit initact 1
writeFile "condsInit.txt" (show initcond)
let initbehav = initactX
writeFile "actionsInit.txt" (show initbehav)
let actionsAll_ = actX ++ initbehav
let listexp_ = nub $ listexp actionsAll_
let actionsEnum = enumlistexp listexp_ 1
writeFile "actionsEnum.txt" (show actionsEnum)
let actionsAllAux = listexpid actionsAll_ actionsEnum
let actionsAll = [((a,b),c)|(a,b,c)<-actionsAllAux]
writeFile "actionsAll.txt" (show actionsAll)
pres <- actionsAnalyse
pres1 <- actionsAnalyse1
let filterS = splitString (args!!3)
pres2 <- actionsAnalyse3 filterS
pres4 <- actionsAnalyse4
let modelDialogue = "--Generated automatically by GuiSurfer\n\n" ++
"module GuiModel where\n\n"++
"import Data.Map\n\n" ++
"type EventRef = String\n" ++
"type CondRef = String\n" ++
"type WindowName = String\n" ++
"type ExpRef = Int\n\n" ++
"type GuiModel = Map (EventRef,CondRef) [ExpRef]\n\n" ++
"type Pres = Map ExpRef (EventRef,Bool)\n" ++
"type End = [ExpRef]\n" ++
"type Close = [ExpRef]\n" ++
"type NewWindow = Map ExpRef WindowName\n\n" ++
"guimodel :: GuiModel\n" ++
"guimodel = fromList\n" ++ (formatList actionsAll) ++ "\n" ++
-- "-- Please insert pre-conditions here:\n" ++
"pres :: Pres\n" ++
-- "pres = fromList\n" ++ "\t[\n\t]\n" ++ "\n" ++
"pres = fromList\n" ++ (formatList pres) ++ "\n\n" ++
-- "-- Please insert exit events here:\n" ++
"end :: End\n" ++
"end = \n" ++ "\t" ++ (show pres1) ++ "\n" ++ "\n" ++
"newWindow :: NewWindow\n" ++
"newWindow = fromList\n"
-- ++ "\t[]"
++ (formatList pres2)
++ "\n" ++ "\n" ++
"close :: Close\n" ++
"close = \n" ++ "\t" ++ (show pres4) ++ "\n" ++ "\n"
let modelfull = "--Generated automatically by GuiSurfer\n\n" ++
"module GuiModelFull where\n\n"++
"import Data.Map\n" ++
"import GuiModel\n\n" ++
"type Type = String\n" ++
"type AstList = [[String]]\n" ++
"type InitPos = Int\n" ++
"type EndPos = Int\n" ++
"type SourcePosList = [(InitPos,EndPos)]\n" ++
"type Exp = (Type,AstList,InitPos,EndPos,SourcePosList)\n\n" ++
"type Exps = Map ExpRef Exp\n"++
"type Events = Map EventRef Exp\n" ++
"type Conds = Map CondRef [Exp]\n\n" ++
{--
"validEvents :: [ExpRef] -> Pres -> [EventRef]\n" ++
"validEvents l p = keys ( Data.Map.filter (\\v -> v==True) (validEventAux l p (Data.Map.map (\\e -> True) events)))\n\n" ++
"validEventAux :: [ExpRef] -> Pres -> Map EventRef Bool -> Map EventRef Bool\n" ++
"validEventAux [] p validevents = validevents\n" ++
"validEventAux (h:t) p validevents | member h p = let res = p ! h in validEventAux t pres (Data.Map.insert (fst res) (snd res) validevents)\n" ++
" | otherwise = validEventAux t pres validevents\n\n" ++
"ways :: GuiModel -> Int -> [([CondRef],[EventRef])]\n" ++
"ways gui n = waysAux gui n [\"init\"] [] [] [] end\n\n" ++
"waysAux :: GuiModel -> Int -> [EventRef] -> [EventRef] -> [CondRef] -> [ExpRef] -> End -> [([CondRef],[EventRef])]\n" ++
"waysAux _ 0 _ _ _ _ _ = []\n" ++
"waysAux gui n lEventRef1 lEventRef lCondRef lExpRef endlist =\n" ++
" concat [let lCondRefExpRef = toList (mapKeys (\\k -> [snd k]) (filterWithKey (\\k v -> fst k == e) gui))\n" ++
" lCondRefEventRef1 = [(lCondRef++lc,lEventRef++[e]) | (lc,le) <- lCondRefExpRef]\n" ++
" lCondRefEventRef2 = if (not (elem e endlist)) then\n" ++
" concat [let ve = validEvents (lExpRef++le) pres in waysAux gui (n-1) ve (lEventRef++[e]) (lCondRef++lc) (lExpRef++le) endlist\n" ++
" | (lc,le) <- lCondRefExpRef\n" ++
" ]\n" ++
" else []\n" ++
" in lCondRefEventRef1 ++ lCondRefEventRef2\n" ++
" | e <- lEventRef1\n" ++
" ]\n\n" ++
--}
"exps :: Exps\n" ++
"exps = fromList\n" ++ (formatList actionsEnum) ++ "\n" ++
"events :: Events\n" ++
"events = fromList\n" ++ (formatList events) ++ "\n" ++
"conds :: Conds\n" ++
"conds = fromList\n" ++ (formatList (cond++initcond)) ++ "\n"
writeFile "GuiModel.hs" (modelDialogue)
writeFile "GuiModelFull.hs" (modelfull)
-- let behavAll = behav ++ initbehav
-- writeFile "behavAll.txt" (show behavAll)
-- let behavC = [let l = [(d,e)|(d,e,f,g,h) <-c] in (a,b,l) |(a,b,c)<-behavAll]
-- writeFile "behavC.txt" (show behavC)
-- let laux = nub [c|(a,b,c)<-behavC]
-- let statesSet = labelsAux laux 1
-- writeFile "statesSet.txt" (show statesSet)
-- let behavA = [(e,d,a)|(e,d,f)<-behavC,(a,b)<-statesSet, b==f]
-- writeFile "behavA.txt" (show behavA)
-- let grp = nub $ grX behavA (g(args!!2))
-- let grpX = [(if a == [] then "empty" else consS a,b,c,if d == [] then "empty" else consS d)|(a,b,c,d)<-grp]
-- writeFile "grpX.txt" (show grpX)
-- let nodes = nub $ concat [[a]++[d]|(a,b,c,d)<-grpX]
-- writeFile "nodes.txt" (show nodes)
-- let graph = grF nodes grpX
-- writeFile "graph.dot" graph
-- writeFile "teste1.lixo" (show ast)
-- writeFile "teste.lixo" (show $ slice ast "Ident" 1 1)
-- writeFile "res5.lixo" (show $ mainMethod ast)
-- writeFile "init.gui" (show $ initState ast "main" ["setEnabled"])
-- writeFile "events.gui" (show $ eventsFromInitState ast "main" ["setEnabled"])
-- otherwise -> error ""
consS [] = ""
consS [h] = h
consS (h:t) = h++""++(consS t)
labelsAux [] _ = []
--labelsAux [h] n = [("state"++show n,h)]
labelsAux (h:t) n = ("State"++show n,h):(labelsAux t (n+1))
grF nodes grpX = "digraph gr { rankdir = LR;\n"++
concat [
e++
" [shape=box , label=\"" ++
e ++
"\" ,color=black];" ++
"\n"
|e<-nodes] ++
concat [a ++" -> " ++ d ++ " [label= \""++ b ++ "/" ++ c ++"\"];\n"|(a,b,c,d)<-grpX] ++
"}"
grX l n = let l1 = addg l
l2 = adf l1 n
in l2
addg l = [(a,b,[c])|(a,b,c)<-l]
adf :: [(String,String,[String])] -> Int -> [([String],String,String,[String])]
adf l n = let linit = [([],a,b,c)|(a,b,c)<-l,a=="init"]
lall = linit ++ (adfAll linit l n)
in lall
adfAll _ _ 0 = []
adfAll l1 l2 n = let res = [(d,a1,b1,nub $ d++c1)|(a,b,c,d)<-l1,(a1,b1,c1)<-l2,a1/="init"]
in res ++ (adfAll res l2) (n-1)
|