1 {-# LANGUAGE TypeFamilies #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 module Language.Symantic.RNC.Write.Namespaces where
5 import Control.Applicative (Applicative(..), Alternative(..), (<$>))
6 import Control.Monad (Monad(..), forM, sequence)
7 import Data.Default.Class (Default(..))
8 import Data.Function (($), (.), id)
9 import Data.Functor (Functor(..))
10 import Data.Maybe (Maybe(..), maybe, isNothing)
11 import Data.Monoid (Monoid(..))
12 import Data.Semigroup (Semigroup(..))
13 import Text.Show (Show(..))
14 import Data.String (String)
15 import qualified Data.HashMap.Strict as HM
16 import qualified Data.HashSet as HS
17 import qualified Control.Monad.Trans.State.Strict as S
19 import qualified Language.Symantic.XML as XML
20 import Language.Symantic.RNC.Sym
22 -- | Collect 'XML.Namespace's used and get them a dedicated prefix.
23 runNS :: forall a. [NS a] -> XML.Namespaces XML.NCName
26 { XML.namespaces_prefixes =
27 (`S.evalState` HS.empty) $
28 let prefixesByNamespace =
29 HM.delete "" $ -- NOTE: no prefix when there is no namespace.
30 HM.update -- NOTE: no prefix when this is the default namespace.
31 (\p -> if isNothing p then Nothing else Just p)
32 (XML.namespaces_default namespaces) $
33 XML.namespaces_prefixes namespaces in
34 forM prefixesByNamespace $ \mp -> do
37 (XML.freshNCName usedPrefixes)
38 (XML.freshifyNCName usedPrefixes)
40 S.modify' $ HS.insert fp
44 namespaces :: XML.Namespaces (Maybe XML.NCName)
45 namespaces = mconcat $ (`S.evalState` def) $ sequence $ unNS <$> ns
47 coerceNS :: NS a -> NS b
49 {-# INLINE coerceNS #-}
52 -- | Collect 'XML.Namespaces's and any prefixes associated with it,
53 -- using 'State' to avoid recurring into already visited 'rule's.
54 newtype NS a = NS { unNS :: S.State State (XML.Namespaces (Maybe XML.NCName)) }
58 { state_rules :: {-!-}(HS.HashSet String)
60 instance Default State where
62 { state_rules = HS.empty
65 instance Show (NS a) where
66 showsPrec p = showsPrec p . runNS . pure
67 instance Semigroup (NS a) where
68 NS x <> NS y = NS $ (<>) <$> x <*> y
69 instance Monoid (NS a) where
70 mempty = NS $ return mempty
72 instance Functor NS where
74 instance Applicative NS where
76 NS f <*> NS x = NS f <> NS x
77 NS f <* NS x = NS f <> NS x
78 NS f *> NS x = NS f <> NS x
79 instance Alternative NS where
81 NS f <|> NS x = NS f <> NS x
84 instance Sym_Rule NS where
85 rule n (NS ns) = NS $ do
86 -- NOTE: avoid infinite loops
87 -- by not reentering into already visited rules.
89 if HS.member n state_rules
92 S.put $ st{state_rules = HS.insert n state_rules}
95 type instance Perm NS = NS
96 instance Sym_Interleaved NS where
97 interleaved = coerceNS
99 _f <$?> (_, NS x) = NS x
102 NS f <||> NS x = NS f <> NS x
103 NS f <|?> (_, NS x) = NS f <> NS x
104 NS f <|*> NS x = NS f <> NS x
105 instance Sym_RNC NS where
107 -- NS $ return $ HM.singleton ns $ HS.singleton n
111 Just p -> XML.Namespaces{XML.namespaces_prefixes = HM.singleton n $ Just p, XML.namespaces_default = ""}
112 Nothing -> def{XML.namespaces_default = n}
113 element XML.QName{..} (NS nsM) =
114 NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =
115 HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}
116 attribute XML.QName{..} (NS nsM) =
117 NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =
118 HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}
119 anyElem qNameSpace f =
120 let NS nsM = f $ XML.NCName "*" in
121 NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =
122 HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}
129 option _def = coerceNS