packages feed

uuagc-0.9.38.4: src/KennedyWarren.hs

module KennedyWarren where

import CommonTypes
import Pretty
import Knuth1
import Debug.Trace
import Control.Monad.ST
import Control.Monad.State
import Control.Monad.Error
import Data.STRef
import Data.Maybe
import Data.List

import qualified Data.Set as Set
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet

kennedyWarrenIO :: [NontDependencyInformation] -> PP_Doc
kennedyWarrenIO ndis = runST $ do 
  indi <- mapM mkNontDependencyInformationM ndis
  knuth1 indi
  -- Check all graphs for cyclicity, transitive closure and consistency
  traceST $ "Checking graphs..."
  forM_ indi $ \ndi -> do
    let nont = ndiNonterminal . ndimOrig $ ndi
    let g = ndgmDepGraph . ndimDepGraph $ ndi
    -- Cyclicity check
    c1 <- graphIsCyclic g
    when c1 $ traceST $ "Nonterminal graph " ++ show nont ++ " is cylic!"
    -- Transtive closure check
    trc <- graphIsTRC g
    when (not trc) $ traceST $ "Nonterminal graph " ++ show nont ++ " is not transitively closed!"
    -- Consistency check
    cons <- graphCheckConsistency g
    when (not cons) $ traceST $ "Nonterminal graph " ++ show nont ++ " is not consistent!"
    -- Loop trough all productions
    forM_ (ndimProds ndi) $ \prod -> do
      let pr = pdgProduction $ pdgmOrig prod
      let g = pdgmDepGraph $ prod
      -- Check for cyclicity
      c2 <- graphIsCyclic g 
      when c2 $ traceST $ "Production graph " ++ show pr ++ " of nonterminal "
                          ++ show nont ++ " is cylic!"
      -- Transtive closure check
      trc <- graphIsTRC g
      when (not trc) $ traceST $ "Production graph " ++ show pr ++ " of nonterminal " 
                                 ++ show nont ++ " is not transitively closed!"
      -- Check consistency
      cons <- graphCheckConsistency g
      when (not cons) $ traceST $ "Production graph " ++ show pr ++ " of nonterminal " 
                                 ++ show nont ++ " is not consistent!"
  -- Recreate non-transitive closed graph for efficiency
  indi <- undoTransitiveClosure indi
  -- Debug output
  traceST $ "Converting to string..."
  rtexts <- mapM toGVNontDependencyInfo indi
  traceST $ "Done."
  return (vlist rtexts)

-------------------------------------------------------------------------------
--         Debugging functionality
-------------------------------------------------------------------------------

-- | Pretty print a vertex in GraphViz format
toGVVertex :: Bool -> Vertex -> ST s PP_Doc
toGVVertex l (VAttr t a b) = return $ (text $ "attr_" ++ show t ++ "_" ++ show a ++ "_" ++ show b) >#< if l
	     	      	   	then text ("[shape=box,label=\"" ++ show t ++ " @" ++ show a ++ "." ++ show b ++ "\"]") else empty
toGVVertex l (VChild c)    = return $ (text $ "child_" ++ show c) >#< if l
	     	      	   	then text ("[shape=ellipse,label=\"Child " ++ show c ++ "\"]") else empty
toGVVertex l (VRule r)   = return $ (text $ "rule_"  ++ show r) >#< if l
	     	      	   	then text ("[shape=diamond,label=\"" ++ show r ++ "\"]") else empty

-- | Pretty print an edge in GraphViz format
toGVEdge :: Edge -> ST s PP_Doc
toGVEdge (v1, v2) = do r1 <- toGVVertex False v1 
                       r2 <- toGVVertex False v2
                       return $ r1 >|< text "->" >#< r2

-- | Pretty print a NontDependencyInformation in GraphViz format
toGVNontDependencyInfo :: NontDependencyInformationM s -> ST s PP_Doc
toGVNontDependencyInfo ndi = do dg <- return $ ndgmDepGraph . ndimDepGraph $ ndi
                                verts <- graphVertices dg
                                edges <- graphEdges dg
                                vtexts <- mapM (toGVVertex True) verts
                                etexts <- mapM toGVEdge edges
                                ptexts <- mapM toGVProdDependencyGraph (ndimProds ndi)
                                return $ (text ("digraph ndg_" ++ show (ndiNonterminal $ ndimOrig ndi) ++ " {")
                                          >-<
                                          vlist vtexts
                                          >-<
                                          vlist etexts
                                          >-<
                                          text "}"
                                          >-<
                                          text "" -- empty line
                                          >-<
                                          vlist ptexts)

-- | Pretty print a ProdDependencyGraph in GraphViz format
toGVProdDependencyGraph :: ProdDependencyGraphM s -> ST s PP_Doc
toGVProdDependencyGraph pdg = do dg <- return $ pdgmDepGraph pdg
                                 verts <- graphVertices dg
                                 edges <- graphEdges dg
                                 vtexts <- mapM (toGVVertex True) verts
                                 etexts <- mapM toGVEdge edges
                                 return $ (text ("digraph pdg_" ++ show (pdgProduction $ pdgmOrig pdg) ++ " {")
                                           >-<
                                           (vlist vtexts)
                                           >-<
                                           (vlist etexts)
                                           >-<
                                           text ("info [shape=box,label=\"" ++ show (pdgChildMap $ pdgmOrig pdg) ++ "\"];")
                                           >-<
                                           text "}"
                                           >-<
                                           text "")