---------------------------------------------------------------------- -- | -- Module : MkGFC -- Maintainer : AR -- Stability : (stable) -- Portability : (portable) -- -- > CVS $Date: 2005/09/04 11:45:38 $ -- > CVS $Author: aarne $ -- > CVS $Revision: 1.16 $ -- -- (Description of the module) ----------------------------------------------------------------------------- module GF.Canon.MkGFC (prCanonModInfo, prCanon, prCanonMGr, canon2grammar, grammar2canon, -- buildCanonGrammar, info2mod,info2def, trExp, rtExp, rtQIdent) where import GF.Canon.GFC import GF.Canon.AbsGFC import qualified GF.Grammar.Abstract as A import GF.Grammar.PrGrammar import GF.Infra.Ident import GF.Data.Operations import qualified GF.Infra.Modules as M prCanonModInfo :: CanonModule -> String prCanonModInfo = prt . info2mod prCanon :: CanonGrammar -> String prCanon = unlines . map prCanonModInfo . M.modules prCanonMGr :: CanonGrammar -> String prCanonMGr g = header ++++ prCanon g where header = case M.greatestAbstract g of Just a -> prt (MGr (M.allConcretes g a) a []) _ -> [] canon2grammar :: Canon -> CanonGrammar canon2grammar (MGr _ _ modules) = canon2grammar (Gr modules) ---- ignoring the header canon2grammar (Gr modules) = M.MGrammar $ map mod2info modules mod2info m = case m of Mod mt e os flags defs -> let defs' = buildTree $ map def2info defs (a,mt') = case mt of MTAbs a -> (a,M.MTAbstract) MTRes a -> (a,M.MTResource) MTCnc a x -> (a,M.MTConcrete x) MTTrans a x y -> (a,M.MTTransfer (M.oSimple x) (M.oSimple y)) in (a,M.ModMod (M.Module mt' M.MSComplete flags (ee e) (oo os) defs')) where ee (Ext m) = map M.inheritAll m ee _ = [] oo (Opens ms) = map M.oSimple ms oo _ = [] grammar2canon :: CanonGrammar -> Canon grammar2canon (M.MGrammar modules) = Gr $ map info2mod modules info2mod :: (Ident, M.ModInfo Ident Flag Info) -> Module info2mod m = case m of (a, M.ModMod (M.Module mt _ flags me os defs)) -> let defs' = map info2def $ tree2list defs mt' = case mt of M.MTAbstract -> MTAbs a M.MTResource -> MTRes a M.MTConcrete x -> MTCnc a x M.MTTransfer (M.OSimple _ x) (M.OSimple _ y) -> MTTrans a x y in Mod mt' (gfcE me) (gfcO os) flags defs' where gfcE = ifNull NoExt Ext . map fst gfcO os = if null os then NoOpens else Opens [m | M.OSimple _ m <- os] -- these translations are meant to be trivial defs2infos = sorted2tree . map def2info def2info d = case d of AbsDCat c cont fs -> (c,AbsCat (trCont cont) (trFs fs)) AbsDFun c ty df -> (c,AbsFun (trExp ty) (trExp df)) AbsDTrans c t -> (c,AbsTrans (trExp t)) ResDPar c df -> (c,ResPar df) ResDOper c ty df -> (c,ResOper ty df) CncDCat c ty df pr -> (c, CncCat ty df pr) CncDFun f c xs li pr -> (f, CncFun c xs li pr) AnyDInd c b m -> (c, AnyInd (b == Canon) m) -- from file to internal trCont cont = [(x,trExp t) | Decl x t <- cont] trFs = map trQIdent trExp :: Exp -> A.Term trExp t = case t of EProd x a b -> A.Prod x (trExp a) (trExp b) EAbs x b -> A.Abs x (trExp b) EApp f a -> A.App (trExp f) (trExp a) EEq eqs -> A.Eqs [(map trPt ps, trExp e) | Equ ps e <- eqs] EData -> A.EData _ -> trAt t where trAt (EAtom t) = case t of AC c -> (uncurry A.Q) $ trQIdent c AD c -> (uncurry A.QC) $ trQIdent c AV v -> A.Vr v AM i -> A.Meta $ A.MetaSymb $ fromInteger i AT s -> A.Sort $ prt s AS s -> A.K s AI i -> A.EInt $ i AF i -> A.EFloat $ i trPt p = case p of APC mc ps -> let (m,c) = trQIdent mc in A.PP m c (map trPt ps) APV x -> A.PV x APS s -> A.PString s API i -> A.PInt $ i APF i -> A.PFloat $ i APW -> A.PW trQIdent (CIQ m c) = (m,c) -- from internal to file infos2defs = map info2def . tree2list info2def d = case d of (c,AbsCat cont fs) -> AbsDCat c (rtCont cont) (rtFs fs) (c,AbsFun ty df) -> AbsDFun c (rtExp ty) (rtExp df) (c,AbsTrans t) -> AbsDTrans c (rtExp t) (c,ResPar df) -> ResDPar c df (c,ResOper ty df) -> ResDOper c ty df (c,CncCat ty df pr) -> CncDCat c ty df pr (f,CncFun c xs li pr) -> CncDFun f c xs li pr (c,AnyInd b m) -> AnyDInd c (if b then Canon else NonCan) m rtCont cont = [Decl (rtIdent x) (rtExp t) | (x,t) <- cont] rtFs = map rtQIdent rtExp :: A.Term -> Exp rtExp t = case t of A.Prod x a b -> EProd (rtIdent x) (rtExp a) (rtExp b) A.Abs x b -> EAbs (rtIdent x) (rtExp b) A.App f a -> EApp (rtExp f) (rtExp a) A.Eqs eqs -> EEq [Equ (map rtPt ps) (rtExp e) | (ps,e) <- eqs] A.EData -> EData _ -> EAtom $ rtAt t where rtAt t = case t of A.Q m c -> AC $ rtQIdent (m,c) A.QC m c -> AD $ rtQIdent (m,c) A.Vr v -> AV v A.Meta i -> AM $ toInteger $ A.metaSymbInt i A.Sort "Type" -> AT SType A.K s -> AS s A.EInt i -> AI $ toInteger i _ -> error $ "MkGFC.rt not defined for" +++ show t rtPt p = case p of A.PP m c ps -> APC (rtQIdent (m,c)) (map rtPt ps) A.PV x -> APV x A.PString s -> APS s A.PInt i -> API $ toInteger i A.PW -> APW _ -> error $ "MkGFC.rt not defined for" +++ show p rtQIdent :: (Ident, Ident) -> CIdent rtQIdent (m,c) = CIQ (rtIdent m) (rtIdent c) rtIdent x | isWildIdent x = identC "h_" --- needed in declarations | otherwise = identC $ prt x --- {- -- the following is called in GetGFC to read gfc files line -- by line. It does not save memory, though, and is therefore -- not used. buildCanonGrammar :: Int -> CanonGrammar -> Line -> (CanonGrammar,Int) buildCanonGrammar n gr0 line = mgr $ case line of -- LMulti ids id LHeader mt ext op -> newModule mt ext op LFlag f@(Flg (IC "modulesize") (IC n)) -> initModule f $ read $ tail n LFlag flag -> newFlag flag LDef def -> newDef $ def2info def -- LEnd -> cleanNames _ -> M.modules gr0 where newModule mt ext op = mod2info (Mod mt ext op [] []) : mods initModule f i = case actm of (name, M.ModMod (M.Module mt com flags ee oo defs)) -> (name, M.ModMod (M.Module mt com (f:flags) ee oo (newtree i))) : tmods newFlag f = case actm of (name, M.ModMod (M.Module mt com flags ee oo defs)) -> (name, M.ModMod (M.Module mt com (f:flags) ee oo defs)) : tmods newDef d = case actm of (name, M.ModMod (M.Module mt com flags ee oo defs)) -> (name, M.ModMod (M.Module mt com flags ee oo (upd (padd 8 n) d defs))) : tmods -- cleanNames = case actm of -- (name, M.ModMod (M.Module mt com flags ee oo defs)) -> -- (name, M.ModMod (M.Module mt com (reverse flags) ee oo -- (mapTree (\ (IC f,t) -> (IC (drop 8 f),t)) defs))) : tmods actm = head mods -- only used when a new mod has been created mods = M.modules gr0 tmods = tail mods mgr ms = (M.MGrammar ms, case line of LDef _ -> n+1 LEnd -> 1 _ -> n ) -- create an initial tree with who-cares value newtree (i :: Int) = emptyBinTree -- newtree (i :: Int) = sorted2tree [ -- (padd 8 k, ResPar []) | -- k <- [1..i]] --- padd (length (show i)) padd l k = 0 -- padd l k = let sk = show k in identC (replicate (l - length sk) '0' ++ sk) upd _ d defs = updateTree d defs -- upd n d@(f,t) defs = case defs of -- NT -> BT (merg n f,t) NT NT --- should not happen -- BT c@(a,_) left right -- | n < a -> let left' = upd n d left in BT c left' right -- | n > a -> let right' = upd n d right in BT c left right' -- | otherwise -> BT (merg n f,t) left right -- merg (IC n) (IC f) = IC (n ++ f) -}