{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Data.CfgTests (sampleCfg, tests) where import Control.Monad(forM) import Data.Char(toLower, toUpper) import qualified Data.Cfg.BnfTests import Data.Cfg.Cfg(V(..)) import Data.Cfg.CPretty(cpretty) import Data.Cfg.FreeCfg import qualified Data.Cfg.FirstSetTests import qualified Data.Cfg.FollowSetTests import qualified Data.Cfg.LookaheadSetTests import qualified Data.Cfg.ProductiveTests import qualified Data.Cfg.ReachableTests import qualified Data.Map as M import qualified Data.Set as S import Test.Framework(Test, testGroup) import Test.QuickCheck import Text.PrettyPrint instance Arbitrary (FreeCfg Int Int) where arbitrary = do tCnt <- choose (1, 25) let ts = [0..tCnt-1] ntCnt <- choose (1, 100) let nts = [0..ntCnt-1] let vs = map T ts ++ map NT nts let genV = elements vs let genVs = listOf genV pairs <- forM nts $ \nt -> do altCnt <- choose (1, 5) rhss <- vectorOf altCnt genVs return (nt, S.fromList rhss) let map' = M.fromList pairs return FreeCfg { nonterminals' = S.fromList nts, terminals' = S.fromList ts, productionRules' = (map' M.!), startSymbol' = 0 } ctxt :: V Int Int -> Doc ctxt v = text $ map f $ base26 n where (f, n) = case v of NT n' -> (toLower, n') T n' -> (toUpper, n') base26 :: Int -> String base26 n' | n' < 26 = [digitToChar n'] | otherwise = if msds == 0 then [digitToChar lsd] else base26 msds ++ [digitToChar lsd] where (msds, lsd) = n' `divMod` 26 digitToChar :: Int -> Char digitToChar digit = toEnum (fromEnum 'a' + digit) pretty :: FreeCfg Int Int -> Doc pretty cfg = cpretty cfg ctxt sampleCfg :: IO () sampleCfg = do cfgs <- sample' (arbitrary :: Gen (FreeCfg Int Int)) mapM_ (print . pretty) (take 3 cfgs) tests :: Test tests = testGroup "Data.Cfg" [ Data.Cfg.BnfTests.tests, Data.Cfg.FirstSetTests.tests, Data.Cfg.FollowSetTests.tests, Data.Cfg.LookaheadSetTests.tests, Data.Cfg.ProductiveTests.tests, Data.Cfg.ReachableTests.tests ]