{-# OPTIONS_HADDOCK hide #-}
module WriteDotGraph (renderDotGraph, writeDotFile) where
import Data.Tree
labelTree :: Tree a -> Int -> (Tree (Int,a), Int)
labelTree (Node l ts) n = (Node (n,l) ts', n')
where
(ts', n') = labelForest ts [] (n+1)
labelForest [] nts n = (reverse nts, n)
labelForest (t:ts) nts n = let (nt, n') = labelTree t n
in labelForest ts (nt:nts) n'
treeToGraph :: Tree (Int, String) -> ([(Int, String)], [(Int, Int)])
treeToGraph (Node (n, label) ts) =
let node = (n, label)
edges = [ (n, n') | Node (n', _) _ <- ts ]
(nodes', edges') = unzip (map treeToGraph ts)
in (node:concat nodes', edges++concat edges')
writeDotFile :: FilePath -> Tree String -> IO ()
writeDotFile file tree = writeFile file (renderDotGraph tree)
renderDotGraph :: Tree String -> String
renderDotGraph tree =
unlines (
[header
,graphDefaultAtribs
,nodeDefaultAtribs
,edgeDefaultAtribs]
++ map makeNode nodes
++ map makeEdge edges
++ [footer]
)
where
(nodes, edges) = treeToGraph (fst $ labelTree tree 0)
makeNode (n,l) = "\t" ++ show n ++ " [label=\"" ++ escape l ++ "\"];"
makeEdge (n, n') = "\t" ++ show n ++ " -> " ++ show n' ++ "[];"
escape [] = []
escape ('\n':cs) = "\\n" ++ escape cs
escape ('"' :cs) = "\\\"" ++ escape cs
escape (c :cs) = c : escape cs
header = "digraph contract {"
footer = "}"
graphDefaultAtribs = "\tgraph [fontsize=14, fontcolor=black, color=black];"
nodeDefaultAtribs = "\tnode [label=\"\\N\", width=\"0.75\", shape=ellipse];"
edgeDefaultAtribs = "\tedge [fontsize=10];"