module Data.Cfg.RuleApplication(
language,
yields,
directlyYields
) where
import Control.Monad(liftM, msum)
import Control.Monad.Omega
import Data.Cfg.Cfg
import qualified Data.DList as DL
import qualified Data.Map as M
import qualified Data.Set as S
directlyYields :: (Cfg cfg t nt) => cfg t nt -> Vs t nt -> [Vs t nt]
directlyYields cfg vs = do
i <- [0..length vs 1]
let (pre, NT nt : post) = splitAt i vs
expansion <- S.toList $ productionRules cfg nt
return (pre ++ expansion ++ post)
yields :: forall cfg t nt . (Cfg cfg t nt, Ord nt)
=> cfg t nt -> [Vs t nt]
yields cfg = map DL.toList $ runOmega $ yieldNT (startSymbol cfg)
where
yieldNT :: nt -> Omega (DL.DList (V t nt))
yieldNT nt = memoMap M.! nt
where
memoMap :: M.Map nt (Omega (DL.DList (V t nt)))
memoMap = M.fromList
[(nt', yieldNT' nt')
| nt' <- S.toList $ nonterminals cfg]
yieldNT' :: nt -> Omega (DL.DList (V t nt))
yieldNT' nt' = msum (return (DL.singleton (NT nt'))
: map yieldVs rhss)
where
rhss = S.toList $ productionRules cfg nt'
yieldV :: V t nt -> Omega (DL.DList (V t nt))
yieldV v = case v of
NT nt -> yieldNT nt
t -> return $ DL.singleton t
yieldVs :: Vs t nt -> Omega (DL.DList (V t nt))
yieldVs = liftM DL.concat . mapM yieldV
language :: (Cfg cfg t nt, Ord nt) => cfg t nt -> [Vs t nt]
language = filter (all isT) . yields