module Data.Cfg.Augment (
augmentCfg,
AugNT(..),
AugT(..),
AugV,
AugVs,
AugProduction,
AugFreeCfg
) where
import Data.Cfg.Cfg(Cfg(..), Production, V(..), Vs)
import Data.Cfg.FreeCfg(FreeCfg(..))
import qualified Data.Set as S
data AugNT nt = StartSymbol | AugNT nt
deriving (Eq, Ord, Show)
data AugT t = EOF | AugT t
deriving (Eq, Ord, Show)
type AugV t nt = V (AugT t) (AugNT nt)
type AugVs t nt = Vs (AugT t) (AugNT nt)
type AugProduction t nt = Production (AugT t) (AugNT nt)
type AugFreeCfg t nt = FreeCfg (AugT t) (AugNT nt)
augmentCfg :: forall cfg t nt . (Cfg cfg t nt, Ord nt, Ord t)
=> cfg t nt -> FreeCfg (AugT t) (AugNT nt)
augmentCfg cfg = FreeCfg {
nonterminals' = S.insert StartSymbol $ S.map AugNT $ nonterminals cfg,
terminals' = S.insert EOF $ S.map AugT $ terminals cfg,
productionRules' = pr,
startSymbol' = StartSymbol
}
where
pr :: AugNT nt -> S.Set (Vs (AugT t) (AugNT nt))
pr StartSymbol = S.singleton [NT $ AugNT $ startSymbol cfg, T EOF]
pr (AugNT nt) = S.map augmentVs oldRhss
where
oldRhss :: S.Set (Vs t nt)
oldRhss = productionRules cfg nt
augmentVs :: Vs t nt -> Vs (AugT t) (AugNT nt)
augmentVs = map augmentV
augmentV :: V t nt -> V (AugT t) (AugNT nt)
augmentV (NT nt') = NT $ AugNT nt'
augmentV (T t') = T $ AugT t'