packages feed

symantic-xml 1.0.0.20190223 → 2.0.0.20200523

raw patch · 34 files changed

+3704/−2706 lines, 34 filesdep +symantic-basedep −data-default-classdep −filepathdep −safedep ~megaparsecPVP ok

version bump matches the API change (PVP)

Dependencies added: symantic-base

Dependencies removed: data-default-class, filepath, safe

Dependency ranges changed: megaparsec

API changes (from Hackage documentation)

- Symantic.RNC: (*>) :: Applicative f => f a -> f b -> f b
- Symantic.RNC: (<$) :: Functor f => a -> f b -> f a
- Symantic.RNC: (<*) :: Applicative f => f a -> f b -> f a
- Symantic.RNC: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
- Symantic.RNC: (<|>) :: Alternative f => f a -> f a -> f a
- Symantic.RNC: class Applicative f => Alternative (f :: Type -> Type)
- Symantic.RNC: class Functor f => Applicative (f :: Type -> Type)
- Symantic.RNC: class Functor (f :: Type -> Type)
- Symantic.RNC: fmap :: Functor f => (a -> b) -> f a -> f b
- Symantic.RNC: infixl 3 <|>
- Symantic.RNC: infixl 4 <*
- Symantic.RNC: liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
- Symantic.RNC: pure :: Applicative f => a -> f a
- Symantic.RNC.Sym: (*>) :: Applicative f => f a -> f b -> f b
- Symantic.RNC.Sym: (<$$>) :: Sym_Permutation repr => (a -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: (<$) :: Functor f => a -> f b -> f a
- Symantic.RNC.Sym: (<$*>) :: Sym_Permutation repr => ([a] -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: (<$:>) :: Sym_Permutation repr => (Seq a -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: (<$>) :: Functor f => (a -> b) -> f a -> f b
- Symantic.RNC.Sym: (<$?>) :: Sym_Permutation repr => (a -> b) -> (a, repr a) -> Permutation repr b
- Symantic.RNC.Sym: (<*) :: Applicative f => f a -> f b -> f a
- Symantic.RNC.Sym: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
- Symantic.RNC.Sym: (<|*>) :: Sym_Permutation repr => Permutation repr ([a] -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: (<|:>) :: Sym_Permutation repr => Permutation repr (Seq a -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: (<|>) :: Alternative f => f a -> f a -> f a
- Symantic.RNC.Sym: (<|?>) :: Sym_Permutation repr => Permutation repr (a -> b) -> (a, repr a) -> Permutation repr b
- Symantic.RNC.Sym: (<||>) :: Sym_Permutation repr => Permutation repr (a -> b) -> repr a -> Permutation repr b
- Symantic.RNC.Sym: RuleMode_Body :: RuleMode
- Symantic.RNC.Sym: RuleMode_Def :: RuleMode
- Symantic.RNC.Sym: RuleMode_Ref :: RuleMode
- Symantic.RNC.Sym: any :: Sym_RNC repr => repr ()
- Symantic.RNC.Sym: anyElem :: Sym_RNC repr => Namespace -> (NCName -> repr a) -> repr a
- Symantic.RNC.Sym: arg :: Sym_Rule repr => String -> repr ()
- Symantic.RNC.Sym: attribute :: Sym_RNC repr => QName -> repr a -> repr a
- Symantic.RNC.Sym: choice :: Sym_RNC repr => [repr a] -> repr a
- Symantic.RNC.Sym: class Applicative f => Alternative (f :: Type -> Type)
- Symantic.RNC.Sym: class Functor f => Applicative (f :: Type -> Type)
- Symantic.RNC.Sym: class Functor (f :: Type -> Type)
- Symantic.RNC.Sym: class (Alternative repr, Applicative (Permutation repr)) => Sym_Permutation repr
- Symantic.RNC.Sym: class (Applicative repr, Alternative repr, Sym_Rule repr, Sym_Permutation repr) => Sym_RNC repr
- Symantic.RNC.Sym: class Sym_Rule repr
- Symantic.RNC.Sym: data RuleMode
- Symantic.RNC.Sym: element :: Sym_RNC repr => QName -> repr a -> repr a
- Symantic.RNC.Sym: empty :: Alternative f => f a
- Symantic.RNC.Sym: escapedText :: Sym_RNC repr => repr EscapedText
- Symantic.RNC.Sym: fail :: Sym_RNC repr => repr a
- Symantic.RNC.Sym: fmap :: Functor f => (a -> b) -> f a -> f b
- Symantic.RNC.Sym: infixl 1 <|:>
- Symantic.RNC.Sym: infixl 2 <$:>
- Symantic.RNC.Sym: infixl 3 <|>
- Symantic.RNC.Sym: infixl 4 <*
- Symantic.RNC.Sym: instance GHC.Classes.Eq Symantic.RNC.Sym.RuleMode
- Symantic.RNC.Sym: instance GHC.Show.Show Symantic.RNC.Sym.RuleMode
- Symantic.RNC.Sym: intermany :: Sym_RNC repr => [repr a] -> repr [a]
- Symantic.RNC.Sym: liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
- Symantic.RNC.Sym: many :: Alternative f => f a -> f [a]
- Symantic.RNC.Sym: manySeq :: Sym_RNC repr => repr a -> repr (Seq a)
- Symantic.RNC.Sym: namespace :: Sym_RNC repr => Maybe NCName -> Namespace -> repr ()
- Symantic.RNC.Sym: option :: Sym_RNC repr => a -> repr a -> repr a
- Symantic.RNC.Sym: optional :: Sym_RNC repr => repr a -> repr (Maybe a)
- Symantic.RNC.Sym: pure :: Applicative f => a -> f a
- Symantic.RNC.Sym: rule :: (Sym_Rule repr, Show a) => String -> repr a -> repr a
- Symantic.RNC.Sym: runPermutation :: Sym_Permutation repr => Permutation repr a -> repr a
- Symantic.RNC.Sym: some :: Alternative f => f a -> f [a]
- Symantic.RNC.Sym: someSeq :: Sym_RNC repr => repr a -> repr (Seq a)
- Symantic.RNC.Sym: text :: Sym_RNC repr => repr Text
- Symantic.RNC.Sym: toPermutation :: Sym_Permutation repr => repr a -> Permutation repr a
- Symantic.RNC.Sym: toPermutationWithDefault :: Sym_Permutation repr => a -> repr a -> Permutation repr a
- Symantic.RNC.Sym: try :: Sym_RNC repr => repr a -> repr a
- Symantic.RNC.Sym: type family Permutation (repr :: * -> *) = (r :: * -> *) | r -> repr
- Symantic.RNC.Validate: Perm :: Maybe a -> m (Perm m a) -> Perm m a
- Symantic.RNC.Validate: data Perm m a
- Symantic.RNC.Validate: instance (GHC.Classes.Ord err, GHC.Classes.Ord src, Symantic.XML.Document.NoSource src, Text.Megaparsec.Stream.Stream (Data.Sequence.Internal.Seq (Symantic.XML.Document.XML src)), Text.Megaparsec.Stream.Token (Data.Sequence.Internal.Seq (Symantic.XML.Document.XML src)) Data.Type.Equality.~ Data.TreeSeq.Strict.Tree (Symantic.XML.Document.Sourced src Symantic.XML.Document.Node)) => Symantic.RNC.Sym.Sym_RNC (Text.Megaparsec.Parsec err (Symantic.XML.Document.XMLs src))
- Symantic.RNC.Validate: instance (GHC.Classes.Ord err, GHC.Classes.Ord src, Text.Megaparsec.Stream.Stream (Data.Sequence.Internal.Seq (Symantic.XML.Document.XML src))) => Symantic.RNC.Sym.Sym_Permutation (Text.Megaparsec.Internal.ParsecT err (Symantic.XML.Document.XMLs src) m)
- Symantic.RNC.Validate: instance (GHC.Classes.Ord err, GHC.Classes.Ord src, Text.Megaparsec.Stream.Stream (Data.Sequence.Internal.Seq (Symantic.XML.Document.XML src))) => Symantic.RNC.Sym.Sym_Rule (Text.Megaparsec.Internal.ParsecT err (Symantic.XML.Document.XMLs src) m)
- Symantic.RNC.Validate: instance GHC.Base.Alternative m => GHC.Base.Applicative (Symantic.RNC.Validate.Perm m)
- Symantic.RNC.Validate: instance GHC.Base.Functor m => GHC.Base.Functor (Symantic.RNC.Validate.Perm m)
- Symantic.RNC.Validate: isIgnoredNode :: Node -> Bool
- Symantic.RNC.Validate: p_XMLs :: Ord err => Ord src => Stream (Seq (XML src)) => Parsec err (XMLs src) a -> XMLs src -> Parsec err (XMLs src) a
- Symantic.RNC.Validate: validateXML :: Ord e => Parsec e (XMLs src) a -> XMLs src -> Either (ParseErrorBundle (XMLs src) e) a
- Symantic.RNC.Write: Writer :: (Namespaces NCName -> RuleMode -> (Infix, Side) -> Pair -> Text) -> Writer a
- Symantic.RNC.Write: [unWriter] :: Writer a -> Namespaces NCName -> RuleMode -> (Infix, Side) -> Pair -> Text
- Symantic.RNC.Write: coerceWriter :: Writer a -> Writer b
- Symantic.RNC.Write: instance GHC.Base.Alternative Symantic.RNC.Write.Writer
- Symantic.RNC.Write: instance GHC.Base.Applicative Symantic.RNC.Write.Writer
- Symantic.RNC.Write: instance GHC.Base.Functor Symantic.RNC.Write.Writer
- Symantic.RNC.Write: instance Symantic.RNC.Sym.Sym_Permutation Symantic.RNC.Write.Writer
- Symantic.RNC.Write: instance Symantic.RNC.Sym.Sym_RNC Symantic.RNC.Write.Writer
- Symantic.RNC.Write: instance Symantic.RNC.Sym.Sym_Rule Symantic.RNC.Write.Writer
- Symantic.RNC.Write: newtype Writer a
- Symantic.RNC.Write: runWriter :: Namespaces NCName -> Writer a -> Text
- Symantic.RNC.Write: writeRNC :: [NS a] -> [Writer a] -> Text
- Symantic.RNC.Write: writeText :: Text -> Writer a
- Symantic.RNC.Write.Fixity: AssocB :: Side -> Associativity
- Symantic.RNC.Write.Fixity: AssocL :: Associativity
- Symantic.RNC.Write.Fixity: AssocR :: Associativity
- Symantic.RNC.Write.Fixity: Fixity1 :: Unifix -> Fixity
- Symantic.RNC.Write.Fixity: Fixity2 :: Infix -> Fixity
- Symantic.RNC.Write.Fixity: Infix :: Maybe Associativity -> Precedence -> Infix
- Symantic.RNC.Write.Fixity: Postfix :: Precedence -> Unifix
- Symantic.RNC.Write.Fixity: Prefix :: Precedence -> Unifix
- Symantic.RNC.Write.Fixity: SideL :: Side
- Symantic.RNC.Write.Fixity: SideR :: Side
- Symantic.RNC.Write.Fixity: [infix_associativity] :: Infix -> Maybe Associativity
- Symantic.RNC.Write.Fixity: [infix_precedence] :: Infix -> Precedence
- Symantic.RNC.Write.Fixity: [unifix_precedence] :: Unifix -> Precedence
- Symantic.RNC.Write.Fixity: class PrecedenceOf a
- Symantic.RNC.Write.Fixity: data Associativity
- Symantic.RNC.Write.Fixity: data Fixity
- Symantic.RNC.Write.Fixity: data Infix
- Symantic.RNC.Write.Fixity: data Side
- Symantic.RNC.Write.Fixity: data Unifix
- Symantic.RNC.Write.Fixity: infixB :: Side -> Precedence -> Infix
- Symantic.RNC.Write.Fixity: infixL :: Precedence -> Infix
- Symantic.RNC.Write.Fixity: infixN :: Precedence -> Infix
- Symantic.RNC.Write.Fixity: infixN0 :: Infix
- Symantic.RNC.Write.Fixity: infixN5 :: Infix
- Symantic.RNC.Write.Fixity: infixR :: Precedence -> Infix
- Symantic.RNC.Write.Fixity: instance GHC.Classes.Eq Symantic.RNC.Write.Fixity.Associativity
- Symantic.RNC.Write.Fixity: instance GHC.Classes.Eq Symantic.RNC.Write.Fixity.Fixity
- Symantic.RNC.Write.Fixity: instance GHC.Classes.Eq Symantic.RNC.Write.Fixity.Infix
- Symantic.RNC.Write.Fixity: instance GHC.Classes.Eq Symantic.RNC.Write.Fixity.Side
- Symantic.RNC.Write.Fixity: instance GHC.Classes.Eq Symantic.RNC.Write.Fixity.Unifix
- Symantic.RNC.Write.Fixity: instance GHC.Show.Show Symantic.RNC.Write.Fixity.Associativity
- Symantic.RNC.Write.Fixity: instance GHC.Show.Show Symantic.RNC.Write.Fixity.Fixity
- Symantic.RNC.Write.Fixity: instance GHC.Show.Show Symantic.RNC.Write.Fixity.Infix
- Symantic.RNC.Write.Fixity: instance GHC.Show.Show Symantic.RNC.Write.Fixity.Side
- Symantic.RNC.Write.Fixity: instance GHC.Show.Show Symantic.RNC.Write.Fixity.Unifix
- Symantic.RNC.Write.Fixity: instance Symantic.RNC.Write.Fixity.PrecedenceOf Symantic.RNC.Write.Fixity.Fixity
- Symantic.RNC.Write.Fixity: instance Symantic.RNC.Write.Fixity.PrecedenceOf Symantic.RNC.Write.Fixity.Infix
- Symantic.RNC.Write.Fixity: instance Symantic.RNC.Write.Fixity.PrecedenceOf Symantic.RNC.Write.Fixity.Unifix
- Symantic.RNC.Write.Fixity: isPairNeeded :: (Infix, Side) -> Infix -> Bool
- Symantic.RNC.Write.Fixity: pairBrace :: Pair
- Symantic.RNC.Write.Fixity: pairIfNeeded :: Semigroup s => IsString s => Pair -> (Infix, Side) -> Infix -> s -> s
- Symantic.RNC.Write.Fixity: pairParen :: Pair
- Symantic.RNC.Write.Fixity: precedence :: PrecedenceOf a => a -> Precedence
- Symantic.RNC.Write.Fixity: type Pair = (String, String)
- Symantic.RNC.Write.Fixity: type Precedence = Int
- Symantic.RNC.Write.Namespaces: NS :: State State (Namespaces (Maybe NCName)) -> NS a
- Symantic.RNC.Write.Namespaces: State :: HashSet String -> State
- Symantic.RNC.Write.Namespaces: [state_rules] :: State -> HashSet String
- Symantic.RNC.Write.Namespaces: [unNS] :: NS a -> State State (Namespaces (Maybe NCName))
- Symantic.RNC.Write.Namespaces: coerceNS :: NS a -> NS b
- Symantic.RNC.Write.Namespaces: instance Data.Default.Class.Default Symantic.RNC.Write.Namespaces.State
- Symantic.RNC.Write.Namespaces: instance GHC.Base.Alternative Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: instance GHC.Base.Applicative Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: instance GHC.Base.Functor Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: instance GHC.Base.Monoid (Symantic.RNC.Write.Namespaces.NS a)
- Symantic.RNC.Write.Namespaces: instance GHC.Base.Semigroup (Symantic.RNC.Write.Namespaces.NS a)
- Symantic.RNC.Write.Namespaces: instance GHC.Show.Show (Symantic.RNC.Write.Namespaces.NS a)
- Symantic.RNC.Write.Namespaces: instance GHC.Show.Show Symantic.RNC.Write.Namespaces.State
- Symantic.RNC.Write.Namespaces: instance Symantic.RNC.Sym.Sym_Permutation Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: instance Symantic.RNC.Sym.Sym_RNC Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: instance Symantic.RNC.Sym.Sym_Rule Symantic.RNC.Write.Namespaces.NS
- Symantic.RNC.Write.Namespaces: newtype NS a
- Symantic.RNC.Write.Namespaces: newtype State
- Symantic.RNC.Write.Namespaces: runNS :: forall a. [NS a] -> Namespaces NCName
- Symantic.XML: readFile :: FilePath -> IO (Either ErrorRead Text)
- Symantic.XML: readXML :: FilePath -> Text -> Either (ParseErrorBundle Text Error) XMLs
- Symantic.XML: writeFile :: FilePath -> Text -> IO ()
- Symantic.XML: writeXML :: NoSource src => XMLs src -> Text
- Symantic.XML: writeXMLIndented :: NoSource src => Text -> XMLs src -> Text
- Symantic.XML.Document: CharRef :: Char -> CharRef
- Symantic.XML.Document: EntityRef :: NCName -> Text -> EntityRef
- Symantic.XML.Document: EscapedCharRef :: CharRef -> Escaped
- Symantic.XML.Document: EscapedEntityRef :: EntityRef -> Escaped
- Symantic.XML.Document: EscapedPlain :: Text -> Escaped
- Symantic.XML.Document: EscapedText :: Seq Escaped -> EscapedText
- Symantic.XML.Document: FileRange :: FilePath -> pos -> pos -> FileRange pos
- Symantic.XML.Document: LineColumn :: {-# UNPACK #-}Offset -> {-# UNPACK #-}Offset -> LineColumn
- Symantic.XML.Document: NCName :: Text -> NCName
- Symantic.XML.Document: Name :: Text -> Name
- Symantic.XML.Document: Namespace :: Text -> Namespace
- Symantic.XML.Document: Namespaces :: HashMap Namespace prefix -> Namespace -> Namespaces prefix
- Symantic.XML.Document: NodeAttr :: QName -> Node
- Symantic.XML.Document: NodeCDATA :: Text -> Node
- Symantic.XML.Document: NodeComment :: Text -> Node
- Symantic.XML.Document: NodeElem :: QName -> Node
- Symantic.XML.Document: NodePI :: PName -> Text -> Node
- Symantic.XML.Document: NodeText :: EscapedText -> Node
- Symantic.XML.Document: Offset :: Int -> Offset
- Symantic.XML.Document: PName :: Maybe NCName -> NCName -> PName
- Symantic.XML.Document: QName :: Namespace -> NCName -> QName
- Symantic.XML.Document: Sourced :: src -> a -> Sourced src a
- Symantic.XML.Document: Tree :: !a -> !Trees a -> Tree a
- Symantic.XML.Document: [colNum] :: LineColumn -> {-# UNPACK #-}Offset
- Symantic.XML.Document: [entityRef_name] :: EntityRef -> NCName
- Symantic.XML.Document: [entityRef_value] :: EntityRef -> Text
- Symantic.XML.Document: [fileRange_begin] :: FileRange pos -> pos
- Symantic.XML.Document: [fileRange_end] :: FileRange pos -> pos
- Symantic.XML.Document: [fileRange_file] :: FileRange pos -> FilePath
- Symantic.XML.Document: [lineNum] :: LineColumn -> {-# UNPACK #-}Offset
- Symantic.XML.Document: [namespaces_default] :: Namespaces prefix -> Namespace
- Symantic.XML.Document: [namespaces_prefixes] :: Namespaces prefix -> HashMap Namespace prefix
- Symantic.XML.Document: [pNameLocal] :: PName -> NCName
- Symantic.XML.Document: [pNameSpace] :: PName -> Maybe NCName
- Symantic.XML.Document: [qNameLocal] :: QName -> NCName
- Symantic.XML.Document: [qNameSpace] :: QName -> Namespace
- Symantic.XML.Document: [source] :: Sourced src a -> src
- Symantic.XML.Document: [subTrees] :: Tree a -> !Trees a
- Symantic.XML.Document: [unNCName] :: NCName -> Text
- Symantic.XML.Document: [unName] :: Name -> Text
- Symantic.XML.Document: [unNamespace] :: Namespace -> Text
- Symantic.XML.Document: [unSourced] :: Sourced src a -> a
- Symantic.XML.Document: [unTree] :: Tree a -> !a
- Symantic.XML.Document: class NoSource src
- Symantic.XML.Document: data EntityRef
- Symantic.XML.Document: data Escaped
- Symantic.XML.Document: data FileRange pos
- Symantic.XML.Document: data LineColumn
- Symantic.XML.Document: data Namespaces prefix
- Symantic.XML.Document: data Node
- Symantic.XML.Document: data PName
- Symantic.XML.Document: data QName
- Symantic.XML.Document: data Sourced src a
- Symantic.XML.Document: data Tree a
- Symantic.XML.Document: entityRef_amp :: EntityRef
- Symantic.XML.Document: entityRef_apos :: EntityRef
- Symantic.XML.Document: entityRef_gt :: EntityRef
- Symantic.XML.Document: entityRef_lt :: EntityRef
- Symantic.XML.Document: entityRef_quot :: EntityRef
- Symantic.XML.Document: escapeChar :: Char -> Escaped
- Symantic.XML.Document: escapeText :: Text -> EscapedText
- Symantic.XML.Document: filePos1 :: LineColumn
- Symantic.XML.Document: freshNCName :: HashSet NCName -> NCName
- Symantic.XML.Document: freshifyNCName :: HashSet NCName -> NCName -> NCName
- Symantic.XML.Document: instance (GHC.Classes.Eq src, GHC.Classes.Eq a) => GHC.Classes.Eq (Symantic.XML.Document.Sourced src a)
- Symantic.XML.Document: instance (GHC.Classes.Ord src, GHC.Classes.Ord a) => GHC.Classes.Ord (Symantic.XML.Document.Sourced src a)
- Symantic.XML.Document: instance (GHC.Show.Show src, GHC.Show.Show a) => GHC.Show.Show (Symantic.XML.Document.Sourced src a)
- Symantic.XML.Document: instance Data.Default.Class.Default (Symantic.XML.Document.FileRange Symantic.XML.Document.LineColumn)
- Symantic.XML.Document: instance Data.Default.Class.Default (Symantic.XML.Document.FileRange Symantic.XML.Document.Offset)
- Symantic.XML.Document: instance Data.Default.Class.Default (Symantic.XML.Document.Namespaces (GHC.Maybe.Maybe Symantic.XML.Document.NCName))
- Symantic.XML.Document: instance Data.Default.Class.Default (Symantic.XML.Document.Namespaces Symantic.XML.Document.NCName)
- Symantic.XML.Document: instance Data.Default.Class.Default Symantic.XML.Document.LineColumn
- Symantic.XML.Document: instance Data.Default.Class.Default Symantic.XML.Document.Offset
- Symantic.XML.Document: instance Data.Default.Class.Default pos => Symantic.XML.Document.NoSource (Symantic.XML.Document.FileRange pos)
- Symantic.XML.Document: instance Data.Default.Class.Default pos => Symantic.XML.Document.NoSource (Symantic.XML.Document.FileSource pos)
- Symantic.XML.Document: instance Data.Hashable.Class.Hashable Symantic.XML.Document.NCName
- Symantic.XML.Document: instance Data.Hashable.Class.Hashable Symantic.XML.Document.Name
- Symantic.XML.Document: instance Data.Hashable.Class.Hashable Symantic.XML.Document.Namespace
- Symantic.XML.Document: instance Data.Hashable.Class.Hashable Symantic.XML.Document.PName
- Symantic.XML.Document: instance Data.Hashable.Class.Hashable Symantic.XML.Document.QName
- Symantic.XML.Document: instance Data.String.IsString Symantic.XML.Document.NCName
- Symantic.XML.Document: instance Data.String.IsString Symantic.XML.Document.Name
- Symantic.XML.Document: instance Data.String.IsString Symantic.XML.Document.Namespace
- Symantic.XML.Document: instance Data.String.IsString Symantic.XML.Document.PName
- Symantic.XML.Document: instance Data.String.IsString Symantic.XML.Document.QName
- Symantic.XML.Document: instance GHC.Base.Functor (Symantic.XML.Document.Sourced src)
- Symantic.XML.Document: instance GHC.Base.Monoid (Symantic.XML.Document.Namespaces (GHC.Maybe.Maybe Symantic.XML.Document.NCName))
- Symantic.XML.Document: instance GHC.Base.Monoid (Symantic.XML.Document.Namespaces Symantic.XML.Document.NCName)
- Symantic.XML.Document: instance GHC.Base.Monoid Symantic.XML.Document.EscapedText
- Symantic.XML.Document: instance GHC.Base.Monoid Symantic.XML.Document.Offset
- Symantic.XML.Document: instance GHC.Base.Semigroup (Symantic.XML.Document.Namespaces (GHC.Maybe.Maybe Symantic.XML.Document.NCName))
- Symantic.XML.Document: instance GHC.Base.Semigroup (Symantic.XML.Document.Namespaces Symantic.XML.Document.NCName)
- Symantic.XML.Document: instance GHC.Base.Semigroup Symantic.XML.Document.EscapedText
- Symantic.XML.Document: instance GHC.Base.Semigroup Symantic.XML.Document.Offset
- Symantic.XML.Document: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Symantic.XML.Document.Sourced (Symantic.XML.Document.FileSource Symantic.XML.Document.Offset) a)
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.CharRef
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.EntityRef
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.Escaped
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.EscapedText
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.LineColumn
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.NCName
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.Name
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.Namespace
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.Node
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.Offset
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.PName
- Symantic.XML.Document: instance GHC.Classes.Eq Symantic.XML.Document.QName
- Symantic.XML.Document: instance GHC.Classes.Eq pos => GHC.Classes.Eq (Symantic.XML.Document.FileRange pos)
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.CharRef
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.EntityRef
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.Escaped
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.EscapedText
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.LineColumn
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.NCName
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.Name
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.Namespace
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.Node
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.Offset
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.PName
- Symantic.XML.Document: instance GHC.Classes.Ord Symantic.XML.Document.QName
- Symantic.XML.Document: instance GHC.Classes.Ord pos => GHC.Classes.Ord (Symantic.XML.Document.FileRange pos)
- Symantic.XML.Document: instance GHC.Generics.Generic Symantic.XML.Document.PName
- Symantic.XML.Document: instance GHC.Generics.Generic Symantic.XML.Document.QName
- Symantic.XML.Document: instance GHC.Show.Show (Symantic.XML.Document.FileRange Symantic.XML.Document.LineColumn)
- Symantic.XML.Document: instance GHC.Show.Show (Symantic.XML.Document.FileRange Symantic.XML.Document.Offset)
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.CharRef
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.EntityRef
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.Escaped
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.EscapedText
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.LineColumn
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.NCName
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.Name
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.Namespace
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.Node
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.Offset
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.PName
- Symantic.XML.Document: instance GHC.Show.Show Symantic.XML.Document.QName
- Symantic.XML.Document: instance GHC.Show.Show prefix => GHC.Show.Show (Symantic.XML.Document.Namespaces prefix)
- Symantic.XML.Document: instance Symantic.XML.Document.NoSource Symantic.XML.Document.Offset
- Symantic.XML.Document: ncName :: Text -> Maybe NCName
- Symantic.XML.Document: newtype CharRef
- Symantic.XML.Document: newtype EscapedText
- Symantic.XML.Document: newtype NCName
- Symantic.XML.Document: newtype Name
- Symantic.XML.Document: newtype Namespace
- Symantic.XML.Document: newtype Offset
- Symantic.XML.Document: noSource :: NoSource src => src
- Symantic.XML.Document: notSourced :: NoSource src => a -> Sourced src a
- Symantic.XML.Document: pName :: NCName -> PName
- Symantic.XML.Document: pattern Tree0 :: a -> Tree a
- Symantic.XML.Document: poolNCNames :: [NCName]
- Symantic.XML.Document: prefixifyQName :: Namespaces NCName -> QName -> PName
- Symantic.XML.Document: qName :: NCName -> QName
- Symantic.XML.Document: tree0 :: () => a -> Tree a
- Symantic.XML.Document: type FileSource pos = NonEmpty (FileRange pos)
- Symantic.XML.Document: type FileSourced = Sourced (FileSource Offset)
- Symantic.XML.Document: type Trees a = Seq Tree a
- Symantic.XML.Document: type XML src = Tree (Sourced src Node)
- Symantic.XML.Document: type XMLs src = Seq (XML src)
- Symantic.XML.Document: unescapeText :: EscapedText -> Text
- Symantic.XML.Document: union :: Semigroup (Sourced src EscapedText) => XMLs src -> XMLs src -> XMLs src
- Symantic.XML.Document: unions :: Semigroup (Sourced src EscapedText) => Foldable f => f (XMLs src) -> XMLs src
- Symantic.XML.Document: xmlns_empty :: Namespace
- Symantic.XML.Document: xmlns_xml :: Namespace
- Symantic.XML.Document: xmlns_xmlns :: Namespace
- Symantic.XML.Read: ErrorRead_IO :: IOError -> ErrorRead
- Symantic.XML.Read: ErrorRead_Unicode :: UnicodeException -> ErrorRead
- Symantic.XML.Read: data ErrorRead
- Symantic.XML.Read: instance GHC.Show.Show Symantic.XML.Read.ErrorRead
- Symantic.XML.Read: p_AttValue :: Tokens s ~ Text => Parser Error s (FileSourced EscapedText)
- Symantic.XML.Read: p_AttValueText :: Tokens s ~ Text => Char -> Parser Error s (FileSourced EscapedText)
- Symantic.XML.Read: p_Attribute :: Tokens s ~ Text => Parser Error s (FileSourced (PName, FileSourced EscapedText))
- Symantic.XML.Read: p_CDSect :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_CDSect_ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_CDSect__ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_CRLF :: Tokens s ~ Text => Parser e s Char
- Symantic.XML.Read: p_Char :: Tokens s ~ Text => Parser e s Char
- Symantic.XML.Read: p_CharData :: Tokens s ~ Text => Parser e s EscapedText
- Symantic.XML.Read: p_CharRef :: Tokens s ~ Text => Parser Error s CharRef
- Symantic.XML.Read: p_Comment :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_Comment_ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_Comment__ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_ETag :: Tokens s ~ Text => QName -> Parser Error s ()
- Symantic.XML.Read: p_Element :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_Element_ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_EncName :: Tokens s ~ Text => Parser Error s Text
- Symantic.XML.Read: p_EncodingDecl :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_EntityRef :: Tokens s ~ Text => Parser Error s EntityRef
- Symantic.XML.Read: p_Eq :: Tokens s ~ Text => Parser e s ()
- Symantic.XML.Read: p_Misc :: Tokens s ~ Text => Parser Error s XMLs
- Symantic.XML.Read: p_NCName :: Tokens s ~ Text => Parser e s NCName
- Symantic.XML.Read: p_Name :: Tokens s ~ Text => Parser Error s Name
- Symantic.XML.Read: p_PI :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_PITarget :: Tokens s ~ Text => Parser Error s PName
- Symantic.XML.Read: p_PI_ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_PI__ :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_PName :: Tokens s ~ Text => Parser e s PName
- Symantic.XML.Read: p_QName :: Tokens s ~ Text => Parser Error s QName
- Symantic.XML.Read: p_Reference :: Tokens s ~ Text => Parser Error s Escaped
- Symantic.XML.Read: p_S :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_SDDecl :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_STag :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_Space :: Tokens s ~ Text => Parser e s Char
- Symantic.XML.Read: p_Spaces :: Tokens s ~ Text => Parser e s ()
- Symantic.XML.Read: p_Spaces1 :: Tokens s ~ Text => Parser e s ()
- Symantic.XML.Read: p_VersionInfo :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_XMLDecl :: Tokens s ~ Text => Parser Error s XML
- Symantic.XML.Read: p_content :: Tokens s ~ Text => Parser Error s XMLs
- Symantic.XML.Read: p_document :: Tokens s ~ Text => Parser Error s XMLs
- Symantic.XML.Read: p_prolog :: Tokens s ~ Text => Parser Error s XMLs
- Symantic.XML.Read: p_separator :: Tokens s ~ Text => Char -> Parser e s ()
- Symantic.XML.Read: readDecimal :: String -> Integer
- Symantic.XML.Read: readFile :: FilePath -> IO (Either ErrorRead Text)
- Symantic.XML.Read: readHexadecimal :: String -> Integer
- Symantic.XML.Read: readInt :: Integer -> String -> Integer
- Symantic.XML.Read: readXML :: FilePath -> Text -> Either (ParseErrorBundle Text Error) XMLs
- Symantic.XML.Read.Parser: Error_Attribute_collision :: QName -> Error
- Symantic.XML.Read.Parser: Error_CharRef_invalid :: Integer -> Error
- Symantic.XML.Read.Parser: Error_Closing_tag_unexpected :: QName -> QName -> Error
- Symantic.XML.Read.Parser: Error_EntityRef_unknown :: NCName -> Error
- Symantic.XML.Read.Parser: Error_Namespace_empty :: NCName -> Error
- Symantic.XML.Read.Parser: Error_Namespace_prefix_unknown :: NCName -> Error
- Symantic.XML.Read.Parser: Error_Namespace_reserved :: Namespace -> Error
- Symantic.XML.Read.Parser: Error_Namespace_reserved_prefix :: NCName -> Error
- Symantic.XML.Read.Parser: Error_PI_reserved :: PName -> Error
- Symantic.XML.Read.Parser: Reader :: FileSource Offset -> HashMap NCName Namespace -> Namespace -> Reader
- Symantic.XML.Read.Parser: [reader_ns_default] :: Reader -> Namespace
- Symantic.XML.Read.Parser: [reader_ns_scope] :: Reader -> HashMap NCName Namespace
- Symantic.XML.Read.Parser: [reader_source] :: Reader -> FileSource Offset
- Symantic.XML.Read.Parser: data Error
- Symantic.XML.Read.Parser: data Reader
- Symantic.XML.Read.Parser: instance Data.Default.Class.Default Symantic.XML.Read.Parser.Reader
- Symantic.XML.Read.Parser: instance GHC.Classes.Eq Symantic.XML.Read.Parser.Error
- Symantic.XML.Read.Parser: instance GHC.Classes.Ord Symantic.XML.Read.Parser.Error
- Symantic.XML.Read.Parser: instance GHC.Show.Show Symantic.XML.Read.Parser.Error
- Symantic.XML.Read.Parser: instance GHC.Show.Show Symantic.XML.Read.Parser.Reader
- Symantic.XML.Read.Parser: instance Text.Megaparsec.Error.ShowErrorComponent Symantic.XML.Read.Parser.Error
- Symantic.XML.Read.Parser: p_Offset :: Parser e s Offset
- Symantic.XML.Read.Parser: p_Sourced :: Parser e s a -> Parser e s (Sourced (FileSource Offset) a)
- Symantic.XML.Read.Parser: p_SourcedBegin :: Parser e s a -> Parser e s a
- Symantic.XML.Read.Parser: p_SourcedEnd :: Parser e s (a -> Sourced (FileSource Offset) a)
- Symantic.XML.Read.Parser: p_error :: e -> Parser e s a
- Symantic.XML.Read.Parser: p_quoted :: Tokens s ~ Text => (Char -> Parser e s a) -> Parser e s a
- Symantic.XML.Read.Parser: p_until :: Tokens s ~ Text => (Char -> Bool) -> (Char, Text) -> Parser e s Text
- Symantic.XML.Read.Parser: p_until1 :: Tokens s ~ Text => (Char -> Bool) -> (Char, Text) -> Parser e s Text
- Symantic.XML.Read.Parser: setSource :: FileRange pos -> FileSource pos -> FileSource pos
- Symantic.XML.Read.Parser: type Parsable e s a = (Stream s, Token s ~ Char, Ord e, IsString (Tokens s), ShowErrorComponent e)
- Symantic.XML.Read.Parser: type Parser e s a = Parsable e s a => ReaderT Reader (Parsec e s) a
- Symantic.XML.Read.Parser: type XML = XML (FileSource Offset)
- Symantic.XML.Read.Parser: type XMLs = XMLs (FileSource Offset)
- Symantic.XML.Write: Reader :: Namespaces NCName -> Builder -> Text -> Bool -> Reader
- Symantic.XML.Write: [reader_indent] :: Reader -> Builder
- Symantic.XML.Write: [reader_indent_delta] :: Reader -> Text
- Symantic.XML.Write: [reader_no_text] :: Reader -> Bool
- Symantic.XML.Write: [reader_ns_scope] :: Reader -> Namespaces NCName
- Symantic.XML.Write: build :: Buildable a => a -> Builder
- Symantic.XML.Write: buildAttr :: PName -> EscapedText -> Builder
- Symantic.XML.Write: buildAttrValue :: EscapedText -> Builder
- Symantic.XML.Write: class Buildable a
- Symantic.XML.Write: class Writeable a
- Symantic.XML.Write: data Reader
- Symantic.XML.Write: instance Data.Default.Class.Default Symantic.XML.Write.Reader
- Symantic.XML.Write: instance Data.String.IsString Symantic.XML.Write.Write
- Symantic.XML.Write: instance GHC.Base.Monoid Symantic.XML.Write.Write
- Symantic.XML.Write: instance GHC.Base.Semigroup Symantic.XML.Write.Write
- Symantic.XML.Write: instance Symantic.XML.Document.NoSource src => Symantic.XML.Write.Writeable (Symantic.XML.Document.XML src)
- Symantic.XML.Write: instance Symantic.XML.Document.NoSource src => Symantic.XML.Write.Writeable (Symantic.XML.Document.XMLs src)
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Data.Text.Internal.Lazy.Text
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable GHC.Base.String
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable GHC.Types.Char
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.CharRef
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.EntityRef
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.EscapedText
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.NCName
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.Name
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.Namespace
- Symantic.XML.Write: instance Symantic.XML.Write.Buildable Symantic.XML.Document.PName
- Symantic.XML.Write: instance Symantic.XML.Write.Writeable Symantic.XML.Document.NCName
- Symantic.XML.Write: removeSpaces :: XMLs src -> XMLs src
- Symantic.XML.Write: type Write = Reader Reader Builder
- Symantic.XML.Write: writeFile :: FilePath -> Text -> IO ()
- Symantic.XML.Write: writeXML :: NoSource src => XMLs src -> Text
- Symantic.XML.Write: writeXMLIndented :: NoSource src => Text -> XMLs src -> Text
+ Symantic.XML.Language: attribute :: XML repr => QName -> repr a k -> repr a k
+ Symantic.XML.Language: cdata :: XML repr => repr (Text -> k) k
+ Symantic.XML.Language: class Textable repr where {
+ Symantic.XML.Language: class (Composable repr, Tupable repr, Eitherable repr, Textable repr) => XML repr
+ Symantic.XML.Language: comment :: XML repr => repr (Text -> k) k
+ Symantic.XML.Language: element :: XML repr => QName -> repr a k -> repr a k
+ Symantic.XML.Language: literal :: XML repr => Text -> repr k k
+ Symantic.XML.Language: namespace :: (XML repr, Transformable repr) => XML (UnTrans repr) => Maybe NCName -> Namespace -> repr k k
+ Symantic.XML.Language: pi :: XML repr => PName -> repr (Text -> k) k
+ Symantic.XML.Language: text :: (Textable repr, TextConstraint repr a) => repr (a -> k) k
+ Symantic.XML.Language: type TextConstraint repr a = TextConstraint (UnTrans repr) a;
+ Symantic.XML.Language: type family TextConstraint repr a :: Constraint;
+ Symantic.XML.Language: }
+ Symantic.XML.Namespace: NCName :: Text -> NCName
+ Symantic.XML.Namespace: Namespace :: Text -> Namespace
+ Symantic.XML.Namespace: Namespaces :: HashMap Namespace prefix -> Namespace -> Namespaces prefix
+ Symantic.XML.Namespace: PName :: Maybe NCName -> NCName -> PName
+ Symantic.XML.Namespace: QName :: Namespace -> NCName -> QName
+ Symantic.XML.Namespace: [namespaces_default] :: Namespaces prefix -> Namespace
+ Symantic.XML.Namespace: [namespaces_prefixes] :: Namespaces prefix -> HashMap Namespace prefix
+ Symantic.XML.Namespace: [pNameLocal] :: PName -> NCName
+ Symantic.XML.Namespace: [pNameSpace] :: PName -> Maybe NCName
+ Symantic.XML.Namespace: [qNameLocal] :: QName -> NCName
+ Symantic.XML.Namespace: [qNameSpace] :: QName -> Namespace
+ Symantic.XML.Namespace: [unNCName] :: NCName -> Text
+ Symantic.XML.Namespace: [unNamespace] :: Namespace -> Text
+ Symantic.XML.Namespace: data Namespaces prefix
+ Symantic.XML.Namespace: data PName
+ Symantic.XML.Namespace: data QName
+ Symantic.XML.Namespace: defaultNamespaces :: IsString prefix => Namespaces prefix
+ Symantic.XML.Namespace: freshNCName :: HashSet NCName -> NCName
+ Symantic.XML.Namespace: freshifyNCName :: HashSet NCName -> NCName -> NCName
+ Symantic.XML.Namespace: instance Data.Hashable.Class.Hashable Symantic.XML.Namespace.NCName
+ Symantic.XML.Namespace: instance Data.Hashable.Class.Hashable Symantic.XML.Namespace.Namespace
+ Symantic.XML.Namespace: instance Data.Hashable.Class.Hashable Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance Data.String.IsString Symantic.XML.Namespace.NCName
+ Symantic.XML.Namespace: instance Data.String.IsString Symantic.XML.Namespace.Namespace
+ Symantic.XML.Namespace: instance Data.String.IsString Symantic.XML.Namespace.PName
+ Symantic.XML.Namespace: instance Data.String.IsString Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance GHC.Base.Functor Symantic.XML.Namespace.Namespaces
+ Symantic.XML.Namespace: instance GHC.Base.Monoid (Symantic.XML.Namespace.Namespaces (GHC.Maybe.Maybe Symantic.XML.Namespace.NCName))
+ Symantic.XML.Namespace: instance GHC.Base.Monoid (Symantic.XML.Namespace.Namespaces Symantic.XML.Namespace.NCName)
+ Symantic.XML.Namespace: instance GHC.Base.Semigroup (Symantic.XML.Namespace.Namespaces (GHC.Maybe.Maybe Symantic.XML.Namespace.NCName))
+ Symantic.XML.Namespace: instance GHC.Base.Semigroup (Symantic.XML.Namespace.Namespaces Symantic.XML.Namespace.NCName)
+ Symantic.XML.Namespace: instance GHC.Classes.Eq Symantic.XML.Namespace.NCName
+ Symantic.XML.Namespace: instance GHC.Classes.Eq Symantic.XML.Namespace.Namespace
+ Symantic.XML.Namespace: instance GHC.Classes.Eq Symantic.XML.Namespace.PName
+ Symantic.XML.Namespace: instance GHC.Classes.Eq Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance GHC.Classes.Ord Symantic.XML.Namespace.NCName
+ Symantic.XML.Namespace: instance GHC.Classes.Ord Symantic.XML.Namespace.Namespace
+ Symantic.XML.Namespace: instance GHC.Classes.Ord Symantic.XML.Namespace.PName
+ Symantic.XML.Namespace: instance GHC.Classes.Ord Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance GHC.Generics.Generic Symantic.XML.Namespace.PName
+ Symantic.XML.Namespace: instance GHC.Generics.Generic Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance GHC.Show.Show Symantic.XML.Namespace.NCName
+ Symantic.XML.Namespace: instance GHC.Show.Show Symantic.XML.Namespace.Namespace
+ Symantic.XML.Namespace: instance GHC.Show.Show Symantic.XML.Namespace.PName
+ Symantic.XML.Namespace: instance GHC.Show.Show Symantic.XML.Namespace.QName
+ Symantic.XML.Namespace: instance GHC.Show.Show prefix => GHC.Show.Show (Symantic.XML.Namespace.Namespaces prefix)
+ Symantic.XML.Namespace: ncName :: Text -> Maybe NCName
+ Symantic.XML.Namespace: newtype NCName
+ Symantic.XML.Namespace: newtype Namespace
+ Symantic.XML.Namespace: pName :: NCName -> PName
+ Symantic.XML.Namespace: poolNCNames :: [NCName]
+ Symantic.XML.Namespace: prefixifyQName :: Namespaces NCName -> QName -> PName
+ Symantic.XML.Namespace: qName :: NCName -> QName
+ Symantic.XML.Namespace: xmlns_empty :: Namespace
+ Symantic.XML.Namespace: xmlns_xml :: Namespace
+ Symantic.XML.Namespace: xmlns_xmlns :: Namespace
+ Symantic.XML.Namespace: xmlns_xsd :: Namespace
+ Symantic.XML.Read: Read :: Parsec e (ReadStream src) (f -> k) -> Read src e f k
+ Symantic.XML.Read: ReadPerm :: !Maybe (a -> k) -> Parsec err (ReadStream src) (ReadPerm src err a k) -> ReadPerm err a k
+ Symantic.XML.Read: [readPerm_parser] :: ReadPerm err a k -> Parsec err (ReadStream src) (ReadPerm src err a k)
+ Symantic.XML.Read: [readPerm_result] :: ReadPerm err a k -> !Maybe (a -> k)
+ Symantic.XML.Read: [unRead] :: Read src e f k -> Parsec e (ReadStream src) (f -> k)
+ Symantic.XML.Read: class DecodeText a
+ Symantic.XML.Read: concatCont :: [(a -> k) -> k] -> ([a] -> k) -> k
+ Symantic.XML.Read: consCont :: (a -> b -> c) -> ((a -> k) -> k) -> ((b -> k) -> k) -> (c -> k) -> k
+ Symantic.XML.Read: data ReadPerm (src :: * -> *) err a k
+ Symantic.XML.Read: decodeText :: DecodeText a => Parsec Void Text a
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Constant (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Dicurryable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Dicurryable (Symantic.XML.Read.ReadPerm src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Eitherable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Emptyable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Optionable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Repeatable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Tupable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Tupable (Symantic.XML.Read.ReadPerm src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Algebrable.Unitable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Composable.Composable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Composable.Composable (Symantic.XML.Read.ReadPerm src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Composable.Dimapable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Composable.Dimapable (Symantic.XML.Read.ReadPerm src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Composable.Voidable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src) => Symantic.Base.Permutable.Permutable (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src, Symantic.XML.Language.Textable (Symantic.XML.Read.Read src err)) => Symantic.XML.Language.XML (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance (GHC.Classes.Ord err, Symantic.XML.Read.ReadConstraints src, Symantic.XML.Language.Textable (Symantic.XML.Read.Read src err), Symantic.XML.RelaxNG.Language.Definable (Symantic.XML.Read.Read src err)) => Symantic.XML.RelaxNG.Language.RelaxNG (Symantic.XML.Read.Read src err)
+ Symantic.XML.Read: instance GHC.Classes.Ord err => Symantic.XML.Language.Textable (Symantic.XML.Read.Read Symantic.XML.Tree.Source.FileSourced err)
+ Symantic.XML.Read: instance GHC.Classes.Ord err => Symantic.XML.RelaxNG.Language.Definable (Symantic.XML.Read.Read Symantic.XML.Tree.Source.FileSourced err)
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText Data.Text.Internal.Lazy.Text
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText Data.Text.Internal.Text
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText GHC.Base.String
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText GHC.Integer.Type.Integer
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText GHC.Natural.Natural
+ Symantic.XML.Read: instance Symantic.XML.Read.DecodeText GHC.Types.Bool
+ Symantic.XML.Read: instance Symantic.XML.Read.ReadConstraints src => Text.Megaparsec.Stream.Stream (Symantic.XML.Read.ReadStream src)
+ Symantic.XML.Read: instance Symantic.XML.RelaxNG.Language.Definable (Symantic.XML.Read.ReadPerm src err)
+ Symantic.XML.Read: mapCont :: (a -> b) -> ((a -> k) -> k) -> (b -> k) -> k
+ Symantic.XML.Read: messageItemsPretty :: String -> [String] -> String
+ Symantic.XML.Read: newtype Read src e f k
+ Symantic.XML.Read: orList :: IsString s => Monoid s => [s] -> s
+ Symantic.XML.Read: pTokenAttr :: forall e m src. ReadConstraints src => QName -> Set (ErrorItem (Token (ReadStream src))) -> ParsecT e (ReadStream src) m (src EscapedAttr)
+ Symantic.XML.Read: pTokenAttrNameClass :: forall e m src. ReadConstraints src => NameClass -> Set (ErrorItem (Token (ReadStream src))) -> ParsecT e (ReadStream src) m (QName, src EscapedAttr)
+ Symantic.XML.Read: pTokenPI :: forall e m src. UnSource src => PName -> Set (ErrorItem (Token (ReadStream src))) -> ParsecT e (ReadStream src) m Text
+ Symantic.XML.Read: parseErrorTextPretty :: ShowErrorComponent err => ParseError (ReadStream FileSourced) err -> String
+ Symantic.XML.Read: read :: Read FileSourced Void (x -> x) a -> FilePath -> IO (Either String a)
+ Symantic.XML.Read: readNested :: Ord err => ReadConstraints src => Read src err f a -> ReadStream src -> Read src err f a
+ Symantic.XML.Read: removeSpaces :: UnSource src => Trees src -> Trees src
+ Symantic.XML.Read: removeXMLNS :: HashMap QName (src EscapedAttr) -> HashMap QName (src EscapedAttr)
+ Symantic.XML.Read: runRead :: Read FileSourced Void (x -> x) a -> FileSourcedTrees -> Either String a
+ Symantic.XML.Read: showErrorItem :: s ~ ReadStream (Sourced (FileSource Offset)) => Proxy s -> ErrorItem (Token s) -> String
+ Symantic.XML.Read: take1_ :: UnSource src => (Node (src EscapedAttr) -> Bool) -> ReadStream src -> Maybe (Token (ReadStream src), ReadStream src)
+ Symantic.XML.Read: type ReadConstraints src = (Ord (src (Node (src EscapedAttr))), Ord (src EscapedAttr), UnSource src, NoSource src, SourceOf src, Show (Source src), Show (src String), Functor src)
+ Symantic.XML.Read: type ReadStream src = (HashMap QName (src EscapedAttr), Trees src)
+ Symantic.XML.RelaxNG.Compact.Write: RNCWriteInh :: Namespaces NCName -> (Infix, Side) -> Pair -> RNCWriteInh
+ Symantic.XML.RelaxNG.Compact.Write: RNCWriteState :: Namespaces (Maybe NCName) -> Map DefineName (RNCWriteInh -> Maybe Builder) -> RNCWriteState
+ Symantic.XML.RelaxNG.Compact.Write: RNCWriteSyn :: Chained RNCWriteState -> (RNCWriteInh -> Maybe Builder) -> RNCWriteSyn a k
+ Symantic.XML.RelaxNG.Compact.Write: RNCWriteSynPerm :: [RNCWriteSyn a k] -> RNCWriteSynPerm a k
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteInh_namespaces] :: RNCWriteInh -> Namespaces NCName
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteInh_op] :: RNCWriteInh -> (Infix, Side)
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteInh_pair] :: RNCWriteInh -> Pair
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteState_defines] :: RNCWriteState -> Map DefineName (RNCWriteInh -> Maybe Builder)
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteState_namespaces] :: RNCWriteState -> Namespaces (Maybe NCName)
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteSynPerm_alternatives] :: RNCWriteSynPerm a k -> [RNCWriteSyn a k]
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteSyn_schema] :: RNCWriteSyn a k -> RNCWriteInh -> Maybe Builder
+ Symantic.XML.RelaxNG.Compact.Write: [rncWriteSyn_state] :: RNCWriteSyn a k -> Chained RNCWriteState
+ Symantic.XML.RelaxNG.Compact.Write: class RNCText a
+ Symantic.XML.RelaxNG.Compact.Write: coerceRNCWriteSyn :: RNCWriteSyn a k -> RNCWriteSyn a' k'
+ Symantic.XML.RelaxNG.Compact.Write: data RNCWriteInh
+ Symantic.XML.RelaxNG.Compact.Write: data RNCWriteState
+ Symantic.XML.RelaxNG.Compact.Write: data RNCWriteSyn a k
+ Symantic.XML.RelaxNG.Compact.Write: instance Data.String.IsString (Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn a k)
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Constant Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Dicurryable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Eitherable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Emptyable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Optionable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Repeatable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Tupable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Tupable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSynPerm
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Algebrable.Unitable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Composable.Composable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Composable.Composable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSynPerm
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Composable.Dimapable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Composable.Dimapable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSynPerm
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Composable.Voidable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.Base.Permutable.Permutable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.Language.Textable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.Language.XML Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText Data.Text.Internal.Lazy.Text
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText Data.Text.Internal.Text
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText GHC.Base.String
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText GHC.Integer.Type.Integer
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText GHC.Natural.Natural
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText GHC.Types.Bool
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Compact.Write.RNCText GHC.Types.Int
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Language.Definable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Language.Definable Symantic.XML.RelaxNG.Compact.Write.RNCWriteSynPerm
+ Symantic.XML.RelaxNG.Compact.Write: instance Symantic.XML.RelaxNG.Language.RelaxNG Symantic.XML.RelaxNG.Compact.Write.RNCWriteSyn
+ Symantic.XML.RelaxNG.Compact.Write: newtype RNCWriteSynPerm a k
+ Symantic.XML.RelaxNG.Compact.Write: pairRNCWriteInh :: Semigroup s => IsString s => RNCWriteInh -> Infix -> Maybe s -> Maybe s
+ Symantic.XML.RelaxNG.Compact.Write: rncText_params :: RNCText a => Map Text Text
+ Symantic.XML.RelaxNG.Compact.Write: rncText_qname :: RNCText a => QName
+ Symantic.XML.RelaxNG.Compact.Write: runRNCWriteSyn :: RNCWriteSyn a k -> Builder
+ Symantic.XML.RelaxNG.Compact.Write: type Chained a = a -> a
+ Symantic.XML.RelaxNG.Compact.Write: writeRNC :: RNCWriteSyn a k -> Text
+ Symantic.XML.RelaxNG.Language: (*:*) :: NameClass
+ Symantic.XML.RelaxNG.Language: (:*) :: Namespace -> NameClass
+ Symantic.XML.RelaxNG.Language: (:-:) :: NameClass -> NameClass -> NameClass
+ Symantic.XML.RelaxNG.Language: (:::) :: Namespace -> NCName -> NameClass
+ Symantic.XML.RelaxNG.Language: (:|:) :: NameClass -> NameClass -> NameClass
+ Symantic.XML.RelaxNG.Language: NameClass_Any :: NameClass
+ Symantic.XML.RelaxNG.Language: attributeMatch :: RelaxNG repr => NameClass -> repr a k -> repr (QName -> a) k
+ Symantic.XML.RelaxNG.Language: class Definable repr
+ Symantic.XML.RelaxNG.Language: class (XML repr, Permutable repr, Definable repr) => RelaxNG repr
+ Symantic.XML.RelaxNG.Language: data NameClass
+ Symantic.XML.RelaxNG.Language: define :: (Definable repr, Transformable repr) => RelaxNG (UnTrans repr) => DefineName -> repr f k -> repr f k
+ Symantic.XML.RelaxNG.Language: elementMatch :: RelaxNG repr => NameClass -> repr a k -> repr (QName -> a) k
+ Symantic.XML.RelaxNG.Language: infix 9 :::
+ Symantic.XML.RelaxNG.Language: infixl 6 :-:
+ Symantic.XML.RelaxNG.Language: infixr 2 :|:
+ Symantic.XML.RelaxNG.Language: instance Data.String.IsString Symantic.XML.RelaxNG.Language.NameClass
+ Symantic.XML.RelaxNG.Language: instance Symantic.XML.Text.Textify (Symantic.XML.Namespace.Namespaces Symantic.XML.Namespace.NCName, (Symantic.Base.Fixity.Infix, Symantic.Base.Fixity.Side), Symantic.XML.RelaxNG.Language.NameClass)
+ Symantic.XML.RelaxNG.Language: matchNameClass :: NameClass -> QName -> Bool
+ Symantic.XML.RelaxNG.Language: namespacesNameClass :: NameClass -> HashMap Namespace (Maybe NCName)
+ Symantic.XML.RelaxNG.Language: type DefineName = String
+ Symantic.XML.Text: CharRef :: Char -> CharRef
+ Symantic.XML.Text: EntityRef :: NCName -> Text -> EntityRef
+ Symantic.XML.Text: EscapedAttr :: Seq Escaped -> EscapedAttr
+ Symantic.XML.Text: EscapedCharRef :: CharRef -> Escaped
+ Symantic.XML.Text: EscapedEntityRef :: EntityRef -> Escaped
+ Symantic.XML.Text: EscapedPlain :: Text -> Escaped
+ Symantic.XML.Text: EscapedText :: Seq Escaped -> EscapedText
+ Symantic.XML.Text: [entityRef_name] :: EntityRef -> NCName
+ Symantic.XML.Text: [entityRef_value] :: EntityRef -> Text
+ Symantic.XML.Text: class Textify a
+ Symantic.XML.Text: data EntityRef
+ Symantic.XML.Text: data Escaped
+ Symantic.XML.Text: entityRef_amp :: EntityRef
+ Symantic.XML.Text: entityRef_apos :: EntityRef
+ Symantic.XML.Text: entityRef_gt :: EntityRef
+ Symantic.XML.Text: entityRef_lt :: EntityRef
+ Symantic.XML.Text: entityRef_quot :: EntityRef
+ Symantic.XML.Text: escapeAttr :: Text -> EscapedAttr
+ Symantic.XML.Text: escapeAttrChar :: Char -> Escaped
+ Symantic.XML.Text: escapeText :: Text -> EscapedText
+ Symantic.XML.Text: escapeTextChar :: Char -> Escaped
+ Symantic.XML.Text: instance Data.String.IsString Symantic.XML.Text.EscapedAttr
+ Symantic.XML.Text: instance Data.String.IsString Symantic.XML.Text.EscapedText
+ Symantic.XML.Text: instance GHC.Classes.Eq Symantic.XML.Text.CharRef
+ Symantic.XML.Text: instance GHC.Classes.Eq Symantic.XML.Text.EntityRef
+ Symantic.XML.Text: instance GHC.Classes.Eq Symantic.XML.Text.Escaped
+ Symantic.XML.Text: instance GHC.Classes.Eq Symantic.XML.Text.EscapedAttr
+ Symantic.XML.Text: instance GHC.Classes.Eq Symantic.XML.Text.EscapedText
+ Symantic.XML.Text: instance GHC.Classes.Ord Symantic.XML.Text.CharRef
+ Symantic.XML.Text: instance GHC.Classes.Ord Symantic.XML.Text.EntityRef
+ Symantic.XML.Text: instance GHC.Classes.Ord Symantic.XML.Text.Escaped
+ Symantic.XML.Text: instance GHC.Classes.Ord Symantic.XML.Text.EscapedAttr
+ Symantic.XML.Text: instance GHC.Classes.Ord Symantic.XML.Text.EscapedText
+ Symantic.XML.Text: instance GHC.Show.Show Symantic.XML.Text.CharRef
+ Symantic.XML.Text: instance GHC.Show.Show Symantic.XML.Text.EntityRef
+ Symantic.XML.Text: instance GHC.Show.Show Symantic.XML.Text.Escaped
+ Symantic.XML.Text: instance GHC.Show.Show Symantic.XML.Text.EscapedAttr
+ Symantic.XML.Text: instance GHC.Show.Show Symantic.XML.Text.EscapedText
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Data.Text.Internal.Lazy.Text
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify GHC.Base.String
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify GHC.Types.Char
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Namespace.NCName
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Namespace.Namespace
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Namespace.PName
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Text.CharRef
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Text.EntityRef
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Text.EscapedAttr
+ Symantic.XML.Text: instance Symantic.XML.Text.Textify Symantic.XML.Text.EscapedText
+ Symantic.XML.Text: newtype CharRef
+ Symantic.XML.Text: newtype EscapedAttr
+ Symantic.XML.Text: newtype EscapedText
+ Symantic.XML.Text: textify :: Textify a => a -> Builder
+ Symantic.XML.Text: textifyAttr :: PName -> EscapedAttr -> Builder
+ Symantic.XML.Text: unEscapedAttr :: EscapedAttr -> Seq Escaped
+ Symantic.XML.Text: unEscapedText :: EscapedText -> Seq Escaped
+ Symantic.XML.Text: unescapeAttr :: EscapedAttr -> Text
+ Symantic.XML.Text: unescapeText :: EscapedText -> Text
+ Symantic.XML.Tree.Data: NodeCDATA :: Text -> Node attr
+ Symantic.XML.Tree.Data: NodeComment :: Text -> Node attr
+ Symantic.XML.Tree.Data: NodeElem :: QName -> HashMap QName attr -> Node attr
+ Symantic.XML.Tree.Data: NodePI :: PName -> Text -> Node attr
+ Symantic.XML.Tree.Data: NodeText :: EscapedText -> Node attr
+ Symantic.XML.Tree.Data: TreeData :: ((HashMap QName (Identity EscapedAttr) -> Text -> Trees Identity -> k) -> params) -> TreeData params k
+ Symantic.XML.Tree.Data: TreeDataPerm :: repr xml k -> TreeDataPerm repr xml k
+ Symantic.XML.Tree.Data: [unTreeDataPerm] :: TreeDataPerm repr xml k -> repr xml k
+ Symantic.XML.Tree.Data: [unTreeData] :: TreeData params k -> (HashMap QName (Identity EscapedAttr) -> Text -> Trees Identity -> k) -> params
+ Symantic.XML.Tree.Data: data Node attr
+ Symantic.XML.Tree.Data: instance GHC.Classes.Eq attr => GHC.Classes.Eq (Symantic.XML.Tree.Data.Node attr)
+ Symantic.XML.Tree.Data: instance GHC.Classes.Ord attr => GHC.Classes.Ord (Symantic.XML.Tree.Data.Node attr)
+ Symantic.XML.Tree.Data: instance GHC.Show.Show attr => GHC.Show.Show (Symantic.XML.Tree.Data.Node attr)
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Constant Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Dicurryable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Eitherable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Emptyable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Optionable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Repeatable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Tupable (Symantic.XML.Tree.Data.TreeDataPerm Symantic.XML.Tree.Data.TreeData)
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Tupable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Algebrable.Unitable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Composable (Symantic.XML.Tree.Data.TreeDataPerm Symantic.XML.Tree.Data.TreeData)
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Composable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Dimapable (Symantic.XML.Tree.Data.TreeDataPerm Symantic.XML.Tree.Data.TreeData)
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Dimapable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Transformable (Symantic.XML.Tree.Data.TreeDataPerm repr)
+ Symantic.XML.Tree.Data: instance Symantic.Base.Composable.Voidable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.Base.Permutable.Permutable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.XML.Language.Textable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.XML.Language.XML Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.XML.RelaxNG.Language.Definable Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: instance Symantic.XML.RelaxNG.Language.RelaxNG Symantic.XML.Tree.Data.TreeData
+ Symantic.XML.Tree.Data: newtype TreeData params k
+ Symantic.XML.Tree.Data: newtype TreeDataPerm repr xml k
+ Symantic.XML.Tree.Data: pattern Tree0 :: a -> Tree a
+ Symantic.XML.Tree.Data: subTrees :: Tree a -> Trees a
+ Symantic.XML.Tree.Data: tree :: TreeData callers (Trees Identity) -> callers
+ Symantic.XML.Tree.Data: type FileSourcedTree = SourcedTree (FileSource Offset)
+ Symantic.XML.Tree.Data: type FileSourcedTrees = SourcedTrees (FileSource Offset)
+ Symantic.XML.Tree.Data: type SourcedTree src = Tree (Sourced src)
+ Symantic.XML.Tree.Data: type SourcedTrees src = Trees (Sourced src)
+ Symantic.XML.Tree.Data: type Tree src = Tree (src (Node (src EscapedAttr)))
+ Symantic.XML.Tree.Data: type Trees src = Trees (src (Node (src EscapedAttr)))
+ Symantic.XML.Tree.Data: unTree :: Tree a -> a
+ Symantic.XML.Tree.Data: union :: Semigroup (Sourced src EscapedText) => SourcedTrees src -> SourcedTrees src -> SourcedTrees src
+ Symantic.XML.Tree.Data: unions :: Semigroup (Sourced src EscapedText) => Foldable f => f (SourcedTrees src) -> SourcedTrees src
+ Symantic.XML.Tree.Read: ErrorRead_IO :: IOError -> ErrorRead
+ Symantic.XML.Tree.Read: ErrorRead_Unicode :: UnicodeException -> ErrorRead
+ Symantic.XML.Tree.Read: Error_Attribute_collision :: QName -> Error
+ Symantic.XML.Tree.Read: Error_CharRef_invalid :: Integer -> Error
+ Symantic.XML.Tree.Read: Error_Closing_tag_unexpected :: QName -> QName -> Error
+ Symantic.XML.Tree.Read: Error_EntityRef_unknown :: NCName -> Error
+ Symantic.XML.Tree.Read: Error_Namespace_empty :: NCName -> Error
+ Symantic.XML.Tree.Read: Error_Namespace_prefix_unknown :: NCName -> Error
+ Symantic.XML.Tree.Read: Error_Namespace_reserved :: Namespace -> Error
+ Symantic.XML.Tree.Read: Error_Namespace_reserved_prefix :: NCName -> Error
+ Symantic.XML.Tree.Read: Error_PI_reserved :: PName -> Error
+ Symantic.XML.Tree.Read: ReadTreeInh :: FileSource Offset -> HashMap NCName Namespace -> Namespace -> ReadTreeInh
+ Symantic.XML.Tree.Read: [readTreeInh_ns_default] :: ReadTreeInh -> Namespace
+ Symantic.XML.Tree.Read: [readTreeInh_ns_scope] :: ReadTreeInh -> HashMap NCName Namespace
+ Symantic.XML.Tree.Read: [readTreeInh_source] :: ReadTreeInh -> FileSource Offset
+ Symantic.XML.Tree.Read: data Error
+ Symantic.XML.Tree.Read: data ErrorRead
+ Symantic.XML.Tree.Read: data ReadTreeInh
+ Symantic.XML.Tree.Read: defaultReadTreeInh :: ReadTreeInh
+ Symantic.XML.Tree.Read: instance GHC.Classes.Eq Symantic.XML.Tree.Read.Error
+ Symantic.XML.Tree.Read: instance GHC.Classes.Ord Symantic.XML.Tree.Read.Error
+ Symantic.XML.Tree.Read: instance GHC.Show.Show Symantic.XML.Tree.Read.Error
+ Symantic.XML.Tree.Read: instance GHC.Show.Show Symantic.XML.Tree.Read.ErrorRead
+ Symantic.XML.Tree.Read: instance GHC.Show.Show Symantic.XML.Tree.Read.ReadTreeInh
+ Symantic.XML.Tree.Read: instance Text.Megaparsec.Error.ShowErrorComponent Symantic.XML.Tree.Read.Error
+ Symantic.XML.Tree.Read: p_AttrValue :: Tokens s ~ Text => ReadTree Error s EscapedAttr
+ Symantic.XML.Tree.Read: p_AttrValueText :: Tokens s ~ Text => Char -> ReadTree Error s EscapedAttr
+ Symantic.XML.Tree.Read: p_Attribute :: Tokens s ~ Text => ReadTree Error s (PName, FileSourced EscapedAttr)
+ Symantic.XML.Tree.Read: p_CDSect :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_CDSect_ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_CDSect__ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_CRLF :: Tokens s ~ Text => ReadTree e s Char
+ Symantic.XML.Tree.Read: p_Char :: Tokens s ~ Text => ReadTree e s Char
+ Symantic.XML.Tree.Read: p_CharData :: Tokens s ~ Text => ReadTree e s EscapedText
+ Symantic.XML.Tree.Read: p_CharRef :: Tokens s ~ Text => ReadTree Error s CharRef
+ Symantic.XML.Tree.Read: p_Comment :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_Comment_ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_Comment__ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_ETag :: Tokens s ~ Text => QName -> ReadTree Error s ()
+ Symantic.XML.Tree.Read: p_Element :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_Element_ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_EncName :: Tokens s ~ Text => ReadTree Error s Text
+ Symantic.XML.Tree.Read: p_EncodingDecl :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_EntityRef :: Tokens s ~ Text => ReadTree Error s EntityRef
+ Symantic.XML.Tree.Read: p_Eq :: Tokens s ~ Text => ReadTree e s ()
+ Symantic.XML.Tree.Read: p_Miscs :: Tokens s ~ Text => ReadTree Error s FileSourcedTrees
+ Symantic.XML.Tree.Read: p_NCName :: Tokens s ~ Text => ReadTree e s NCName
+ Symantic.XML.Tree.Read: p_Offset :: ReadTree e s Offset
+ Symantic.XML.Tree.Read: p_PI :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_PITarget :: Tokens s ~ Text => ReadTree Error s PName
+ Symantic.XML.Tree.Read: p_PI_ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_PI__ :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_PName :: Tokens s ~ Text => ReadTree e s PName
+ Symantic.XML.Tree.Read: p_QName :: Tokens s ~ Text => ReadTree Error s QName
+ Symantic.XML.Tree.Read: p_Reference :: Tokens s ~ Text => ReadTree Error s Escaped
+ Symantic.XML.Tree.Read: p_SDDecl :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_STag :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_Sourced :: ReadTree e s a -> ReadTree e s (Sourced (FileSource Offset) a)
+ Symantic.XML.Tree.Read: p_SourcedBegin :: ReadTree e s a -> ReadTree e s a
+ Symantic.XML.Tree.Read: p_SourcedEnd :: ReadTree e s (a -> Sourced (FileSource Offset) a)
+ Symantic.XML.Tree.Read: p_Space :: Tokens s ~ Text => ReadTree e s Char
+ Symantic.XML.Tree.Read: p_Spaces :: Tokens s ~ Text => ReadTree e s ()
+ Symantic.XML.Tree.Read: p_Spaces1 :: Tokens s ~ Text => ReadTree e s ()
+ Symantic.XML.Tree.Read: p_VersionInfo :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_XMLDecl :: Tokens s ~ Text => ReadTree Error s FileSourcedTree
+ Symantic.XML.Tree.Read: p_content :: Tokens s ~ Text => ReadTree Error s FileSourcedTrees
+ Symantic.XML.Tree.Read: p_document :: Tokens s ~ Text => ReadTree Error s FileSourcedTrees
+ Symantic.XML.Tree.Read: p_error :: e -> ReadTree e s a
+ Symantic.XML.Tree.Read: p_prolog :: Tokens s ~ Text => ReadTree Error s FileSourcedTrees
+ Symantic.XML.Tree.Read: p_quoted :: Tokens s ~ Text => (Char -> ReadTree e s a) -> ReadTree e s a
+ Symantic.XML.Tree.Read: p_separator :: Tokens s ~ Text => Char -> ReadTree e s ()
+ Symantic.XML.Tree.Read: p_until :: Tokens s ~ Text => (Char -> Bool) -> (Char, Text) -> ReadTree e s Text
+ Symantic.XML.Tree.Read: p_until1 :: Tokens s ~ Text => (Char -> Bool) -> (Char, Text) -> ReadTree e s Text
+ Symantic.XML.Tree.Read: readDecimal :: String -> Integer
+ Symantic.XML.Tree.Read: readHexadecimal :: String -> Integer
+ Symantic.XML.Tree.Read: readInt :: Integer -> String -> Integer
+ Symantic.XML.Tree.Read: readTree :: FilePath -> IO (Either String FileSourcedTrees)
+ Symantic.XML.Tree.Read: readUtf8 :: FilePath -> IO (Either ErrorRead Text)
+ Symantic.XML.Tree.Read: runReadTree :: FilePath -> Text -> Either (ParseErrorBundle Text Error) FileSourcedTrees
+ Symantic.XML.Tree.Read: setSource :: FileRange pos -> FileSource pos -> FileSource pos
+ Symantic.XML.Tree.Read: type ReadTreeConstraints e s a = (Stream s, Token s ~ Char, Ord e, IsString (Tokens s), ShowErrorComponent e)
+ Symantic.XML.Tree.Read: type ReadTree e s a = ReadTreeConstraints e s a => ReaderT ReadTreeInh (Parsec e s) a
+ Symantic.XML.Tree.Source: FileRange :: FilePath -> pos -> pos -> FileRange pos
+ Symantic.XML.Tree.Source: FileSource :: NonEmpty (FileRange pos) -> FileSource pos
+ Symantic.XML.Tree.Source: LineColumn :: {-# UNPACK #-}Offset -> {-# UNPACK #-}Offset -> LineColumn
+ Symantic.XML.Tree.Source: Offset :: Int -> Offset
+ Symantic.XML.Tree.Source: Sourced :: src -> a -> Sourced src a
+ Symantic.XML.Tree.Source: [colNum] :: LineColumn -> {-# UNPACK #-}Offset
+ Symantic.XML.Tree.Source: [fileRange_begin] :: FileRange pos -> pos
+ Symantic.XML.Tree.Source: [fileRange_end] :: FileRange pos -> pos
+ Symantic.XML.Tree.Source: [fileRange_path] :: FileRange pos -> FilePath
+ Symantic.XML.Tree.Source: [lineNum] :: LineColumn -> {-# UNPACK #-}Offset
+ Symantic.XML.Tree.Source: [source] :: Sourced src a -> src
+ Symantic.XML.Tree.Source: [unSourced] :: Sourced src a -> a
+ Symantic.XML.Tree.Source: class NoSource src
+ Symantic.XML.Tree.Source: class SourceOf src
+ Symantic.XML.Tree.Source: class UnSource src
+ Symantic.XML.Tree.Source: data FileRange pos
+ Symantic.XML.Tree.Source: data LineColumn
+ Symantic.XML.Tree.Source: data Sourced src a
+ Symantic.XML.Tree.Source: instance (GHC.Show.Show src, GHC.Show.Show a, Symantic.XML.Tree.Source.NoSource (Symantic.XML.Tree.Source.Sourced src)) => GHC.Show.Show (Symantic.XML.Tree.Source.Sourced src a)
+ Symantic.XML.Tree.Source: instance GHC.Base.Functor (Symantic.XML.Tree.Source.Sourced src)
+ Symantic.XML.Tree.Source: instance GHC.Base.Monoid Symantic.XML.Tree.Source.Offset
+ Symantic.XML.Tree.Source: instance GHC.Base.Semigroup Symantic.XML.Tree.Source.Offset
+ Symantic.XML.Tree.Source: instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Symantic.XML.Tree.Source.Sourced (Symantic.XML.Tree.Source.FileSource Symantic.XML.Tree.Source.Offset) a)
+ Symantic.XML.Tree.Source: instance GHC.Classes.Eq Symantic.XML.Tree.Source.LineColumn
+ Symantic.XML.Tree.Source: instance GHC.Classes.Eq Symantic.XML.Tree.Source.Offset
+ Symantic.XML.Tree.Source: instance GHC.Classes.Eq a => GHC.Classes.Eq (Symantic.XML.Tree.Source.Sourced src a)
+ Symantic.XML.Tree.Source: instance GHC.Classes.Eq pos => GHC.Classes.Eq (Symantic.XML.Tree.Source.FileRange pos)
+ Symantic.XML.Tree.Source: instance GHC.Classes.Eq pos => GHC.Classes.Eq (Symantic.XML.Tree.Source.FileSource pos)
+ Symantic.XML.Tree.Source: instance GHC.Classes.Ord Symantic.XML.Tree.Source.LineColumn
+ Symantic.XML.Tree.Source: instance GHC.Classes.Ord Symantic.XML.Tree.Source.Offset
+ Symantic.XML.Tree.Source: instance GHC.Classes.Ord a => GHC.Classes.Ord (Symantic.XML.Tree.Source.Sourced src a)
+ Symantic.XML.Tree.Source: instance GHC.Classes.Ord pos => GHC.Classes.Ord (Symantic.XML.Tree.Source.FileRange pos)
+ Symantic.XML.Tree.Source: instance GHC.Show.Show (Symantic.XML.Tree.Source.FileRange Symantic.XML.Tree.Source.LineColumn)
+ Symantic.XML.Tree.Source: instance GHC.Show.Show (Symantic.XML.Tree.Source.FileRange Symantic.XML.Tree.Source.Offset)
+ Symantic.XML.Tree.Source: instance GHC.Show.Show (Symantic.XML.Tree.Source.FileRange pos) => GHC.Show.Show (Symantic.XML.Tree.Source.FileSource pos)
+ Symantic.XML.Tree.Source: instance GHC.Show.Show Symantic.XML.Tree.Source.LineColumn
+ Symantic.XML.Tree.Source: instance GHC.Show.Show Symantic.XML.Tree.Source.Offset
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.NoSource (Symantic.XML.Tree.Source.Sourced (Symantic.XML.Tree.Source.FileSource Symantic.XML.Tree.Source.Offset))
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.NoSource Data.Functor.Identity.Identity
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.SourceOf (Symantic.XML.Tree.Source.Sourced src)
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.SourceOf Data.Functor.Identity.Identity
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.UnSource (Symantic.XML.Tree.Source.Sourced src)
+ Symantic.XML.Tree.Source: instance Symantic.XML.Tree.Source.UnSource Data.Functor.Identity.Identity
+ Symantic.XML.Tree.Source: newtype FileSource pos
+ Symantic.XML.Tree.Source: newtype Offset
+ Symantic.XML.Tree.Source: noSource :: NoSource src => a -> src a
+ Symantic.XML.Tree.Source: nullSource :: (NoSource src, Eq (Source src)) => SourceOf src => Source src -> Bool
+ Symantic.XML.Tree.Source: sourceOf :: SourceOf src => src a -> Source src
+ Symantic.XML.Tree.Source: type FileSourced = Sourced (FileSource Offset)
+ Symantic.XML.Tree.Source: type family Source (src :: * -> *) :: *
+ Symantic.XML.Tree.Source: unSource :: UnSource src => src a -> a
+ Symantic.XML.Tree.Write: TreeWrite :: (WriteInh -> Builder) -> TreeWrite
+ Symantic.XML.Tree.Write: [unTreeWrite] :: TreeWrite -> WriteInh -> Builder
+ Symantic.XML.Tree.Write: instance Data.String.IsString Symantic.XML.Tree.Write.TreeWrite
+ Symantic.XML.Tree.Write: instance GHC.Base.Monoid Symantic.XML.Tree.Write.TreeWrite
+ Symantic.XML.Tree.Write: instance GHC.Base.Semigroup Symantic.XML.Tree.Write.TreeWrite
+ Symantic.XML.Tree.Write: newtype TreeWrite
+ Symantic.XML.Tree.Write: writeFile :: FilePath -> Text -> IO ()
+ Symantic.XML.Tree.Write: writeTree :: UnSource src => Trees src -> Text
+ Symantic.XML.Tree.Write: writeTreeIndented :: UnSource src => Text -> Trees src -> Text
+ Symantic.XML.Tree.Write: write_Tree :: UnSource src => Tree src -> TreeWrite
+ Symantic.XML.Tree.Write: write_Trees :: UnSource src => Trees src -> TreeWrite
+ Symantic.XML.Write: Write :: ((WriteSyn -> k) -> params) -> Write params k
+ Symantic.XML.Write: WriteInh :: Namespaces NCName -> Builder -> Text -> WriteInh
+ Symantic.XML.Write: WritePerm :: repr xml k -> WritePerm repr xml k
+ Symantic.XML.Write: WriteSyn :: HashMap QName Text -> Text -> Maybe Namespace -> HashMap Namespace NCName -> (WriteInh -> Maybe Builder) -> WriteSyn
+ Symantic.XML.Write: [unWritePerm] :: WritePerm repr xml k -> repr xml k
+ Symantic.XML.Write: [unWrite] :: Write params k -> (WriteSyn -> k) -> params
+ Symantic.XML.Write: [writeInh_indent] :: WriteInh -> Builder
+ Symantic.XML.Write: [writeInh_indent_delta] :: WriteInh -> Text
+ Symantic.XML.Write: [writeInh_namespaces] :: WriteInh -> Namespaces NCName
+ Symantic.XML.Write: [writeSyn_attr] :: WriteSyn -> Text
+ Symantic.XML.Write: [writeSyn_attrs] :: WriteSyn -> HashMap QName Text
+ Symantic.XML.Write: [writeSyn_namespaces_default] :: WriteSyn -> Maybe Namespace
+ Symantic.XML.Write: [writeSyn_namespaces_prefixes] :: WriteSyn -> HashMap Namespace NCName
+ Symantic.XML.Write: [writeSyn_result] :: WriteSyn -> WriteInh -> Maybe Builder
+ Symantic.XML.Write: class EncodeText a
+ Symantic.XML.Write: data WriteInh
+ Symantic.XML.Write: data WriteSyn
+ Symantic.XML.Write: defaultWriteInh :: WriteInh
+ Symantic.XML.Write: encodeText :: (EncodeText a, Show a) => a -> Text
+ Symantic.XML.Write: instance GHC.Base.Monoid Symantic.XML.Write.WriteSyn
+ Symantic.XML.Write: instance GHC.Base.Semigroup Symantic.XML.Write.WriteSyn
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Constant Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Dicurryable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Eitherable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Emptyable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Optionable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Repeatable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Tupable (Symantic.XML.Write.WritePerm Symantic.XML.Write.Write)
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Tupable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Algebrable.Unitable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Composable.Composable (Symantic.XML.Write.WritePerm Symantic.XML.Write.Write)
+ Symantic.XML.Write: instance Symantic.Base.Composable.Composable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Composable.Dimapable (Symantic.XML.Write.WritePerm Symantic.XML.Write.Write)
+ Symantic.XML.Write: instance Symantic.Base.Composable.Dimapable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Composable.Transformable (Symantic.XML.Write.WritePerm repr)
+ Symantic.XML.Write: instance Symantic.Base.Composable.Voidable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.Base.Permutable.Permutable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.XML.Language.Textable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.XML.Language.XML Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.XML.RelaxNG.Language.Definable Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.XML.RelaxNG.Language.RelaxNG Symantic.XML.Write.Write
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText Data.Text.Internal.Lazy.Text
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText Data.Text.Internal.Text
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText GHC.Base.String
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText GHC.Integer.Type.Integer
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText GHC.Natural.Natural
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText GHC.Types.Bool
+ Symantic.XML.Write: instance Symantic.XML.Write.EncodeText GHC.Types.Int
+ Symantic.XML.Write: newtype Write params k
+ Symantic.XML.Write: newtype WritePerm repr xml k
+ Symantic.XML.Write: nl :: WriteInh -> Builder
+ Symantic.XML.Write: runWrite :: WriteInh -> Write params ByteString -> params
+ Symantic.XML.Write: type ErrorWrite = IOError
+ Symantic.XML.Write: writeUtf8 :: FilePath -> Write params (IO (Maybe ErrorWrite)) -> params
- Symantic.XML.Write: write :: Writeable a => a -> Write
+ Symantic.XML.Write: write :: Write params ByteString -> params

Files

− Symantic/RNC.hs
@@ -1,14 +0,0 @@-module Symantic.RNC- ( module Symantic.RNC.Sym- , module Symantic.RNC.Validate- , module Symantic.RNC.Write- , Functor(..)- , Applicative(..)- , Alternative((<|>))- ) where-import Data.Functor-import Control.Applicative--import Symantic.RNC.Sym-import Symantic.RNC.Write-import Symantic.RNC.Validate
− Symantic/RNC/Sym.hs
@@ -1,100 +0,0 @@-{-# LANGUAGE TypeFamilyDependencies #-}-module Symantic.RNC.Sym- ( module Symantic.RNC.Sym- , Functor(..), (<$>)- , Applicative(..)- , Alternative(..)- ) where--import Control.Applicative (Applicative(..), Alternative(..))-import Data.Eq (Eq)-import Data.Function ((.), id)-import Data.Functor (Functor(..), (<$>))-import Data.Maybe (Maybe(..))-import Data.Sequence (Seq)-import Data.String (String)-import Text.Show (Show(..))-import qualified Data.Sequence as Seq-import qualified Data.Text.Lazy as TL--import qualified Symantic.XML as XML---- * Class 'Sym_RNC'-class- ( Applicative repr- , Alternative repr- , Sym_Rule repr- , Sym_Permutation repr- ) => Sym_RNC repr where-	namespace   :: Maybe XML.NCName -> XML.Namespace -> repr ()-	element     :: XML.QName -> repr a -> repr a-	attribute   :: XML.QName -> repr a -> repr a-	any         :: repr ()-	anyElem     :: XML.Namespace -> (XML.NCName -> repr a) -> repr a-	escapedText :: repr XML.EscapedText-	text        :: repr TL.Text-	text = XML.unescapeText <$> escapedText-	fail        :: repr a-	try         :: repr a -> repr a-	option      :: a -> repr a -> repr a-	optional    :: repr a -> repr (Maybe a)-	choice      :: [repr a] -> repr a-	intermany   :: [repr a] -> repr [a]-	intermany = many . choice . (try <$>)-	manySeq :: repr a -> repr (Seq a)-	manySeq r = Seq.fromList <$> many r-	someSeq :: repr a -> repr (Seq a)-	someSeq r = Seq.fromList <$> some r---- * Class 'Sym_Rule'-class Sym_Rule repr where-	rule :: Show a => String -> repr a -> repr a-	rule _n = id-	arg :: String -> repr ()---- ** Type 'RuleMode'-data RuleMode- =   RuleMode_Body -- ^ Request to generate the body of the rule.- |   RuleMode_Ref  -- ^ Request to generate a reference to the rule.- |   RuleMode_Def  -- ^ Request to generate a definition of the rule.- deriving (Eq, Show)---- * Class 'Sym_Permutation'-class (Alternative repr, Applicative (Permutation repr)) => Sym_Permutation repr where-	runPermutation :: Permutation repr a -> repr a-	toPermutation :: repr a -> Permutation repr a-	toPermutationWithDefault :: a -> repr a -> Permutation repr a-	-	(<$$>) :: (a -> b) -> repr a -> Permutation repr b-	(<$?>) :: (a -> b) -> (a, repr a) -> Permutation repr b-	(<$*>) :: ([a] -> b) -> repr a -> Permutation repr b-	(<$:>) :: (Seq a -> b) -> repr a -> Permutation repr b-	infixl 2 <$$>, <$?>, <$*>, <$:>-	{-# INLINE (<$$>) #-}-	{-# INLINE (<$?>) #-}-	{-# INLINE (<$*>) #-}-	{-# INLINE (<$:>) #-}-	-	(<||>) :: Permutation repr (a -> b) -> repr a -> Permutation repr b-	(<|?>) :: Permutation repr (a -> b) -> (a, repr a) -> Permutation repr b-	(<|*>) :: Permutation repr ([a] -> b) -> repr a -> Permutation repr b-	(<|:>) :: Permutation repr (Seq a -> b) -> repr a -> Permutation repr b-	infixl 1 <||>, <|?>, <|*>, <|:>-	{-# INLINE (<||>) #-}-	{-# INLINE (<|?>) #-}-	{-# INLINE (<|*>) #-}-	{-# INLINE (<|:>) #-}-	-	f <$$> x = f <$> toPermutation x-	f <$?> (d,x) = f <$> toPermutationWithDefault d x-	f <$*> x = f <$> toPermutationWithDefault [] (some x)-	f <$:> x = f . Seq.fromList <$> toPermutationWithDefault [] (some x)-	-	f <||> x = f <*> toPermutation x-	f <|?> (d,x) = f <*> toPermutationWithDefault d x-	f <|*> x = f <*> toPermutationWithDefault [] (some x)-	f <|:> x = f <*> toPermutationWithDefault Seq.empty (Seq.fromList <$> some x)---- ** Type family 'Permutation'--- | Type of permutations, depending on the representation.-type family Permutation (repr:: * -> *) = (r :: * -> *) | r -> repr
− Symantic/RNC/Validate.hs
@@ -1,206 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Symantic.RNC.Validate where--import Control.Applicative (Applicative(..), Alternative(..), optional)-import Control.Monad (Monad(..))-import Data.Bool-import Data.Either (Either(..))-import Data.Eq (Eq(..))-import Data.Foldable (Foldable(..), all)-import Data.Function (($), const, id)-import Data.Functor (Functor(..), (<$>))-import Data.Maybe (Maybe(..), maybe)-import Data.Monoid (Monoid(..))-import Data.Ord (Ord(..))-import Data.Semigroup (Semigroup(..))-import Data.Tuple (snd)-import Prelude (error)-import Data.Sequence (Seq)-import qualified Data.Char as Char-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Sequence as Seq-import qualified Data.Set as Set-import qualified Data.Text.Lazy as TL-import qualified Text.Megaparsec as P--import Symantic.XML (XMLs)-import qualified Symantic.XML as XML-import qualified Symantic.RNC.Sym as RNC--validateXML ::- Ord e => P.Parsec e (XMLs src) a -> XMLs src ->- Either (P.ParseErrorBundle (XMLs src) e) a-validateXML p stateInput =-	snd $-	P.runParser' p P.State-	 { P.stateInput-	 , P.stateOffset = 0-	 , P.statePosState = error "[BUG] validateXML: getSourcePos is not helpful here, please use annotated source locations"-	  -- NOTE: reporting the node number is less helpful-		-- than the source text line and number where the node is;-		-- P.statePosState is only used by P.getSourcePos.-	 }--instance- ( Ord err- , Ord src- , XML.NoSource src- , P.Stream (Seq (XML.XML src))- , P.Token  (Seq (XML.XML src)) ~ XML.Tree (XML.Sourced src XML.Node)- ) => RNC.Sym_RNC (P.Parsec err (XMLs src)) where-	{--	none = P.label "none" $ P.eof-	-}-	namespace _p _n = pure ()-	element n p = do-		ts <- P.token check $ Set.singleton $ P.Tokens $ pure expected-		p_XMLs p ts-		where-		expected = XML.Tree (XML.notSourced $ XML.NodeElem n) mempty-		check (XML.Tree (XML.unSourced -> XML.NodeElem e) ts)-		 | e == n-		 = Just $ removePI $ removeXMLNS $ removeSpaces ts-			where-			removePI xs =-				(`Seq.filter` xs) $ \case-					 XML.Tree (XML.unSourced -> XML.NodePI{}) _ts -> False-					 _ -> True-			removeSpaces xs =-				if (`all` xs) $ \case-				 XML.Tree (XML.unSourced -> XML.NodeText (XML.EscapedText et)) _ts ->-					all (\case-					 XML.EscapedPlain t -> TL.all Char.isSpace t-					 _ -> False) et-				 _ -> True-				then (`Seq.filter` xs) $ \case-					 XML.Tree (XML.unSourced -> XML.NodeText{}) _ts -> False-					 _ -> True-				else xs-			removeXMLNS xs =-				let (attrs,rest) = (`Seq.spanl` xs) $ \case-					 XML.Tree (XML.unSourced -> XML.NodeAttr{}) _ts -> True-					 _ -> False in-				let attrs' = (`Seq.filter` attrs) $ \case-					 XML.Tree (XML.unSourced -> XML.NodeAttr a) _ts ->-						case a of-						 XML.QName "" "xmlns" -> False-						 XML.QName ns _l -> ns /= XML.xmlns_xmlns-					 _ -> True in-				attrs' <> rest-		check _t = Nothing-	attribute n p = do-		v <- P.token check $ Set.singleton $ P.Tokens $ pure expected-		p_XMLs p v-		where-		expected = XML.Tree0 (XML.notSourced $ XML.NodeAttr n)-		check (XML.Tree (XML.unSourced -> XML.NodeAttr k)-		      v@(toList -> [XML.Tree0 (XML.unSourced -> XML.NodeText _v)])) | k == n =-			Just v-		check _t = Nothing-	any  = P.label "any" $-		P.token (const $ Just ())  Set.empty-	anyElem ns p = P.label "anyElem" $ do-		(n,ts) <- P.token check $ Set.singleton $ P.Tokens $ pure expected-		p_XMLs (p $ XML.qNameLocal n) ts-		where-		expected = XML.Tree (XML.notSourced $ XML.NodeElem $ XML.QName ns $ XML.NCName "*") mempty-		check (XML.Tree (XML.unSourced -> XML.NodeElem e) ts)-		 | XML.qNameSpace e == ns-		 = Just $ (e,ts)-		check _t = Nothing-	{--	comment = do-		s <- P.getInput-		case Seq.viewl s of-		 XML.Tree0 (XML.unSourced -> XML.NodeComment c) :< ts -> do-			P.setInput ts-			c <$ XML.setFilePosToNextNode-		 t :< _ts -> P.failure (Just $ P.Tokens $ pure t) ex-		 EmptyL -> P.failure Nothing ex-		where-		ex = Set.singleton $ P.Tokens $ pure expected-		expected = XML.Tree0 (XML.notSourced $ XML.NodeComment "")-	-}-	escapedText = do-		P.token check $ Set.singleton $ P.Tokens $ pure expected-		where-		expected = XML.Tree0 (XML.notSourced $ XML.NodeText $ XML.EscapedText mempty)-		check (XML.Tree0 (XML.unSourced -> XML.NodeText t)) = Just t-		check _t = Nothing-	optional = P.optional-	option   = P.option-	choice   = P.choice-	try      = P.try-	fail     = P.label "fail" $ P.failure Nothing mempty---- | @p_XMLs p xs@ returns a parser parsing @xs@ entirely with @p@,--- updating 'P.stateOffset' and re-raising any exception.-p_XMLs ::- Ord err => Ord src =>- P.Stream (Seq (XML.XML src)) =>- P.Parsec err (XMLs src) a -> XMLs src -> P.Parsec err (XMLs src) a-p_XMLs p stateInput = do-	st <- P.getParserState-	let (st', res) = P.runParser' (p <* P.eof) st-		 { P.stateInput  = stateInput-		 , P.stateOffset = P.stateOffset st-		 }-	P.updateParserState (\s -> s{P.stateOffset = P.stateOffset st'})-	case res of-	 Right a -> return a-	 Left (P.ParseErrorBundle errs _) ->-		case NonEmpty.head errs of-		 P.TrivialError _o us es -> P.failure us es-		 P.FancyError _o es -> P.fancyFailure es---- | Whether the given 'XML.Node' must be ignored by the RNC parser.-isIgnoredNode :: XML.Node -> Bool-isIgnoredNode = \case- XML.NodeComment{} -> True- XML.NodePI{}      -> True- XML.NodeCDATA{}   -> True- _ -> False--instance- ( Ord err- , Ord src- , P.Stream (Seq (XML.XML src))- ) => RNC.Sym_Permutation (P.ParsecT err (XMLs src) m) where-	runPermutation (Perm value parser) = optional parser >>= f-		where-		-- NOTE: copy Control.Applicative.Permutations.runPermutation-		-- to replace the commented empty below so that P.TrivialError-		-- has the unexpected token.-		f  Nothing = maybe {-empty-}(P.token (const Nothing) Set.empty) pure value-		f (Just p) = RNC.runPermutation p-	toPermutation p = Perm Nothing $ pure <$> p-	toPermutationWithDefault v p = Perm (Just v) $ pure <$> p---- | Unprivatized 'Control.Applicative.Permutations.Permutation' to fix 'runPermutation'.--- so that the 'P.TrivialError' has an unexpected token--- which is an 'XML.Node' containing a 'XML.FileSource' useful when reporting errors.-data Perm m a = Perm (Maybe a) (m (Perm m a))-type instance RNC.Permutation (P.ParsecT err (XMLs src) m) = Perm (P.ParsecT err (XMLs src) m)-instance Functor m => Functor (Perm m) where-	fmap f (Perm v p) = Perm (f <$> v) (fmap f <$> p)-instance Alternative m => Applicative (Perm m) where-	pure value = Perm (Just value) empty-	lhs@(Perm f v) <*> rhs@(Perm g w) = Perm (f <*> g) (lhsAlt <|> rhsAlt)-		where-		lhsAlt = (<*> rhs) <$> v-		rhsAlt = (lhs <*>) <$> w--instance- ( Ord err- , Ord src- , P.Stream (Seq (XML.XML src))- ) => RNC.Sym_Rule (P.ParsecT err (XMLs src) m) where-	-- rule n p = P.dbg s p {-(p P.<?> s)-} where s = Text.unpack n-	rule _n = id-	arg _n = pure ()
− Symantic/RNC/Write.hs
@@ -1,165 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE OverloadedStrings #-}-module Symantic.RNC.Write- ( module Symantic.RNC.Write- , module Symantic.RNC.Write.Fixity- , module Symantic.RNC.Write.Namespaces- ) where--import Control.Applicative (Applicative(..), Alternative(..))-import Control.Monad-import Data.Bool-import Data.Function (($), (.), id)-import Data.Functor ((<$>))-import Data.Functor.Compose (Compose(..))-import Data.Semigroup (Semigroup(..))-import Data.String (IsString(..))-import Text.Show (Show(..))-import qualified Data.HashMap.Strict as HM-import qualified Data.List as List-import qualified Data.Text.Lazy as TL--- import qualified Data.Text.Lazy.Builder as TLB--import Symantic.RNC.Sym-import Symantic.RNC.Write.Fixity-import Symantic.RNC.Write.Namespaces-import qualified Symantic.XML as XML---- | Get textual rendition of given 'RuleWriter'.-writeRNC :: [NS a] -> [Writer a] -> TL.Text-writeRNC ns ws =-	let namespaces@XML.Namespaces{..} = runNS ns in-	TL.unlines $ List.concat-	 [ [ "default namespace = \""<>XML.unNamespace namespaces_default<>"\""-		 | not $ TL.null $ XML.unNamespace namespaces_default-		 ]-	 , [ "namespace "<>p<>" = \""<>n<>"\""-		 | (XML.Namespace n, XML.NCName p) <- HM.toList namespaces_prefixes-		 ]-	 , runWriter namespaces <$> ws-	 ]---- * Type 'Writer'-newtype Writer a- = Writer { unWriter :: XML.Namespaces XML.NCName ->-                        RuleMode ->-                        (Infix, Side) ->-                        Pair -> TL.Text }---- | Get textual rendition of given 'Writer'.-runWriter :: XML.Namespaces XML.NCName -> Writer a -> TL.Text-runWriter ns (Writer w) =-	w ns RuleMode_Def (infixN0, SideL) pairParen--coerceWriter :: Writer a -> Writer b-coerceWriter = Writer . unWriter-{-# INLINE coerceWriter #-}--{--instance Show (Writer a) where-	show = TL.unpack . runWriter--}-instance Functor Writer where-	fmap _f (Writer x) = Writer x-instance Applicative Writer where-	pure _ = writeText $ "\"\""-	Writer f <*> Writer x = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		TL.intercalate ", " $-		List.filter (not . TL.null) $-		 [ f ns rm (op, SideL) pairParen-		 , x ns rm (op, SideR) pairParen ]-		where op = infixB SideL 2-instance Alternative Writer where-	empty = writeText "empty"-	Writer wl <|> Writer wr = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		wl ns rm (op, SideL) pairParen <> " | " <> wr ns rm (op, SideR) pairParen-		where op = infixB SideL 2-	many (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		w ns rm (op, SideL) pairParen <> "*"-		where op = infixN 9-	some (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		w ns rm (op, SideL) pairParen <> "+"-		where op = infixN 9-instance Sym_Rule Writer where-	rule n wr@(Writer w) = Writer $ \ns rm po pp ->-		case rm of-		 RuleMode_Ref ->-			pairIfNeeded pp po op $-			fromString n-			where op = infixN 10-		 RuleMode_Body -> w ns RuleMode_Ref po pp-		 RuleMode_Def ->-			TL.intercalate " "-			 [ fromString n-			 , "="-			 , unWriter (rule n wr) ns RuleMode_Body (infixN0, SideR) pp-			 ]-	arg n =-		Writer $ \_ns rm _po _pp ->-			case rm of-			 RuleMode_Ref  -> fromString n-			 RuleMode_Body -> ""-			 RuleMode_Def  -> ""-type instance Permutation Writer = Compose [] Writer-instance Sym_Permutation Writer where-	runPermutation (Compose []) = writeText "empty"-	runPermutation (Compose [Writer w]) = Writer w-	runPermutation (Compose l@(_:_)) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		TL.intercalate " & " $-		List.filter (not . TL.null) $-		(unWriter <$> l) <*> pure ns <*> pure rm <*> pure (op, SideL) <*> pure pairParen-		where op = infixB SideL 1-	toPermutation = Compose . pure-	toPermutationWithDefault _ = Compose . pure-instance Sym_RNC Writer where-	namespace _p _n = writeText ""-	element n (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		"element "<>TL.pack (show $ XML.prefixifyQName ns n)-		 <>" "<>w ns rm (op,SideR) pairBrace-		where op = infixN 10-	anyElem (XML.Namespace n) f = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		(if TL.null n then "" else n<>":") <>-		"* "<>w ns rm (op,SideR) pairBrace-		where-		op = infixN 0-		Writer w = f ""-	attribute n (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		"attribute "<>TL.pack (show $ XML.prefixifyQName ns n)-		 <>" "<>w ns rm (op,SideR) pairBrace-		where op = infixN 10-	try         = id-	fail        = writeText "fail"-	escapedText = writeText "text"-	text        = writeText "text"-	any         = writeText "any"-	choice []   = writeText "empty"-	choice [w]  = w-	choice l@(_:_) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		TL.intercalate " | " $-		(unWriter <$> l) <*> pure ns <*> pure rm <*> pure (op, SideL) <*> pure pairParen-		where op = infixB SideL 2-	option _x (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		w ns rm (op, SideL) pairParen <> "?"-		where op = infixN 9-	optional (Writer w) = Writer $ \ns rm po pp ->-		pairIfNeeded pp po op $-		w ns rm (op, SideL) pairParen <> "?"-		where op = infixN 9-	manySeq = coerceWriter . many-	someSeq = coerceWriter . some---- | 'Writer' returns a constant rendition.-writeText :: TL.Text -> Writer a-writeText t = Writer $ \_ns _rm po pp ->-	pairIfNeeded pp po op t-	where op = infixN 10
− Symantic/RNC/Write/Fixity.hs
@@ -1,110 +0,0 @@-module Symantic.RNC.Write.Fixity where--import Data.Bool-import Data.Eq (Eq(..))-import Data.Function ((.))-import Data.Int (Int)-import Data.Maybe (Maybe(..))-import Data.Ord (Ord(..))-import Data.Semigroup-import Data.String (String, IsString(..))-import Text.Show (Show(..))---- * Type 'Fixity'-data Fixity- =   Fixity1 Unifix- |   Fixity2 Infix- deriving (Eq, Show)---- ** Type 'Unifix'-data Unifix- =   Prefix  { unifix_precedence :: Precedence }- |   Postfix { unifix_precedence :: Precedence }- deriving (Eq, Show)---- ** Type 'Infix'-data Infix- =   Infix- {   infix_associativity :: Maybe Associativity- ,   infix_precedence    :: Precedence- } deriving (Eq, Show)--infixL :: Precedence -> Infix-infixL = Infix (Just AssocL)--infixR :: Precedence -> Infix-infixR = Infix (Just AssocR)--infixB :: Side -> Precedence -> Infix-infixB = Infix . Just . AssocB--infixN :: Precedence -> Infix-infixN = Infix Nothing--infixN0 :: Infix-infixN0 = infixN 0--infixN5 :: Infix-infixN5 = infixN 5---- | Given 'Precedence' and 'Associativity' of its parent operator,--- and the operand 'Side' it is in,--- return whether an 'Infix' operator--- needs to be enclosed by a 'Pair'.-isPairNeeded :: (Infix, Side) -> Infix -> Bool-isPairNeeded (po, lr) op =-	infix_precedence op < infix_precedence po-	|| infix_precedence op == infix_precedence po-	&& not associate-	where-	associate =-		case (lr, infix_associativity po) of-		 (_, Just AssocB{})   -> True-		 (SideL, Just AssocL) -> True-		 (SideR, Just AssocR) -> True-		 _ -> False---- | If 'isPairNeeded' is 'True',--- enclose the given 'IsString' by given 'Pair',--- otherwise returns the same 'IsString'.-pairIfNeeded ::- Semigroup s => IsString s =>- Pair -> (Infix, Side) -> Infix ->- s -> s-pairIfNeeded (o,c) po op s =-	if isPairNeeded po op-	then fromString o <> s <> fromString c-	else s---- * Type 'Precedence'-type Precedence = Int---- ** Class 'PrecedenceOf'-class PrecedenceOf a where-	precedence :: a -> Precedence-instance PrecedenceOf Fixity where-	precedence (Fixity1 uni) = precedence uni-	precedence (Fixity2 inf) = precedence inf-instance PrecedenceOf Unifix where-	precedence = unifix_precedence-instance PrecedenceOf Infix where-	precedence = infix_precedence---- * Type 'Associativity'-data Associativity- =   AssocL      -- ^ Associate to the left:  @a ¹ b ² c == (a ¹ b) ² c@- |   AssocR      -- ^ Associate to the right: @a ¹ b ² c == a ¹ (b ² c)@- |   AssocB Side -- ^ Associate to both sides, but to 'Side' when reading.- deriving (Eq, Show)---- ** Type 'Side'-data Side- =   SideL -- ^ Left- |   SideR -- ^ Right- deriving (Eq, Show)---- ** Type 'Pair'-type Pair = (String, String)-pairParen, pairBrace :: Pair-pairParen = ("(",")")-pairBrace = ("{","}")
− Symantic/RNC/Write/Namespaces.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE OverloadedStrings #-}-module Symantic.RNC.Write.Namespaces where--import Control.Applicative (Applicative(..), Alternative(..), (<$>))-import Control.Monad (Monad(..), forM, sequence)-import Data.Default.Class (Default(..))-import Data.Function (($), (.), id)-import Data.Functor (Functor(..))-import Data.Maybe (Maybe(..), maybe, isNothing)-import Data.Monoid (Monoid(..))-import Data.Semigroup (Semigroup(..))-import Text.Show (Show(..))-import Data.String (String)-import qualified Data.HashMap.Strict as HM-import qualified Data.HashSet as HS-import qualified Control.Monad.Trans.State.Strict as S--import qualified Symantic.XML as XML-import Symantic.RNC.Sym---- | Collect 'XML.Namespace's used and get them a dedicated prefix.-runNS :: forall a. [NS a] -> XML.Namespaces XML.NCName-runNS ns =-	namespaces-	 { XML.namespaces_prefixes =-		(`S.evalState` HS.empty) $-			let prefixesByNamespace =-				HM.delete "" $ -- NOTE: no prefix when there is no namespace.-				HM.update -- NOTE: no prefix when this is the default namespace.-				 (\p -> if isNothing p then Nothing else Just p)-				 (XML.namespaces_default namespaces) $-				XML.namespaces_prefixes namespaces in-			forM prefixesByNamespace $ \mp -> do-				usedPrefixes <- S.get-				let fp = maybe-					 (XML.freshNCName usedPrefixes)-					 (XML.freshifyNCName usedPrefixes)-					 mp-				S.modify' $ HS.insert fp-				return fp-	 }-	where-	namespaces :: XML.Namespaces (Maybe XML.NCName)-	namespaces = mconcat $ (`S.evalState` def) $ sequence $ unNS <$> ns--coerceNS :: NS a -> NS b-coerceNS = NS . unNS-{-# INLINE coerceNS #-}---- * Type 'NS'--- | Collect 'XML.Namespaces's and any prefixes associated with it,--- using 'State' to avoid recurring into already visited 'rule's.-newtype NS a = NS { unNS :: S.State State (XML.Namespaces (Maybe XML.NCName)) }---- ** Type 'State'-newtype State = State- { state_rules :: {-!-}(HS.HashSet String)- } deriving (Show)-instance Default State where-	def = State-	 { state_rules = HS.empty-	 }--instance Show (NS a) where-	showsPrec p = showsPrec p . runNS . pure-instance Semigroup (NS a) where-	NS x <> NS y = NS $ (<>) <$> x <*> y-instance Monoid (NS a) where-	mempty  = NS $ return mempty-	mappend = (<>)-instance Functor NS where-	fmap _f = coerceNS-instance Applicative NS where-	pure _ = mempty-	NS f <*> NS x = NS f <> NS x-	NS f <*  NS x = NS f <> NS x-	NS f  *> NS x = NS f <> NS x-instance Alternative NS where-	empty = mempty-	NS f <|> NS x = NS f <> NS x-	many = coerceNS-	some = coerceNS-instance Sym_Rule NS where-	rule n (NS ns) = NS $ do-		-- NOTE: avoid infinite loops-		-- by not reentering into already visited rules.-		st@State{..} <- S.get-		if HS.member n state_rules-		 then return mempty-		 else do-			S.put $ st{state_rules = HS.insert n state_rules}-			ns-	arg _n = mempty-type instance Permutation NS = NS-instance Sym_Permutation NS where-	runPermutation = coerceNS-	toPermutation = id-	toPermutationWithDefault _def = id-instance Sym_RNC NS where-	-- namespace n ns =-	-- 	NS $ return $ HM.singleton ns $ HS.singleton n-	namespace mp n =-		NS $ return $-		case mp of-		 Just p  -> XML.Namespaces{XML.namespaces_prefixes = HM.singleton n $ Just p, XML.namespaces_default = ""}-		 Nothing -> def{XML.namespaces_default = n}-	element XML.QName{..} (NS nsM) =-		NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =-			HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}-	attribute XML.QName{..} (NS nsM) =-		NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =-			HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}-	anyElem qNameSpace f =-		let NS nsM = f $ XML.NCName "*" in-		NS $ (<$> nsM) $ \ns -> ns{XML.namespaces_prefixes =-			HM.insert qNameSpace Nothing $ XML.namespaces_prefixes ns}-	try         = id-	fail        = mempty-	escapedText = mempty-	text        = mempty-	any         = mempty-	choice      = mconcat-	option _def = coerceNS-	optional    = coerceNS-	manySeq     = coerceNS-	someSeq     = coerceNS
− Symantic/XML.hs
@@ -1,11 +0,0 @@-module Symantic.XML- ( module Symantic.XML.Document- , readXML- , readFile- , writeXML- , writeXMLIndented- , writeFile- ) where-import Symantic.XML.Document-import Symantic.XML.Read-import Symantic.XML.Write
− Symantic/XML/Document.hs
@@ -1,432 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE StrictData #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Symantic.XML.Document- ( module Symantic.XML.Document- , TS.Tree(..)- , TS.Trees- , TS.tree0- ) where--import Control.Applicative (Alternative(..))-import Data.Bool-import Data.Char (Char)-import Data.Default.Class (Default(..))-import Data.Eq (Eq(..))-import Data.Foldable (Foldable(..), all)-import Data.Function (($), (.), id)-import Data.Functor (Functor(..), (<$>))-import Data.Hashable (Hashable(..))-import Data.Int (Int)-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe (Maybe(..), fromMaybe)-import Data.Monoid (Monoid(..))-import Data.Ord (Ord(..))-import Data.Semigroup (Semigroup(..))-import Data.Sequence (Seq)-import Data.String (String, IsString(..))-import GHC.Generics (Generic)-import Prelude ((+), error)-import System.IO (FilePath)-import Text.Show (Show(..), showsPrec, showChar, showParen, showString)-import qualified Data.Char.Properties.XMLCharProps as XC-import qualified Data.HashMap.Strict as HM-import qualified Data.HashSet as HS-import qualified Data.List as List-import qualified Data.Sequence as Seq-import qualified Data.Text.Lazy as TL-import qualified Data.TreeSeq.Strict as TS---- * Type 'XML'-type XML src = TS.Tree (Sourced src Node)-type XMLs src = Seq (XML src)---- | Unify two 'XMLs', merging border 'NodeText's if any.-union :: Semigroup (Sourced src EscapedText) => XMLs src -> XMLs src -> XMLs src-union x y =-	case (Seq.viewr x, Seq.viewl y) of-	 (xs Seq.:> x0, y0 Seq.:< ys) ->-		case (x0,y0) of-		 (  Tree0 (Sourced sx (NodeText tx))-		  , Tree0 (Sourced sy (NodeText ty)) ) ->-			xs `union`-			Seq.singleton (Tree0 $ (NodeText <$>) $ Sourced sx tx <> Sourced sy ty) `union`-			ys-		 _ -> x <> y-	 (Seq.EmptyR, _) -> y-	 (_, Seq.EmptyL) -> x--unions ::- Semigroup (Sourced src EscapedText) =>- Foldable f => f (XMLs src) -> XMLs src-unions = foldl' union mempty--pattern Tree0 :: a -> TS.Tree a-pattern Tree0 a <- TS.Tree a (null -> True)-	where Tree0 a = TS.Tree a Seq.empty---- ** Type 'Node'-data Node- =   NodeElem    QName         -- ^ Node with some 'NodeAttr' and then other 'Node's as children.- |   NodeAttr    QName         -- ^ Node with a 'NodeText' child.- |   NodePI      PName TL.Text -- ^ Leaf (except for @<?xml?>@ which has 'NodeAttr's.- |   NodeText    EscapedText   -- ^ Leaf.- |   NodeComment TL.Text       -- ^ Leaf.- |   NodeCDATA   TL.Text       -- ^ Leaf.- deriving (Eq, Ord, Show)---- ** Type 'EscapedText'-newtype EscapedText = EscapedText (Seq Escaped)- deriving (Eq, Ord, Show)--escapeText :: TL.Text -> EscapedText-escapeText s =-	EscapedText $-	case TL.span (`List.notElem` ("<>&'\""::String)) s of-	 (t, r) | TL.null t -> escape r-	        | otherwise -> EscapedPlain t Seq.<| escape r-	where-	escape t = case TL.uncons t of-	 Nothing -> mempty-	 Just (c, cs) -> escapeChar c Seq.<| et where EscapedText et = escapeText cs--escapeChar :: Char -> Escaped-escapeChar c =-	case c of-	 '<'  -> EscapedEntityRef entityRef_lt-	 '>'  -> EscapedEntityRef entityRef_gt-	 '&'  -> EscapedEntityRef entityRef_amp-	 '\'' -> EscapedEntityRef entityRef_apos-	 '"'  -> EscapedEntityRef entityRef_quot-	 _    -> EscapedPlain $ TL.singleton c--unescapeText :: EscapedText -> TL.Text-unescapeText (EscapedText et) = (`foldMap` et) $ \case- EscapedPlain t -> t- EscapedEntityRef EntityRef{..} -> entityRef_value- EscapedCharRef (CharRef c) -> TL.singleton c--instance Semigroup EscapedText where- EscapedText x <> EscapedText y =-		case (x,y) of-		 (xl Seq.:|> EscapedPlain xr, EscapedPlain yl Seq.:<|yr) ->-			(EscapedText $ xl Seq.|> EscapedPlain (xr<>yl)) <> EscapedText yr-		 _ -> EscapedText $ x <> y-instance Monoid EscapedText where-	mempty  = EscapedText mempty-	mappend = (<>)---- *** Type 'Escaped'--- | 'EscapedText' lexemes.-data Escaped-  =  EscapedPlain     TL.Text-  |  EscapedEntityRef EntityRef-  |  EscapedCharRef   CharRef-  deriving (Eq, Ord, Show)---- *** Type 'EntityRef'-data EntityRef = EntityRef- { entityRef_name  :: NCName- , entityRef_value :: TL.Text- } deriving (Eq, Ord, Show)--entityRef_lt, entityRef_gt, entityRef_amp, entityRef_quot, entityRef_apos :: EntityRef-entityRef_lt   = EntityRef (NCName "lt") "<"-entityRef_gt   = EntityRef (NCName "gt") ">"-entityRef_amp  = EntityRef (NCName "amp") "&"-entityRef_quot = EntityRef (NCName "quot") "\""-entityRef_apos = EntityRef (NCName "apos") "'"---- *** Type 'CharRef'-newtype CharRef = CharRef Char- deriving (Eq, Ord, Show)---- ** Type 'Name'-newtype Name = Name { unName :: TL.Text }- deriving (Eq, Ord, Hashable)-instance Show Name where-	showsPrec _p = showString . TL.unpack . unName-instance IsString Name where-	fromString s-	 | c:cs <- s-	 , XC.isXmlNameStartChar c-	 && all XC.isXmlNameChar cs-	 = Name (TL.pack s)-	 | otherwise = error $ "Invalid XML Name: "<>show s---- ** Type 'Namespace'-newtype Namespace = Namespace { unNamespace :: TL.Text }- deriving (Eq, Ord, Show, Hashable)-instance IsString Namespace where-	fromString s =-		if all (\c -> XC.isXmlChar c && c `List.notElem` ("'\"<&"::String)) s-		then Namespace (fromString s)-		else error $ "Invalid XML Namespace: "<>show s--xmlns_xml, xmlns_xmlns, xmlns_empty :: Namespace-xmlns_xml   = Namespace "http://www.w3.org/XML/1998/namespace"-xmlns_xmlns = Namespace "http://www.w3.org/2000/xmlns/"-xmlns_empty = Namespace ""---- * Type 'Namespaces'-data Namespaces prefix = Namespaces- { namespaces_prefixes :: (HM.HashMap Namespace prefix)- , namespaces_default  :: Namespace- } deriving (Show)-instance Default (Namespaces NCName) where-	def = Namespaces-	 { namespaces_prefixes = HM.fromList-		 [ (xmlns_xml  , "xml")-		 , (xmlns_xmlns, "xmlns")-		 ]-	 , namespaces_default  = ""-	 }-instance Default (Namespaces (Maybe NCName)) where-	def = Namespaces-	 { namespaces_prefixes = HM.fromList-		 [ (xmlns_xml  , Just "xml")-		 , (xmlns_xmlns, Just "xmlns")-		 ]-	 , namespaces_default  = ""-	 }-instance Semigroup (Namespaces NCName) where-	x <> y = Namespaces-	 { namespaces_prefixes = namespaces_prefixes x <> namespaces_prefixes y-	 , namespaces_default  = namespaces_default x-	 }-instance Semigroup (Namespaces (Maybe NCName)) where-	x <> y = Namespaces-	 { namespaces_prefixes = HM.unionWith (<|>) (namespaces_prefixes x) (namespaces_prefixes y)-	 , namespaces_default  = namespaces_default x-	 }-instance Monoid (Namespaces NCName) where-	mempty  = def-	mappend = (<>)-instance Monoid (Namespaces (Maybe NCName)) where-	mempty  = def-	mappend = (<>)--prefixifyQName :: Namespaces NCName -> QName -> PName-prefixifyQName Namespaces{..} QName{..} =-	PName-	 { pNameSpace =-		if qNameSpace == namespaces_default-		then Nothing-		else HM.lookup qNameSpace namespaces_prefixes-	 , pNameLocal = qNameLocal-	 }---- ** Type 'NCName'--- | Non-colonized name.-newtype NCName = NCName { unNCName :: TL.Text }- deriving (Eq, Ord, Hashable)-instance Show NCName where-	showsPrec _p = showString . TL.unpack . unNCName-instance IsString NCName where-	fromString s =-		fromMaybe (error $ "Invalid XML NCName: "<>show s) $-		ncName (TL.pack s)--ncName :: TL.Text -> Maybe NCName-ncName t =-	case TL.uncons t of-	 Just (c, cs)-	  | XC.isXmlNCNameStartChar c-	  , TL.all XC.isXmlNCNameChar cs-	  -> Just (NCName t)-	 _ -> Nothing--poolNCNames :: [NCName]-poolNCNames =-	[ NCName $ TL.pack ("ns"<>show i)-	| i <- [1 :: Int ..]-	]--freshNCName :: HS.HashSet NCName -> NCName-freshNCName ps = List.head $ poolNCNames List.\\ HS.toList ps--freshifyNCName :: HS.HashSet NCName -> NCName -> NCName-freshifyNCName ns (NCName n) =-	let ints = [1..] :: [Int] in-	List.head-	 [ fresh-	 | suffix <- mempty : (show <$> ints)-	 , fresh <- [ NCName $ n <> TL.pack suffix]-	 , not $ fresh `HS.member` ns-	 ]---- ** Type 'PName'--- | Prefixed name.-data PName = PName- { pNameSpace :: (Maybe NCName) -- ^ eg. Just "xml"- , pNameLocal :: NCName         -- ^ eg. "stylesheet"- } deriving (Eq, Ord, Generic)-instance Show PName where-	showsPrec p PName{pNameSpace=Nothing, ..} =-		showsPrec p pNameLocal-	showsPrec _p PName{pNameSpace=Just p, ..} =-		showsPrec 10 p .-		showChar ':' .-		showsPrec 10 pNameLocal-instance IsString PName where-	fromString "" = PName Nothing "" -- NOTE: NCName's fromString will raise an error.-	fromString s =-		case List.break (== ':') s of-		 (_, "")    -> PName Nothing $ fromString s-		 (p, local) -> PName (Just $ fromString p) (fromString $ List.drop 1 local)-instance Hashable PName--pName :: NCName -> PName-pName = PName Nothing-{-# INLINE pName #-}---- ** Type 'QName'--- | Qualified name.-data QName = QName- { qNameSpace :: Namespace -- ^ eg. "http://www.w3.org/1999/XSL/Transform"- , qNameLocal :: NCName    -- ^ eg. "stylesheet"- } deriving (Eq, Ord, Generic)-instance Show QName where-	showsPrec _p QName{..} =-		(if TL.null $ unNamespace qNameSpace then id-		else showChar '{' . showString (TL.unpack $ unNamespace qNameSpace) . showChar '}'-		) . showsPrec 10 qNameLocal-instance IsString QName where-	fromString "" = QName "" "" -- NOTE: NCName's fromString will raise an error.-	fromString full@('{':rest) =-		case List.break (== '}') rest of-		 (_, "")     -> error $ "Invalid XML Clark notation: "<>show full-		 (ns, local) -> QName (fromString ns) $ fromString $ List.drop 1 local-	fromString local = QName "" $ fromString local-instance Hashable QName--qName :: NCName -> QName-qName = QName (Namespace "")-{-# INLINE qName #-}---- * Type 'Sourced'-data Sourced src a- =   Sourced- {   source  :: src- , unSourced :: a- } deriving (Eq, Ord, Functor)-instance (Show src, Show a) => Show (Sourced src a) where-	showsPrec p Sourced{..} =-		showParen (p > 10) $-		showsPrec 11 unSourced .-		showString " @" . showsPrec 10 source-instance Semigroup a => Semigroup (Sourced (FileSource Offset) a) where-	(<>)-	 (Sourced rx@(FileRange xf xb xe :|  xs) x)-	 (Sourced    (FileRange yf yb ye :| _ys) y)-	 | xf == yf && xe == yb = Sourced (FileRange xf xb ye :| xs) $ x<>y-	 | otherwise = Sourced rx (x<>y)-{--instance (FromPad a, Semigroup a) => Semigroup (Sourced (FileSource LineCol) a) where-	(<>)-	 (Sourced rx@(FileRange xf xb xe :|  xs) x)-	 (Sourced    (FileRange yf yb ye :| _ys) y)-	 | xf == yf  = Sourced (FileRange xf xb ye :| xs) $ x<>fromPad (LineColumn l c)<>y-	 | otherwise = Sourced rx (x<>y)-	where-	l = lineNum yb - lineNum xe-	c = colNum  yb - colNum (if l <= 0 then xe else xb)---- ** Class 'FromPad'-class FromPad a where-	fromPad :: LineColumn -> a-instance FromPad T.Text where-	fromPad LineColumn{..} =-		T.replicate lineNum   "\n" <>-		T.replicate colNum " "-instance FromPad TL.Text where-	fromPad LineColumn{..} =-		TL.replicate (fromIntegral lineNum)   "\n" <>-		TL.replicate (fromIntegral colNum) " "-instance FromPad EscapedText where-	fromPad = EscapedText . pure . fromPad-instance FromPad Escaped where-	fromPad = EscapedPlain . fromPad--}---- ** Class 'NoSource'-class NoSource src where-	noSource :: src-instance Default pos => NoSource (FileSource pos) where-	noSource = noSource :| []-instance Default pos => NoSource (FileRange pos) where-	noSource = FileRange "" def def-instance NoSource Offset where-	noSource = Offset def-{--instance (FromPad a, Semigroup a, Monoid a) => Monoid (Sourced a) where-	mempty  = sourced0 mempty-	mappend = (<>)--}--notSourced :: NoSource src => a -> Sourced src a-notSourced = Sourced noSource---- * Type 'FileSource'-type FileSource pos = NonEmpty (FileRange pos)---- ** Type 'FileSourced'-type FileSourced = Sourced (FileSource Offset)---- ** Type 'FileRange'-data FileRange pos- =   FileRange- {   fileRange_file  :: FilePath- ,   fileRange_begin :: pos- ,   fileRange_end   :: pos- } deriving (Eq, Ord)-instance Default (FileRange Offset) where-	def = FileRange "" def def-instance Default (FileRange LineColumn) where-	def = FileRange "" def def-instance Show (FileRange Offset) where-	showsPrec _p FileRange{..} =-		showString fileRange_file .-		showChar '@' . showsPrec 10 fileRange_begin .-		showChar '-' . showsPrec 10 fileRange_end-instance Show (FileRange LineColumn) where-	showsPrec _p FileRange{..} =-		showString fileRange_file .-		showChar '#' . showsPrec 10 fileRange_begin .-		showChar '-' . showsPrec 10 fileRange_end---- *** Type 'Offset'-newtype Offset = Offset Int- deriving (Eq, Ord)-instance Show Offset where-	showsPrec p (Offset o) = showsPrec p o-instance Default Offset where-	def = Offset 0-instance Semigroup Offset where-	Offset x <> Offset y = Offset (x+y)-instance Monoid Offset where-	mempty  = def-	mappend = (<>)---- *** Type 'LineColumn'--- | Absolute text file position.-data LineColumn = LineColumn- { lineNum :: {-# UNPACK #-} Offset- , colNum  :: {-# UNPACK #-} Offset- } deriving (Eq, Ord)-instance Default LineColumn where-	def = LineColumn def def-instance Show LineColumn where-	showsPrec _p LineColumn{..} =-		showsPrec 11 lineNum .-		showChar ':' .-		showsPrec 11 colNum--filePos1 :: LineColumn-filePos1 = def
− Symantic/XML/Read.hs
@@ -1,478 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Symantic.XML.Read- ( module Symantic.XML.Read.Parser- , module Symantic.XML.Read- ) where--import Control.Arrow (left)-import Control.Applicative (Applicative(..), Alternative(..))-import Control.Monad (Monad(..), void, unless, forM, join)-import Data.Bool-import Data.Char (Char)-import Data.Default.Class (Default(..))-import Data.Either (Either(..))-import Data.Eq (Eq(..))-import Data.Foldable (Foldable(..))-import Data.Function (($), (.), const)-import Data.Functor ((<$>), (<$))-import Data.Maybe (Maybe(..), maybe)-import Data.Monoid (Monoid(..))-import Data.Ord (Ord(..))-import Data.Semigroup (Semigroup(..))-import Data.String (String)-import Data.TreeSeq.Strict (Tree(..))-import Data.Tuple (snd)-import Prelude (Num(..), Enum(..), Bounded(..), Integer, toInteger)-import System.IO (FilePath, IO)-import Text.Megaparsec ((<?>))-import Text.Show (Show(..))-import qualified Control.Exception as Exn-import qualified Control.Monad.Trans.Reader as R-import qualified Data.ByteString.Lazy as BSL-import qualified Data.Char as Char-import qualified Data.Char.Properties.XMLCharProps as XC-import qualified Data.HashMap.Strict as HM-import qualified Data.List as List-import qualified Data.Sequence as Seq-import qualified Data.Text.Encoding.Error as TL-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Encoding as TL-import qualified Data.TreeSeq.Strict as TS-import qualified System.IO.Error as IO-import qualified Text.Megaparsec as P-import qualified Text.Megaparsec.Char as P--import Symantic.XML.Document hiding (XML, XMLs)-import Symantic.XML.Read.Parser--readXML :: FilePath -> TL.Text -> Either (P.ParseErrorBundle TL.Text Error) XMLs-readXML filePath stateInput =-	snd $-	P.runParser'-	 (R.runReaderT p_document def)-	 P.State-	 { P.stateInput-	 , P.stateOffset = 0-	 , P.statePosState = P.PosState-		 { P.pstateInput      = stateInput-		 , P.pstateOffset     = 0-		 , P.pstateSourcePos  = P.initialPos filePath-		 , P.pstateTabWidth   = P.pos1-		 , P.pstateLinePrefix = ""-		 }-	 }--readFile :: FilePath -> IO (Either ErrorRead TL.Text)-readFile fp =-	(left ErrorRead_Unicode . TL.decodeUtf8' <$> BSL.readFile fp)-	`Exn.catch` \e ->-		if IO.isAlreadyInUseError e-		|| IO.isDoesNotExistError e-		|| IO.isPermissionError   e-		then return $ Left $ ErrorRead_IO e-		else IO.ioError e---- * Type 'ErrorRead'-data ErrorRead- =   ErrorRead_IO IO.IOError- |   ErrorRead_Unicode TL.UnicodeException- deriving (Show)---- * Document-p_document :: P.Tokens s ~ TL.Text => Parser Error s XMLs-p_document = do-	ps <- p_prolog-	e  <- p_Element-	ms <- P.many p_Misc-	P.eof-	return (ps <> pure e <> join (Seq.fromList ms))---- ** Prolog-p_prolog :: P.Tokens s ~ TL.Text => Parser Error s XMLs-p_prolog = do-	xmlDecl <- P.option Seq.empty $ pure <$> p_XMLDecl-	ms <- P.many p_Misc-	return (xmlDecl <> join (Seq.fromList ms))---- ** Misc-p_Misc :: P.Tokens s ~ TL.Text => Parser Error s XMLs-p_Misc =-	P.try (pure <$> p_Comment)-	 <|> P.try (pure <$> p_PI)-	 <|> pure <$> p_S---- ** XMLDecl-p_XMLDecl :: P.Tokens s ~ TL.Text => Parser Error s XML-p_XMLDecl = P.label "XMLDecl" $ do-	Sourced src as <- p_Sourced $ P.between (P.string "<?xml") (P.string "?>") $ do-		vi <- pure <$> p_VersionInfo-		ed <- P.option Seq.empty $ pure <$> p_EncodingDecl-		sd <- P.option Seq.empty $ pure <$> p_SDDecl-		p_Spaces-		return $ vi <> ed <> sd-	return $ Tree (Sourced src $ NodePI "xml" "") as--p_VersionInfo :: P.Tokens s ~ TL.Text => Parser Error s XML-p_VersionInfo = P.label "VersionInfo" $ do-	Sourced c v <- p_Sourced $ do-		P.try (() <$ p_Spaces1 <* P.string "version")-		p_Eq-		p_quoted $ const $ p_Sourced $-			(<>)-			 <$> P.string "1."-			 <*> P.takeWhile1P Nothing Char.isDigit-	return $ Tree (Sourced c $ NodeAttr "version") $ pure $-		TS.tree0 $ NodeText . EscapedText . pure . EscapedPlain <$> v--p_EncodingDecl :: P.Tokens s ~ TL.Text => Parser Error s XML-p_EncodingDecl = P.label "EncodingDecl" $ do-	Sourced c v <- p_Sourced $ do-		P.try (() <$ p_Spaces1 <* P.string "encoding")-		p_Eq-		p_quoted $ const $ p_Sourced p_EncName-	return $ Tree (Sourced c $ NodeAttr "encoding") $ pure $-		TS.tree0 $ NodeText . EscapedText . pure . EscapedPlain <$> v--p_EncName :: P.Tokens s ~ TL.Text => Parser Error s TL.Text-p_EncName = P.label "EncName" $ do-	P.notFollowedBy (P.satisfy $ not . isAlpha)-	P.takeWhile1P Nothing $ \c ->-		isAlpha c || Char.isDigit c ||-		c=='.' || c=='_' || c=='-'-	where isAlpha c = Char.isAsciiLower c || Char.isAsciiUpper c---- *** SDDecl-p_SDDecl :: P.Tokens s ~ TL.Text => Parser Error s XML-p_SDDecl = P.label "SDDecl" $ do-	p_SourcedBegin $ do-		Sourced ca () <- P.try (p_Sourced $ () <$ p_Spaces1 <* P.string "standalone")-		p_Eq-		v <- p_quoted $ const $ p_Sourced $ P.string "yes" <|> P.string "no"-		return $ Tree (Sourced ca $ NodeAttr "standalone") $ pure $-			TS.tree0 $ NodeText . EscapedText . pure . EscapedPlain <$> v---- ** CharData-p_CharData :: P.Tokens s ~ TL.Text => Parser e s EscapedText-p_CharData =-	escapeText-	 <$> p_until1 (\c -> XC.isXmlChar c && c/='<' && c/='&') (']',"]>")---- ** Comment-p_Comment :: P.Tokens s ~ TL.Text => Parser Error s XML-p_Comment = p_SourcedBegin $ P.string "<!--" *> p_Comment__-p_Comment_ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_Comment_ = P.string "--" *> p_Comment__-p_Comment__:: P.Tokens s ~ TL.Text => Parser Error s XML-p_Comment__ = P.label "Comment" $ do-	c <- p_until XC.isXmlChar ('-', "-")-	void $ P.string "-->"-	cell <- p_SourcedEnd-	return $ TS.tree0 (cell $ NodeComment c)---- ** CDATA-p_CDSect :: P.Tokens s ~ TL.Text => Parser Error s XML-p_CDSect = p_SourcedBegin $ P.string "<![CDATA[" *> p_CDSect__-p_CDSect_ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_CDSect_ = P.string "[CDATA[" *> p_CDSect__-p_CDSect__ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_CDSect__ = P.label "CDSect" $ do-	c <- p_until XC.isXmlChar (']', "]>")-	void $ P.string "]]>"-	cell <- p_SourcedEnd-	return $ TS.tree0 $ cell $ NodeCDATA c---- ** PI-p_PI :: P.Tokens s ~ TL.Text => Parser Error s XML-p_PI = p_SourcedBegin $ P.string "<?" *> p_PI__-p_PI_ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_PI_ = P.char '?' *> p_PI__-p_PI__ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_PI__ = P.label "PI" $ do-	n <- p_PITarget-	v <- P.option "" $ P.try $ p_Spaces1 *> p_until XC.isXmlChar ('?', ">")-	void $ P.string "?>"-	cell <- p_SourcedEnd-	return $ TS.tree0 $ cell $ NodePI n v-p_PITarget :: P.Tokens s ~ TL.Text => Parser Error s PName-p_PITarget = do-	n <- p_PName-	case n of-	 PName{pNameSpace=Nothing, pNameLocal=NCName l}-	  | "xml" == TL.toLower l -> p_error $ Error_PI_reserved n-	 _ -> return n---- ** Element-p_Element :: P.Tokens s ~ TL.Text => Parser Error s XML-p_Element = p_SourcedBegin $ (P.char '<' *> p_Element_)-p_Element_ :: P.Tokens s ~ TL.Text => Parser Error s XML-p_Element_ = P.label "Element" p_STag---- *** STag-p_STag :: P.Tokens s ~ TL.Text => Parser Error s XML-p_STag = do-	n  <- p_PName-	as <- P.many $ P.try $ p_Spaces1 *> p_Attribute-	p_Spaces-	ro <- R.ask-	elemNS :: HM.HashMap NCName Namespace <--		(HM.fromList . List.concat <$>) $ forM as $ \case-		 Sourced _ (PName{..}, Sourced _ av)-		  | ns <- Namespace $ unescapeText av-		  , Nothing        <- pNameSpace-		  , NCName "xmlns" <- pNameLocal ->-			-- NOTE: default namespace declaration.-			case ns of-			 _ |  ns == xmlns_xml   -- DOC: it MUST NOT be declared as the default namespace-			   || ns == xmlns_xmlns -- DOC: it MUST NOT be declared as the default namespace-			   -> p_error $ Error_Namespace_reserved ns-			 _ -> return [(NCName "" , ns)]-		  | ns <- Namespace $ unescapeText av-		  , Just (NCName "xmlns") <- pNameSpace ->-			-- NOTE: namespace prefix declaration.-			case unNCName pNameLocal of-			 "xml" -- DOC: It MAY, but need not, be declared,-			       -- and MUST NOT be bound to any other namespace name.-			       | ns == xmlns_xml -> return []-			       | otherwise -> p_error $ Error_Namespace_reserved_prefix pNameLocal-			 "xmlns" -- DOC: It MUST NOT be declared-			         -> p_error $ Error_Namespace_reserved_prefix pNameLocal-			 local | "xml" <- TL.toLower $ TL.take 3 local -> return []-			       -- DOC: All other prefixes beginning with the three-letter-			       -- sequence x, m, l, in any case combination, are reserved.-			       -- This means that: processors MUST NOT treat them as fatal errors.-			 _ |  ns == xmlns_xml   -- DOC: Other prefixes MUST NOT be bound to this namespace name.-			   || ns == xmlns_xmlns -- DOC: Other prefixes MUST NOT be bound to this namespace name.-			   -> p_error $ Error_Namespace_reserved ns-			 _ -> return [(pNameLocal, ns)]-		  | otherwise -> return []-	let scopeNS = elemNS <> reader_ns_scope ro-	let defaultNS = HM.lookupDefault (reader_ns_default ro) (NCName "") scopeNS-	let lookupNamePrefix prefix =-		maybe (p_error $ Error_Namespace_prefix_unknown prefix) return $-		HM.lookup prefix scopeNS-	elemName :: QName <--		-- NOTE: expand element's QName.-		case pNameSpace n of-		 Nothing -> return QName{qNameSpace=defaultNS, qNameLocal=pNameLocal n}-		  -- DOC: If there is a default namespace declaration in scope,-		  -- the expanded name corresponding to an unprefixed element name-		  -- has the URI of the default namespace as its namespace name.-		 Just prefix-		  | NCName "xmlns" <- prefix ->-			-- DOC: Element names MUST NOT have the prefix xmlns.-			p_error $ Error_Namespace_reserved_prefix prefix-		  | otherwise -> do-			ns <- lookupNamePrefix prefix-			return QName{qNameSpace=ns, qNameLocal=pNameLocal n}-	elemAttrs :: [FileSourced (QName, FileSourced EscapedText)] <--		-- NOTE: expand attributes' PName into QName.-		forM as $ \s@Sourced{unSourced=(an, av)} -> do-			ns <- maybe (return "") lookupNamePrefix $ pNameSpace an-			let qn = QName{qNameSpace=ns, qNameLocal=pNameLocal an}-			return s{unSourced=(qn, av)}-	-- NOTE: check for attribute collision.-	let attrsByQName :: HM.HashMap QName [FileSourced (QName, FileSourced EscapedText)] =-		HM.fromListWith (<>) $ (<$> elemAttrs) $ \a@(Sourced _c (an, _av)) -> (an, [a])-	case HM.toList $ HM.filter (\x -> length x > 1) attrsByQName of-	 (an, _):_ -> p_error $ Error_Attribute_collision an-	 _ -> return ()-	elemAttrsXML :: XMLs <- (Seq.fromList <$>) $-		forM elemAttrs $ \(Sourced sa (an, av)) -> do-			return $ TS.Tree (Sourced sa $ NodeAttr an) $-				pure $ TS.tree0 $ NodeText <$> av-	content :: XMLs <--		elemAttrsXML <$ P.string "/>" <|>-		R.local-		 (const ro-			 { reader_ns_scope   = scopeNS-			 , reader_ns_default = defaultNS-			 })-		 ((elemAttrsXML <>) <$ P.char '>' <*> p_content <* p_ETag elemName)-	cell <- p_SourcedEnd-	return $ Tree (cell $ NodeElem elemName) content---- *** Attribute-p_Attribute :: P.Tokens s ~ TL.Text => Parser Error s (FileSourced (PName, FileSourced EscapedText))-p_Attribute = p_Sourced $ (,) <$> p_PName <* p_Eq <*> p_AttValue--p_AttValue :: P.Tokens s ~ TL.Text => Parser Error s (FileSourced EscapedText)-p_AttValue = P.label "AttValue" $ p_quoted p_AttValueText--p_AttValueText :: P.Tokens s ~ TL.Text => Char -> Parser Error s (FileSourced EscapedText)-p_AttValueText q = p_Sourced $-	EscapedText . Seq.fromList <$> P.many-	 ( p_Reference-	 <|> EscapedPlain <$> P.takeWhile1P Nothing (\c ->-		XC.isXmlChar c &&-		c `List.notElem` (q:"<&'\">"))-	 <|> EscapedEntityRef entityRef_gt <$ P.char '>'-	 <|> (if q == '\''-		then EscapedEntityRef entityRef_quot <$ P.char '"'-		else EscapedEntityRef entityRef_apos <$ P.char '\'')-	 )---- * content-p_content :: P.Tokens s ~ TL.Text => Parser Error s XMLs-p_content =-	(Seq.fromList <$>) $ P.many $-		(p_SourcedBegin $ do-			P.try $ P.char '<' *> P.notFollowedBy (P.char '/')-			p_Element_ <|> p_PI_ <|> (P.char '!' *> (p_Comment_ <|> p_CDSect_))-		)-		<|> ((tree0 <$>) $ p_Sourced $ NodeText . mconcat-			 <$> P.some (p_CharData <|> EscapedText . pure <$> p_Reference))---- *** ETag-p_ETag :: P.Tokens s ~ TL.Text => QName -> Parser Error s ()-p_ETag expected = do-	got <- P.string "</" *> p_QName <* p_Spaces <* P.char '>'-	unless (got == expected) $-		p_error $ Error_Closing_tag_unexpected got expected---- * Name-p_Name :: P.Tokens s ~ TL.Text => Parser Error s Name-p_Name = P.label "Name" $-	Name-	 <$  P.notFollowedBy (P.satisfy $ not . XC.isXmlNameStartChar)-	 <*> P.takeWhile1P Nothing XC.isXmlNameChar---- * PName-p_PName :: P.Tokens s ~ TL.Text => Parser e s PName-p_PName = P.label "PName" $ do-	n <- p_NCName-	s <- P.optional $ P.try $ P.char ':' *> p_NCName-	return $ case s of-	 Nothing -> PName{pNameSpace=Nothing, pNameLocal=n}-	 Just l  -> PName{pNameSpace=Just n , pNameLocal=l}---- * QName-p_QName :: P.Tokens s ~ TL.Text => Parser Error s QName-p_QName = P.label "QName" $ do-	n <- p_NCName-	s <- P.optional $ P.try $ P.char ':' *> p_NCName-	Reader{..} <- R.ask-	case s of-	 Nothing -> return QName{qNameSpace=reader_ns_default, qNameLocal=n}-	 Just l ->-		case HM.lookup n reader_ns_scope of-		 Nothing -> p_error $ Error_Namespace_prefix_unknown n-		 Just ns -> return QName{qNameSpace=ns, qNameLocal=l}---- ** NCName-p_NCName :: P.Tokens s ~ TL.Text => Parser e s NCName-p_NCName = P.label "NCName" $-	NCName-	 <$  P.notFollowedBy (P.satisfy $ not . XC.isXmlNCNameStartChar)-	 <*> P.takeWhile1P Nothing XC.isXmlNCNameChar---- * Reference-p_Reference :: P.Tokens s ~ TL.Text => Parser Error s Escaped-p_Reference =-	EscapedCharRef <$> p_CharRef <|>-	EscapedEntityRef <$> p_EntityRef---- ** EntityRef-p_EntityRef :: P.Tokens s ~ TL.Text => Parser Error s EntityRef-p_EntityRef = P.label "EntityRef" $ do-	ref <- P.char '&' *> p_NCName <* P.char ';'-	EntityRef ref <$> lookupEntityRef ref-	where-	lookupEntityRef (NCName "lt"  ) = pure "<"-	lookupEntityRef (NCName "gt"  ) = pure ">"-	lookupEntityRef (NCName "amp" ) = pure "&"-	lookupEntityRef (NCName "apos") = pure "'"-	lookupEntityRef (NCName "quot") = pure "\""-	lookupEntityRef n = p_error $ Error_EntityRef_unknown n---- ** CharRef-p_CharRef :: P.Tokens s ~ TL.Text => Parser Error s CharRef-p_CharRef = P.label "CharRef" $-	do-		ref <- readHexadecimal-		 <$  P.string "&#x"-		 <*> P.some P.hexDigitChar-		 <*  P.char ';'-		check ref-	<|> do-		ref <- readDecimal-		 <$  P.string "&#"-		 <*> P.some P.digitChar-		 <*  P.char ';'-		check ref-	where-	check i =-		let c = toEnum (fromInteger i) in-		if i <= toInteger (fromEnum (maxBound::Char))-		&& XC.isXmlChar c-		then pure $ CharRef c-		else p_error $ Error_CharRef_invalid i--readInt :: Integer -> String -> Integer-readInt base digits =-	sign * List.foldl' acc 0 (List.concatMap digToInt digits1)-	where-	acc q r = q*base + r-	(sign, digits1) =-		case digits of-		 [] -> (1, digits)-		 c:ds | c == '-'  -> (-1, ds)-		      | c == '+'  -> ( 1, ds)-		      | otherwise -> ( 1, digits)-	ord = toInteger . Char.ord-	digToInt c-	 | Char.isDigit c      = [ord c - ord '0']-	 | Char.isAsciiLower c = [ord c - ord 'a' + 10]-	 | Char.isAsciiUpper c = [ord c - ord 'A' + 10]-	 | otherwise           = []--readDecimal :: String -> Integer-readDecimal = readInt 10--readHexadecimal :: String -> Integer-readHexadecimal = readInt 16---- * Char-p_Char :: P.Tokens s ~ TL.Text => Parser e s Char-p_Char = P.label "Char" $ P.satisfy XC.isXmlCharCR <|> p_CRLF-{-# INLINE p_Char #-}---- ** Space--- | Map '\r' and '\r\n' to '\n'.-p_CRLF :: P.Tokens s ~ TL.Text => Parser e s Char-p_CRLF = P.label "CRLF" $-	P.char '\r' *> P.option '\n' (P.char '\n')--p_Space :: P.Tokens s ~ TL.Text => Parser e s Char-p_Space = P.label "Space" $-	P.satisfy XC.isXmlSpaceCharCR <|> p_CRLF-{-# INLINE p_Space #-}--p_Spaces :: P.Tokens s ~ TL.Text => Parser e s ()-p_Spaces = P.label "Spaces" $-	void $ P.takeWhileP Nothing XC.isXmlSpaceChar-{-# INLINE p_Spaces #-}--p_S :: P.Tokens s ~ TL.Text => Parser Error s XML-p_S = P.label "Spaces" $-	(\ts -> TS.tree0 (NodeText . EscapedText . pure . EscapedPlain . TL.concat <$> ts))-	 <$> p_Sourced (P.some $-		P.takeWhile1P Nothing XC.isXmlSpaceCharCR <|>-		TL.singleton <$> p_CRLF)--p_Spaces1 :: P.Tokens s ~ TL.Text => Parser e s ()-p_Spaces1 = P.label "Spaces1" $-	void $ P.takeWhile1P Nothing XC.isXmlSpaceChar-{-# INLINE p_Spaces1 #-}---- * Eq-p_separator :: P.Tokens s ~ TL.Text => Char -> Parser e s ()-p_separator c = P.try (() <$ p_Spaces <* P.char c) <* p_Spaces <?> [c]--p_Eq :: P.Tokens s ~ TL.Text => Parser e s ()-p_Eq = p_separator '=' <?> "Eq"
− Symantic/XML/Read/Parser.hs
@@ -1,240 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE StrictData #-}-{-# LANGUAGE TypeFamilies #-}-module Symantic.XML.Read.Parser where--import Control.Applicative (Applicative(..), Alternative(..))-import Control.Monad (Monad(..))-import Data.Bool-import Data.Char (Char)-import Data.Default.Class (Default(..))-import Data.Eq (Eq(..))-import Data.Function (($), (.))-import Data.Functor ((<$>))-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe (Maybe(..))-import Data.Ord (Ord(..))-import Data.String (IsString)-import Prelude (Integer)-import Text.Show (Show(..))-import qualified Control.Monad.Trans.Reader as R-import qualified Data.HashMap.Strict as HM-import qualified Data.Set as Set-import qualified Data.Text.Lazy as TL-import qualified Text.Megaparsec as P-import qualified Text.Megaparsec.Char as P--import Symantic.XML.Document hiding (XML, XMLs)-import qualified Symantic.XML.Document as XML---- | Specify |XML.XML|'s 'src' type parameter for parsing.-type XML = XML.XML (FileSource Offset)--- | Specify |XML.XMLs|'s 'src' type parameter for parsing.-type XMLs = XML.XMLs (FileSource Offset)---- * Type 'Parser'--- | Convenient alias.-type Parser   e s a =-     Parsable e s a =>-     R.ReaderT Reader (P.Parsec e s) a---- ** Type 'Parsable'-type Parsable e s a =- ( P.Stream s- , P.Token s ~ Char- , Ord e- , IsString (P.Tokens s)- , P.ShowErrorComponent e- )---- ** Type 'Reader'-data Reader = Reader- { reader_source     :: FileSource Offset- , reader_ns_scope   :: HM.HashMap NCName Namespace- , reader_ns_default :: Namespace- } deriving (Show)-instance Default Reader where-	def = Reader-	 { reader_source     = pure def-	 , reader_ns_scope   = HM.fromList-		 [ ("xml"  , xmlns_xml)-		 , ("xmlns", xmlns_xmlns)-		 ]-	 , reader_ns_default = ""-	 }--p_Offset :: Parser e s Offset-p_Offset = Offset <$> P.getOffset-{-# INLINE p_Offset #-}--p_Sourced :: Parser e s a -> Parser e s (Sourced (FileSource Offset) a)-p_Sourced pa = do-	Reader{reader_source} <- R.ask-	b <- P.getParserState-	let fileRange_file = P.sourceName $ P.pstateSourcePos $ P.statePosState b-	let fileRange_begin = Offset $ P.stateOffset b-	a <- pa-	e <- P.getParserState-	let fileRange_end = Offset $ P.stateOffset e-	return $ Sourced (setSource FileRange{..} reader_source) a--setSource :: FileRange pos -> FileSource pos -> FileSource pos-setSource fileRange (_curr:|next) = fileRange :| next---- | Like 'p_Sourced' but uncoupled (through the use of 'p_SourcedEnd') for more flexibility.-p_SourcedBegin :: Parser e s a -> Parser e s a-p_SourcedBegin pa = do-	b <- P.getParserState-	let fileRange_file  = P.sourceName $ P.pstateSourcePos $ P.statePosState b-	let fileRange_begin = Offset $ P.stateOffset b-	let fileRange_end   = fileRange_begin-	(`R.local` pa) $ \ro@Reader{..} ->-		ro{ reader_source = setSource FileRange{..} reader_source }---- | WARNING: Only to be used within a 'p_SourcedBegin'.-p_SourcedEnd :: Parser e s (a -> Sourced (FileSource Offset) a)-p_SourcedEnd = do-	Reader{..} <- R.ask-	e <- P.getParserState-	let fileRange_end = Offset $ P.stateOffset e-	return $ Sourced $-		 (\(curr:|path) -> curr{fileRange_end}:|path)-		 reader_source--{---- ** Type 'StreamSourced'--- | Wrap 'TL.Text' to have a 'P.Stream' instance--- whose 'P.advance1' method abuses the tab width state--- to instead pass the line indent.--- This in order to report correct 'P.SourcePos'--- when parsing a 'Sourced' containing newlines.-newtype StreamSourced = StreamSourced { unStreamSourced :: TL.Text }- deriving (IsString,Eq,Ord)-instance P.Stream StreamSourced where-	type Token  StreamSourced = Char-	type Tokens StreamSourced = TL.Text-	take1_       (StreamSourced t) = (StreamSourced <$>) <$> P.take1_ t-	takeN_     n (StreamSourced t) = (StreamSourced <$>) <$> P.takeN_ n t-	takeWhile_ f (StreamSourced t) = StreamSourced <$> P.takeWhile_ f t-	tokensToChunk _s = P.tokensToChunk (Proxy::Proxy TL.Text)-	chunkToTokens _s = P.chunkToTokens (Proxy::Proxy TL.Text)-	chunkLength   _s = P.chunkLength   (Proxy::Proxy TL.Text)-	{--	advance1 _s indent (P.SourcePos n line col) c =-		case c of-		 '\n' -> P.SourcePos n (line <> P.pos1) indent-		 _    -> P.SourcePos n line (col <> P.pos1)-	advanceN s indent = TL.foldl' (P.advance1 s indent)-	-}---- | Wrapper around |P.runParser'|--- to use given 'Sourced' as starting position.-runParserOnSourced ::- Parsable e StreamSourced a =>- Parser e StreamSourced a ->- Sourced FileSource TL.Text ->- Either (P.ParseError (P.Token StreamSourced) e) a-runParserOnSourced p (Sourced (FileRange inp bp _ep :| path) s) =-	snd $-	P.runParser' (R.runReaderT p ro <* P.eof)-	 P.State-	 { P.stateInput    = StreamSourced s-	 , P.statePos      = pure $ P.SourcePos inp (P.mkPos $ filePos_line bp) indent-	 , P.stateTabWidth = indent-	 , P.stateTokensProcessed = 0-	 }-	where-	indent = P.mkPos $ filePos_column bp-	ro     = def{ reader_source = fromMaybe (pure def) $ nonEmpty path }--}---- * Type 'Error'-data Error- =   Error_CharRef_invalid Integer-     -- ^ Well-formedness constraint: Legal Character.-     ---     -- Characters referred to using character references MUST match the production for Char.- |   Error_EntityRef_unknown NCName-     -- ^ Well-formedness constraint: Entity Declared-     ---     -- In a document without any DTD, a document with only an internal DTD-     -- subset which contains no parameter entity references, or a document-     -- with " standalone='yes' ", for an entity reference that does not occur-     -- within the external subset or a parameter entity, the Name given in the-     -- entity reference MUST match that in an entity declaration that does not-     -- occur within the external subset or a parameter entity, except that-     -- well-formed documents need not declare any of the following entities:-     -- amp, lt, gt, apos, quot. The declaration of a general entity MUST-     -- precede any reference to it which appears in a default value in an-     -- attribute-list declaration.-     ---     -- Note that non-validating processors are not obligated to read and-     -- process entity declarations occurring in parameter entities or in the-     -- external subset; for such documents, the rule that an entity must be-     -- declared is a well-formedness constraint only if standalone='yes'.- |   Error_Closing_tag_unexpected QName QName-     -- ^ Well-formedness constraint: Element Type Match.-     ---     -- The Name in an element's end-tag MUST match the element type in the start-tag.- |   Error_Attribute_collision QName-     -- ^ Well-formedness constraint: Unique Att Spec.-     ---     -- An attribute name MUST NOT appear more than once in the same start-tag or empty-element tag.- |   Error_PI_reserved PName-     -- ^ The target names " XML ", " xml ", and so on are reserved for standardization.- |   Error_Namespace_prefix_unknown NCName-     -- ^ Namespace constraint: Prefix Declared-     ---     -- The namespace prefix, unless it is xml or xmlns, MUST have been declared in a namespace declaration attribute in either the start-tag of the element where the prefix is used or in an ancestor element (i.e., an element in whose content the prefixed markup occurs). - |   Error_Namespace_empty NCName-     -- ^ Namespace constraint: No Prefix Undeclaring-     ---     -- In a namespace declaration for a prefix (i.e., where the NSAttName is a PrefixedAttName), the attribute value MUST NOT be empty.- |   Error_Namespace_reserved Namespace- |   Error_Namespace_reserved_prefix NCName-     -- ^ Namespace constraint: Reserved Prefixes and Namespace Names-     ---     -- The prefix xml is by definition bound to the namespace name-     -- http://www.w3.org/XML/1998/namespace. It MAY, but need not, be-     -- declared, and MUST NOT be bound to any other namespace name. Other-     -- prefixes MUST NOT be bound to this namespace name, and it MUST NOT be-     -- declared as the default namespace.-     ---     -- The prefix xmlns is used only to declare namespace bindings and is by-     -- definition bound to the namespace name http://www.w3.org/2000/xmlns/.-     -- It MUST NOT be declared . Other prefixes MUST NOT be bound to this-     -- namespace name, and it MUST NOT be declared as the default namespace.-     -- Element names MUST NOT have the prefix xmlns.-     ---     -- All other prefixes beginning with the three-letter sequence x, m, l, in-     -- any case combination, are reserved. This means that:-     ---     -- - users SHOULD NOT use them except as defined by later specifications-     -- - processors MUST NOT treat them as fatal errors.- deriving (Eq,Ord,Show)-instance P.ShowErrorComponent Error where-	showErrorComponent = show---- * Helpers-p_error :: e -> Parser e s a-p_error = P.fancyFailure . Set.singleton . P.ErrorCustom--p_quoted :: P.Tokens s ~ TL.Text => (Char -> Parser e s a) -> Parser e s a-p_quoted p =-	P.between (P.char '"') (P.char '"') (p '"') <|>-	P.between (P.char '\'') (P.char '\'') (p '\'')--p_until :: P.Tokens s ~ TL.Text => (Char -> Bool) -> (Char, TL.Text) -> Parser e s TL.Text-p_until content (end, end_) =-	(TL.concat <$>) $ P.many $-		P.takeWhile1P Nothing (\c -> content c && c /= end) <|>-		P.try (TL.singleton <$> P.char end <* P.notFollowedBy (P.string end_))--p_until1 :: P.Tokens s ~ TL.Text => (Char -> Bool) -> (Char, TL.Text) -> Parser e s TL.Text-p_until1 content (end, end_) =-	(TL.concat <$>) $ P.some $-		P.takeWhile1P Nothing (\c -> content c && c /= end) <|>-		P.try (TL.singleton <$> P.char end <* P.notFollowedBy (P.string end_))
− Symantic/XML/Write.hs
@@ -1,274 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE StrictData #-}-module Symantic.XML.Write where--import Control.Applicative (Applicative(..), liftA2)-import Control.Monad (Monad(..))-import Data.Bool-import Data.Default.Class (Default(..))-import Data.Eq (Eq(..))-import Data.Foldable (Foldable(..), all)-import Data.Function (($), (.), const)-import Data.Maybe (Maybe(..))-import Data.Monoid (Monoid(..))-import Data.Semigroup (Semigroup(..))-import Data.String (String, IsString(..))-import Data.Traversable (Traversable(..))-import System.IO (IO, FilePath)-import Text.Show (Show(..))-import qualified Control.Monad.Trans.Reader as R-import qualified Control.Monad.Trans.State as S-import qualified Data.ByteString.Lazy as BSL-import qualified Data.Char as Char-import qualified Data.HashMap.Strict as HM-import qualified Data.HashSet as HS-import qualified Data.Sequence as Seq-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Lazy.Builder as TLB-import qualified Data.Text.Lazy.Encoding as TL--import Symantic.XML.Document as XML--writeXML :: NoSource src => XMLs src -> TL.Text-writeXML xs = TLB.toLazyText $ write xs `R.runReader` def--writeXMLIndented :: NoSource src => TL.Text -> XMLs src -> TL.Text-writeXMLIndented ind xs =-	TLB.toLazyText $-	write xs `R.runReader` def-	 { reader_indent       = if TL.null ind then mempty else "\n"-	 , reader_indent_delta = ind-	 }--writeFile :: FilePath -> TL.Text -> IO ()-writeFile fp t = BSL.writeFile fp $ TL.encodeUtf8 t---- * Type 'Write'-type Write = R.Reader Reader TLB.Builder-instance Semigroup Write where-	(<>) = liftA2 (<>)-instance Monoid Write where-	mempty = return ""-	mappend = (<>)-instance IsString Write where-	fromString = return . fromString---- ** Type 'Reader'-data Reader = Reader- { reader_ns_scope     :: Namespaces NCName- , reader_indent       :: TLB.Builder- , reader_indent_delta :: TL.Text- , reader_no_text      :: Bool- }-instance Default Reader where-	def = Reader-	 { reader_ns_scope     = def-	 , reader_indent       = ""-	 , reader_indent_delta = ""-	 , reader_no_text      = False-	 }---- * Class 'Buildable'-class Buildable a where-	build :: a -> TLB.Builder-instance Buildable Char.Char where-	build = TLB.singleton-instance Buildable String where-	build = TLB.fromString-instance Buildable TL.Text where-	build = TLB.fromLazyText-instance Buildable NCName where-	build = build . unNCName-instance Buildable Name where-	build = build . unName-instance Buildable PName where-	build PName{..} =-		case pNameSpace of-		 Nothing -> build pNameLocal-		 Just p -> build p<>":"<> build pNameLocal-instance Buildable Namespace where-	build = build . unNamespace-instance Buildable EntityRef where-	build EntityRef{..} = "&"<>build entityRef_name<>";"-instance Buildable CharRef where-	build (CharRef c) = "&#"<>build (show (Char.ord c))<>";"-instance Buildable EscapedText where-	build (EscapedText et) = (`foldMap` et) $ \case-	 EscapedPlain     t -> build t-	 EscapedEntityRef r -> build r-	 EscapedCharRef   r -> build r---- * Class 'Writable'-class Writeable a where-	write :: a -> Write-instance Writeable NCName where-	write = return . TLB.fromLazyText . unNCName-instance NoSource src => Writeable (XMLs src) where-	write xs = do-		ro <- R.ask-		if TL.null (reader_indent_delta ro)-		 then foldMap write xs-		 else-			R.local (const ro{reader_no_text}) $-				foldMap write xs-			where reader_no_text =-				(`all` xs) $ \case-				 Tree (Sourced _ (NodeText (EscapedText et))) _ts ->-					all (\case-					 EscapedPlain t -> TL.all Char.isSpace t-					 _ -> False) et-				 _ -> True-instance NoSource src => Writeable (XML src) where-	write (Tree (Sourced _src nod) xs) = do-		ro <- R.ask-		case nod of-			NodeAttr an-			 | [Tree (Sourced _ (NodeText av)) _] <- toList xs -> do-				return $ " "<>buildAttr (prefixifyQName (reader_ns_scope ro) an) av-			 | otherwise -> mempty-			NodeCDATA t ->-				return $-					reader_indent ro <>-					"<[CDATA[["<>build t<>"]]>"-			NodeComment t ->-				return $-					reader_indent ro <>-					"<!--"<>build t<>"-->"-			NodeElem elemQName -> do-				let (elemAttrs, elemChilds) =-					(`Seq.spanl` xs) $ \case-						 Tree (Sourced _ NodeAttr{}) _ -> True-						 _ -> False-				let (usedNS, declNS) ::-					( HS.HashSet Namespace-					, Namespaces NCName-					) =-					foldl' go (initUsedNS, initDeclNS) elemAttrs-					where-					initUsedNS-					 | qNameSpace elemQName == xmlns_empty = mempty-					 | otherwise                           = HS.singleton $ qNameSpace elemQName-					initDeclNS = def{namespaces_default = namespaces_default $ reader_ns_scope ro}-					go (!uNS, !dNS) = \case-						Tree (Sourced _ (NodeAttr QName{..})) vs-						 -- xmlns:prefix="namespace"-						 | qNameSpace == xmlns_xmlns-						 , [Tree (Sourced _ (NodeText t)) _] <- toList vs ->-							let n = unescapeText t in-							(uNS,) dNS-							 { namespaces_prefixes =-								(if TL.null n-								then HM.delete-								-- NOTE: empty namespace means removal of the prefix from scope.-								else (`HM.insert` qNameLocal))-								 (Namespace n)-								 (namespaces_prefixes dNS)-							 }-						 -- xmlns="namespace"-						 | qNameSpace == xmlns_empty-						 , qNameLocal == NCName "xmlns"-						 , [Tree (Sourced _ (NodeText t)) _] <- toList vs ->-							(uNS,)-							dNS{namespaces_default = Namespace $ unescapeText t}-						 -- name="value"-						 | qNameSpace == xmlns_empty -> (uNS, dNS)-						 -- {namespace}name="value"-						 | otherwise -> (HS.insert qNameSpace uNS, dNS)-						_ -> (uNS, dNS)-				let inhNS =-					-- NOTE: the inherited namespaces,-					-- including those declared at this element.-					HM.union-					 (namespaces_prefixes declNS)-					 (namespaces_prefixes (reader_ns_scope ro))-				let autoNS =-					-- NOTE: the namespaces used but not declared nor default,-					-- with fresh prefixes.-					HM.delete (namespaces_default declNS) $-					(`S.evalState` HS.empty) $-					traverse-					 (\() -> S.gets freshNCName)-					 (HS.toMap usedNS `HM.difference` inhNS)-				let autoAttrs =-					-- NOTE: XMLify autoNS-					HM.foldlWithKey'-					 (\acc (Namespace v) p ->-						(acc Seq.|>) $-							Tree (notSourced $ NodeAttr QName{qNameSpace=xmlns_xmlns, qNameLocal=p}) $-								pure $ tree0 $ notSourced $ NodeText $ EscapedText $ pure $ EscapedPlain v-					 ) mempty autoNS-				let scopeNS = declNS { namespaces_prefixes = autoNS <> inhNS }-				return $-					let build_elemPName = build $ prefixifyQName scopeNS elemQName in-					let build_elemAttrs =-						(`foldMap` (autoAttrs <> elemAttrs)) $ \case-						 Tree (Sourced _ (NodeAttr an)) vs-						  | [Tree (Sourced _ (NodeText av)) _] <- toList vs ->-							" "<>buildAttr (prefixifyQName scopeNS{namespaces_default=""} an) av-						 _ -> mempty in-					reader_indent ro-					 <> "<"<>build_elemPName-					 <> build_elemAttrs <>-					let build_elemChilds = write elemChilds-						`R.runReader` ro-						 { reader_ns_scope = scopeNS-						 , reader_indent   = reader_indent ro <> build (reader_indent_delta ro)-						 } in-					if null elemChilds-					then "/>"-					else ">"-						 <> build_elemChilds-						 <> (-							if TL.null (reader_indent_delta ro)-							|| noIndent elemChilds-							then mempty-							else reader_indent ro-						 )-						 <> "</"<>build_elemPName<>">"-					where-					noIndent =-						all $ \case-						 Tree (Sourced _ (NodeText _txt)) _ts -> True-						 _ -> False-			NodePI pn pv-			 | pn == "xml" -> do-				write_xs <- write xs-				return $-					"<?"<>build pn<>s<>write_xs<>"?>"-			 | otherwise ->-				return $-					reader_indent ro <>-					"<?"<>build pn<>s<>build pv<>"?>"-				where s | TL.null pv = ""-				        | otherwise  = " "-			NodeText t -> do-				return $-					if reader_no_text ro-					 then mempty-					 else build t--buildAttr :: PName -> EscapedText -> TLB.Builder-buildAttr n v = build n<>"=\""<>buildAttrValue v<>"\""--buildAttrValue :: EscapedText -> TLB.Builder-buildAttrValue (EscapedText et) = (`foldMap` et) $ \case- EscapedPlain p -> build p- EscapedEntityRef EntityRef{..} ->-	build $ TL.replace "\"" "&quot;" entityRef_value- EscapedCharRef (CharRef c)-	| c == '\"' -> "&quot;"-	| otherwise -> build c--removeSpaces :: XMLs src -> XMLs src-removeSpaces xs =-	if (`all` xs) $ \case-	 Tree (Sourced _ (NodeText (EscapedText et))) _ts ->-		all (\case-		 EscapedPlain t -> TL.all Char.isSpace t-		 _ -> False) et-	 _ -> True-	then (`Seq.filter` xs) $ \case-		 Tree (Sourced _ NodeText{}) _ts -> False-		 _ -> True-	else xs
+ src/Symantic/XML.hs view
@@ -0,0 +1,11 @@+module Symantic.XML+ ( module Symantic.XML.Language+ , module Symantic.XML.Read+ , module Symantic.XML.Tree+ , module Symantic.XML.Write+ ) where++import Symantic.XML.Language+import Symantic.XML.Read+import Symantic.XML.Tree+import Symantic.XML.Write
+ src/Symantic/XML/Language.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE UndecidableInstances #-}+module Symantic.XML.Language+ ( module Symantic.XML.Language+ , module Symantic.XML.Namespace+ , module Symantic.XML.Text+ , module Symantic.Base.Composable+ , module Symantic.Base.Algebrable+ , module Symantic.Base.Permutable+ ) where++import Data.Function ((.))+import Data.Maybe (Maybe)+import Data.Kind (Constraint)+import qualified Data.Text.Lazy as TL++import Symantic.XML.Namespace+import Symantic.XML.Text+import Symantic.Base.Algebrable+import Symantic.Base.Composable+import Symantic.Base.Permutable++-- * Class 'XML'+class+ ( Composable repr+ , Tupable repr+ , Eitherable repr+ , Textable repr+ ) => XML repr where+  --xmlPI ::  -> repr a k+  -- | @('namespace' p ns)@ declares a namespace prefix @(p)@+  -- to be used for the 'Namespace' @(ns)@.+  -- Or make @(ns)@ the default namespace if @(p)@ is 'Nothing'.+  namespace :: Maybe NCName -> Namespace -> repr k k+  default namespace ::+   Transformable repr => XML (UnTrans repr) =>+   Maybe NCName -> Namespace -> repr k k+  namespace n ns = noTrans (namespace n ns)+  +  default element :: Transformable repr => XML (UnTrans repr) =>+             QName -> repr a k -> repr a k+  element :: QName -> repr a k -> repr a k+  element n x = noTrans (element n (unTrans x))+  +  default attribute :: Transformable repr => XML (UnTrans repr) =>+               QName -> repr a k -> repr a k+  attribute :: QName -> repr a k -> repr a k+  attribute n x = noTrans (attribute n (unTrans x))+  +  default pi :: Transformable repr => XML (UnTrans repr) =>+        PName -> repr (TL.Text -> k) k+  pi :: PName -> repr (TL.Text -> k) k+  pi n = noTrans (pi n)+  +  default literal :: Transformable repr => XML (UnTrans repr) =>+             TL.Text -> repr k k+  literal :: TL.Text -> repr k k+  literal = noTrans . literal+  +  default comment :: Transformable repr => XML (UnTrans repr) =>+             repr (TL.Text -> k) k+  comment :: repr (TL.Text -> k) k+  comment = noTrans comment+  +  default cdata :: Transformable repr => XML (UnTrans repr) =>+           repr (TL.Text -> k) k+  cdata :: repr (TL.Text -> k) k+  cdata = noTrans cdata++-- ** Class 'Textable'+class Textable repr where+  type TextConstraint repr a :: Constraint+  type TextConstraint repr a = TextConstraint (UnTrans repr) a+  default text :: Transformable repr => XML (UnTrans repr) =>+          TextConstraint (UnTrans repr) a => repr (a -> k) k+  text :: TextConstraint repr a => repr (a -> k) k+  text = noTrans text
+ src/Symantic/XML/Namespace.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Symantic.XML.Namespace where++import Control.Applicative (Alternative(..))+import Data.Bool+import Data.Eq (Eq(..))+import Data.Foldable (all)+import Data.Function (($), (.), id)+import Data.Functor (Functor(..), (<$>))+import Data.Hashable (Hashable(..))+import Data.Int (Int)+import Data.Maybe (Maybe(..), fromMaybe)+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Semigroup (Semigroup(..))+import Data.String (String, IsString(..))+import GHC.Generics (Generic)+import Prelude (error)+import Text.Show (Show(..), showsPrec, showChar, showString)+import qualified Data.Char.Properties.XMLCharProps as XC+import qualified Data.HashMap.Strict as HM+import qualified Data.HashSet as HS+import qualified Data.List as List+import qualified Data.Text.Lazy as TL++-- * Type 'QName'+-- | Qualified name.+data QName+ =   QName+ {   qNameSpace :: Namespace -- ^ eg. "http://www.w3.org/1999/XSL/Transform"+ ,   qNameLocal :: NCName    -- ^ eg. "stylesheet"+ } deriving (Eq, Ord, Generic)+instance Show QName where+  showsPrec _p QName{..} =+    (if TL.null $ unNamespace qNameSpace then id+    else showChar '{' . showString (TL.unpack $ unNamespace qNameSpace) . showChar '}'+    ) . showsPrec 10 qNameLocal+instance IsString QName where+  -- NCName's fromString will raise an error.+  fromString "" = QName "" ""+  fromString full@('{':rest) =+    case List.break (== '}') rest of+     (_, "")     -> error $ "Invalid XML Clark notation: "<>show full+     (ns, local) -> QName (fromString ns) $ fromString $ List.drop 1 local+  fromString local = QName "" $ fromString local+instance Hashable QName++qName :: NCName -> QName+qName = QName (Namespace "")+{-# INLINE qName #-}++-- ** Type 'Namespace'+newtype Namespace = Namespace { unNamespace :: TL.Text }+ deriving (Eq, Ord, Show, Hashable)+instance IsString Namespace where+  fromString s =+    if all (\c -> XC.isXmlChar c && c `List.notElem` ("'\"<&"::String)) s+    then Namespace (fromString s)+    else error $ "Invalid XML Namespace: "<>show s++xmlns_xml, xmlns_xmlns, xmlns_xsd, xmlns_empty :: Namespace+xmlns_xml   = Namespace "http://www.w3.org/XML/1998/namespace"+xmlns_xmlns = Namespace "http://www.w3.org/2000/xmlns/"+xmlns_xsd   = Namespace "http://www/w3/org/2001/XMLSchema-datatypes"+xmlns_empty = Namespace ""++-- *** Type 'Namespaces'+data Namespaces prefix+ =   Namespaces+ {   namespaces_prefixes :: HM.HashMap Namespace prefix+ ,   namespaces_default  :: Namespace+ } deriving (Show)+instance Functor Namespaces where+  fmap f (Namespaces ps d) = Namespaces (fmap f ps) d+instance Semigroup (Namespaces NCName) where+  x <> y = Namespaces+   { namespaces_prefixes = namespaces_prefixes x <> namespaces_prefixes y+   , namespaces_default  = namespaces_default x+   }+instance Semigroup (Namespaces (Maybe NCName)) where+  x <> y = Namespaces+   { namespaces_prefixes = HM.unionWith (<|>) (namespaces_prefixes x) (namespaces_prefixes y)+   , namespaces_default  = namespaces_default x+   }+instance Monoid (Namespaces NCName) where+  mempty  = Namespaces HM.empty xmlns_empty+  mappend = (<>)+instance Monoid (Namespaces (Maybe NCName)) where+  mempty  = Namespaces HM.empty xmlns_empty+  mappend = (<>)++defaultNamespaces :: IsString prefix => Namespaces prefix+defaultNamespaces = Namespaces+ { namespaces_prefixes = HM.fromList+   [ (xmlns_xml  , "xml")+   , (xmlns_xmlns, "xmlns")+   ]+ , namespaces_default = xmlns_empty+ }++prefixifyQName :: Namespaces NCName -> QName -> PName+prefixifyQName Namespaces{..} QName{..} = PName+ { pNameSpace =+  if qNameSpace == namespaces_default+  then Nothing+  else HM.lookup qNameSpace namespaces_prefixes+ , pNameLocal = qNameLocal+ }++-- ** Type 'PName'+-- | Prefixed 'NCName'+data PName+ =   PName+ {   pNameSpace :: Maybe NCName -- ^ eg. Just "xml"+ ,   pNameLocal :: NCName       -- ^ eg. "stylesheet"+ } deriving (Eq, Ord, Generic)+instance Show PName where+  showsPrec p PName{pNameSpace=Nothing, ..} =+    showsPrec p pNameLocal+  showsPrec _p PName{pNameSpace=Just p, ..} =+    showsPrec 10 p .+    showChar ':' .+    showsPrec 10 pNameLocal+instance IsString PName where+  fromString "" = PName Nothing "" -- NCName's fromString will raise an error.+  fromString s =+    case List.break (== ':') s of+     (_, "")    -> PName Nothing $ fromString s+     (p, local) -> PName (Just $ fromString p) (fromString $ List.drop 1 local)++pName :: NCName -> PName+pName = PName Nothing+{-# INLINE pName #-}++-- ** Type 'NCName'+-- | Non-colonized name.+newtype NCName = NCName { unNCName :: TL.Text }+ deriving (Eq, Ord, Hashable)+instance Show NCName where+  showsPrec _p = showString . TL.unpack . unNCName+instance IsString NCName where+  fromString s =+    fromMaybe (error $ "Invalid XML NCName: "<>show s) $+    ncName (TL.pack s)++ncName :: TL.Text -> Maybe NCName+ncName t =+  case TL.uncons t of+   Just (c, cs)+    | XC.isXmlNCNameStartChar c+    , TL.all XC.isXmlNCNameChar cs+    -> Just (NCName t)+   _ -> Nothing++poolNCNames :: [NCName]+poolNCNames =+  [ NCName $ TL.pack ("ns"<>show i)+  | i <- [1 :: Int ..]+  ]++freshNCName :: HS.HashSet NCName -> NCName+freshNCName ps = List.head $ poolNCNames List.\\ HS.toList ps++freshifyNCName :: HS.HashSet NCName -> NCName -> NCName+freshifyNCName ns (NCName n) =+  let ints = [1..] :: [Int] in+  List.head+   [ fresh+   | suffix <- mempty : (show <$> ints)+   , fresh <- [ NCName $ n <> TL.pack suffix]+   , not $ fresh `HS.member` ns+   ]
+ src/Symantic/XML/Read.hs view
@@ -0,0 +1,640 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Symantic.XML.Read where++import Control.Applicative as Alternative (Applicative(..), Alternative(..), optional)+import Control.Monad (Monad(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Data.Bool+import Data.Either (Either(..))+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..), all)+import Data.Function (($), (.), const, id, flip)+import Data.Functor (Functor(..), (<$>))+import Data.List.NonEmpty (NonEmpty(..))+import Data.Maybe (Maybe(..), maybe, isNothing, maybeToList)+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Proxy (Proxy(..))+import Data.Semigroup (Semigroup(..))+import Data.String (String, IsString(..))+import Data.Tuple (fst)+import Data.Void (Void)+import Numeric.Natural (Natural)+import Prelude ((+), Integer, undefined)+import System.IO (IO, FilePath)+import Text.Show (Show(..))+import qualified Data.Char as Char+import qualified Data.HashMap.Strict as HM+import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as Text+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.TreeSeq.Strict as TS+import qualified Text.Megaparsec as P+import qualified Text.Megaparsec.Char as P+import qualified Text.Megaparsec.Char.Lexer as P+import qualified Text.Megaparsec.Internal as P++import Symantic.Base+import Symantic.XML.Language+import Symantic.XML.RelaxNG.Language+import Symantic.XML.Tree++-- | Main reading function.+read ::+ Read FileSourced Void (x->x) a ->+ FilePath ->+ IO (Either String a)+read rng path =+  readTree path >>= \case+   Left  err -> return $ Left err+   Right xml -> return $ runRead rng xml++-- | Like 'readWithRelaxNG' but on a 'FileSourcedTrees'.+runRead ::+ Read FileSourced Void (x->x) a ->+ FileSourcedTrees ->+ Either String a+runRead rng xml =+  case P.runParser (unRead rng) "" (mempty, xml) of+   Left err -> Left $ foldMap parseErrorTextPretty $ P.bundleErrors err+   Right a -> Right $ a id++-- * Type 'ReadStream'+type ReadStream src =+ ( HM.HashMap QName (src EscapedAttr)+ , Trees src+ )++-- | Take one 'Node' from the 'ReadStream',+-- or fallback to an attribute, or 'Nothing'.+-- +-- Use 'pTokenAttr' to take only attributes.+take1_ ::+ UnSource src =>+ (Node (src EscapedAttr) -> Bool) ->+ ReadStream src ->+ Maybe ( P.Token (ReadStream src)+       , ReadStream src )+take1_ isIgnoredNode s@(attrs, trees) =+  go trees+  where+  go trs =+    case Seq.viewl trs of+     Seq.EmptyL+      | null attrs -> Nothing+      | otherwise -> Just (Left attrs, s)+     t Seq.:< ts ->+      case unSource (TS.unTree t) of+       n | isIgnoredNode n -> go ts+         | otherwise -> Just (Right t, (attrs, ts))+        -- Note that having an ignored node+        -- can split a text into two 'NodeText's.+        -- Not sure if it would be better to unify them.++-- ** Type 'ReadConstraints'+-- | Convenient alias to be less verbose.+type ReadConstraints src =+ ( Ord (src (Node (src EscapedAttr)))+ , Ord (src EscapedAttr)+ , UnSource src+ , NoSource src+ , SourceOf src+ , Show (Source src)+ , Show (src String)+ , Functor src+ )++instance ReadConstraints src => P.Stream (ReadStream src) where+  type Token (ReadStream src) = Either+   (HM.HashMap QName (src EscapedAttr))+   (Tree src)+  type Tokens (ReadStream src) = ReadStream src+  take1_ = take1_ isIgnoredNode+    where+    isIgnoredNode = \case+     NodeComment{} -> True+     NodePI{}      -> True+     _ -> False+  showTokens _s toks =+    orList $+    mconcat $+    toList $ showTree <$> toks+    where+    showSource :: src String -> String+    showSource sa =+      let src = sourceOf sa in+      if nullSource @src src+      then unSource sa+      else unSource sa<>" at "<>show src+    showTree = \case+     Left as ->+      (\(an, av) -> showSource $ ("(attribute "<>show an<>")") <$ av)+       <$> List.sortOn fst (HM.toList as)+     Right (TS.Tree nod ts) ->+      pure $+      showSource . (<$ nod) $+      case unSource nod of+       NodeElem n _as -> "(element "<>show n<>")"+       NodeText{} ->+        case Seq.viewl ts of+         TS.Tree tn _ Seq.:< _+          | NodeText lit <- unSource tn ->+          -- Abuse the encoding to detect expected 'literal'+          -- using nested 'NodeText'+          "\""<>TL.unpack (unescapeText lit)<>"\""+         _ -> "text"+       NodeComment _c -> "comment"+       NodePI n _t    -> "(processing-instruction "<>show n<>")"+       NodeCDATA _t   -> "cdata"+  -- Useless methods for validating an XML AST+  takeN_ = undefined+  tokensToChunk = undefined+  chunkToTokens = undefined+  chunkLength = undefined+  takeWhile_ = undefined+  reachOffset = undefined+  reachOffsetNoLine = undefined++-- * Type 'Read'+newtype Read src e f k+ =      Read+ {    unRead :: P.Parsec e (ReadStream src) (f->k) }++instance+ ( Ord err+ , ReadConstraints src+ ) => Emptyable (Read src err) where+  empty = Read $ id <$ P.eof+instance+ ( Ord err+ , ReadConstraints src+ ) => Unitable (Read src err) where+  unit = Read $ return ($ ())+instance+ ( Ord err+ , ReadConstraints src+ ) => Voidable (Read src err) where+  void _a (Read x) = Read $+    (\a2b2k b -> a2b2k (\_a -> b)) <$> x+instance+ ( Ord err+ , ReadConstraints src+ ) => Constant (Read src err) where+  constant a = Read $ return ($ a)+instance+ ( Ord err+ , ReadConstraints src+ ) => Permutable (Read src err) where+  type Permutation (Read src err) =+    ReadPerm src err+  permutable (ReadPerm ma p) = Read $ do+    r <- Alternative.optional p+    unRead $+      case r of+       Just perms -> permutable perms+       Nothing ->+        Read $ maybe+         -- Not 'empty' here so that 'P.TrivialError'+         -- has the unexpected token.+         (P.token (const Nothing) Set.empty)+         return ma+  noPerm = ReadPerm Nothing Alternative.empty+  perm (Read x) =+    ReadPerm Nothing $ (<$> x) $ \a ->+      ReadPerm (Just a) Alternative.empty+  permWithDefault d (Read x) =+    ReadPerm (Just ($ d)) $ (<$> x) $ \a ->+      ReadPerm (Just a) Alternative.empty+instance+ ( Ord err+ , ReadConstraints src+ ) => Composable (Read src err) where+  Read x <.> Read y = Read $+    x >>= \a2b -> (. a2b) <$> y+instance+ ( Ord err+ , ReadConstraints src+ ) => Tupable (Read src err) where+  Read x <:> Read y = Read $+    consCont (,) <$> x <*> y+instance+ ( Ord err+ , ReadConstraints src+ ) => Eitherable (Read src err) where+  Read x <+> Read y = Read $+    mapCont Left <$> P.try x <|>+    mapCont Right <$> y+{-+instance+ ( Ord err+ , ReadConstraints src+ ) => Routable (Read src err) where+  Read x <!> Read y = Read $+    (\a2k (a:!:_b) -> a2k a) <$> P.try x <|>+    (\b2k (_a:!:b) -> b2k b) <$> y+-}+instance+ ( Ord err+ , ReadConstraints src+ ) => Optionable (Read src err) where+  option (Read x) = Read $+    P.try x <|> return id+  optional (Read x) = Read $+    mapCont Just <$> P.try x <|>+    return ($ Nothing)+instance+ ( Ord err+ , ReadConstraints src+ ) => Repeatable (Read src err) where+  many0 (Read x) = Read $ concatCont <$> many x+  many1 (Read x) = Read $ concatCont <$> some x+instance+ ( Ord err+ , ReadConstraints src+ ) => Dimapable (Read src err) where+  dimap a2b _b2a (Read r) =+    Read $ (\k b2k -> k (b2k . a2b)) <$> r+instance+ ( Ord err+ , ReadConstraints src+ ) => Dicurryable (Read src err) where+  dicurry (_::proxy args) constr _destr (Read x) = Read $ do+    f <- x+    return $ \r2k ->+      f (mapresultN @args r2k constr)+instance+ ( Ord err+ , ReadConstraints src+ , Textable (Read src err)+ ) => XML (Read src err) where+  namespace _nm _ns = Read (return id)+  element n p = Read $ do+    s <- P.token check $ Set.singleton $+      P.Tokens $ pure expected+    unRead $ readNested p s+    where+    expected = Right $ TS.tree0 $ noSource $ NodeElem n mempty+    check = \case+     Right (TS.Tree nod ts)+      | NodeElem e as <- unSource nod+      , e == n+      -> Just (removeXMLNS as, removeSpaces ts)+     _ -> Nothing+  attribute n p = Read $ do+    v <- pTokenAttr n $ Set.singleton $+      P.Tokens $ pure expected+    unRead $ readNested p+     (mempty, pure (TS.tree0 (NodeText . EscapedText . unEscapedAttr <$> v)))+    -- Cast 'EscapedAttr' into 'EscapedText'+    -- because it will be read, not written,+    -- hence only given to 'unescapeText'+    -- which is the same than 'unescapeAttr'.+    where+    expected = Left $ HM.singleton n $ noSource ""+  literal lit = Read $ do+    P.token check $ Set.singleton $ P.Tokens $ pure expected+    where+    expected = Right $+      TS.Tree (noSource $ NodeText "")+       (pure $ TS.tree0 (noSource $ NodeText $ escapeText lit))+    check = \case+     Right (Tree0 nod)+      | NodeText t <- unSource nod+      , unescapeText t == lit+      -> Just id+     _ -> Nothing+  pi n = Read $ do+    v <- pTokenPI n $ Set.singleton $+      P.Tokens $ pure expected+    return ($ v)+    where+    expected = Right $ TS.tree0 $ noSource $ NodePI n mempty+  cdata = Read $+    P.token check $ Set.singleton $+      P.Tokens $ pure expected+    where+    expected = Right $ TS.tree0 $ noSource $ NodeCDATA mempty+    check = \case+     Right (Tree0 nod)+      | NodeCDATA v <- unSource nod+      -> Just ($ v)+     _ -> Nothing+  comment = Read $+    P.token check $ Set.singleton $+      P.Tokens $ pure expected+    where+    expected = Right $ TS.tree0 $ noSource $ NodeComment mempty+    check = \case+     Right (Tree0 nod)+      | NodeComment v <- unSource nod+      -> Just ($ v)+     _ -> Nothing+instance Ord err => Textable (Read FileSourced err) where+  type TextConstraint (Read FileSourced err) a =+    DecodeText a+  text :: forall a k repr.+   repr ~ Read FileSourced err =>+   TextConstraint repr a => repr (a->k) k+  text = Read $ do+    Sourced (FileSource (src :| _)) txt <-+      P.token check $ Set.singleton $ P.Tokens $ pure expected+    case P.runParser @Void (decodeText @a <* P.eof) "" (unescapeText txt) of+     Right a -> return ($ a)+     Left errs -> P.fancyFailure $ Set.singleton $ P.ErrorFail $+      (`foldMap` P.bundleErrors errs) $ \err ->+        fileRange_path src <> ":" <>+        show (fileRange_begin src <> Offset (P.errorOffset err)) <> "\n" <>+        P.parseErrorTextPretty err+    where+    expected = Right $ TS.tree0 $ noSource $ NodeText $ EscapedText mempty+    check = \case+     Right (Tree0 nod)+      | NodeText t <- unSource nod+      -> Just (t <$ nod)+     _ -> Nothing+instance+ ( Ord err+ , ReadConstraints src+ , Textable (Read src err)+ , Definable (Read src err)+ ) => RelaxNG (Read src err) where+  elementMatch nc p = Read $ do+    (n,s) <- P.token check $ Set.singleton $+      P.Tokens $ pure expected+    ((\a2k n2a -> a2k (n2a n)) <$>) $+      unRead (readNested p s)+    where+    expected = Right $ TS.tree0 $ noSource $+      NodeElem (qName (NCName (TLB.toLazyText+       (textify (mempty::Namespaces NCName,(infixN0,SideL),nc)))))+       mempty+    check = \case+     Right (TS.Tree nod ts)+      | NodeElem n as <- unSource nod+      , matchNameClass nc n+      -> Just (n, (removeXMLNS as, removeSpaces ts))+     _ -> Nothing+  attributeMatch nc p = Read $ do+    (an,av) <- pTokenAttrNameClass nc $ Set.singleton $+      P.Tokens $ pure expected+    ((\a2k n2a -> a2k (n2a an)) <$>) $+      unRead $ readNested p+       (mempty, pure (TS.tree0 (NodeText . EscapedText . unEscapedAttr <$> av)))+    -- See comment in 'attribute' about the cast to 'EscapedText' here.+    where+    expected = Left $ HM.singleton (qName (NCName n)) $ noSource ""+      where n = TLB.toLazyText $ textify (mempty::Namespaces NCName,(infixN0,SideL),nc)+instance Ord err => Definable (Read FileSourced err) where+  define n = Read . P.label n . unRead++-- ** Type 'ReadPerm'+data ReadPerm (src :: * -> *) err a k+ =   ReadPerm+ {   readPerm_result :: !(Maybe (a->k))+ ,   readPerm_parser :: P.Parsec err (ReadStream src) (ReadPerm src err a k)+ }++instance+ (Ord err, ReadConstraints src) =>+ Dimapable (ReadPerm src err) where+  dimap a2b b2a (ReadPerm a ma) =+    ReadPerm (merge <$> a)+    (dimap a2b b2a `fmap` ma)+    where merge = \a2k2k b2k -> a2k2k $ b2k . a2b+instance+ (Ord err, ReadConstraints src) =>+ Dicurryable (ReadPerm src err) where+  dicurry ::+   forall args r k proxy.+   CurryN args =>+   proxy args ->+   (args-..->r) -> -- construction+   (r->Tuples args) -> -- destruction+   ReadPerm src err (args-..->k) k ->+   ReadPerm src err (r->k) k+  dicurry px constr destr (ReadPerm a ma) =+    ReadPerm (merge <$> a)+     (dicurry px constr destr `fmap` ma)+    where+    merge args2k2k = \r2k ->+      args2k2k $ mapresultN @args r2k constr+instance+ (Ord err, ReadConstraints src) =>+ Composable (ReadPerm src err) where+  lhs@(ReadPerm da pa) <.> rhs@(ReadPerm db pb) =+    ReadPerm a $+      lhsAlt <|> rhsAlt+    where+    lhsAlt = (<.> rhs) <$> pa+    rhsAlt = (lhs <.>) <$> pb+    a = flip (.) <$> da <*> db+instance+ (Ord err, ReadConstraints src) =>+ Tupable (ReadPerm src err) where+  lhs@(ReadPerm da pa) <:> rhs@(ReadPerm db pb) =+    ReadPerm a (lhsAlt <|> rhsAlt)+    where+    lhsAlt = (<:> rhs) <$> pa+    rhsAlt = (lhs <:>) <$> pb+    a = consCont (,) <$> da <*> db+instance Definable (ReadPerm src err) where+  define _n = id++-- * Utils++concatCont :: [(a->k)->k] -> ([a]->k)->k+concatCont = List.foldr (consCont (:)) ($ [])+{-# INLINE concatCont #-}++consCont :: (a->b->c) -> ((a->k)->k) -> ((b->k)->k) -> (c->k)->k+consCont ab2c a2k2k b2k2k = \c2k -> a2k2k $ \a -> b2k2k $ \b -> c2k (ab2c a b)+{-# INLINE consCont #-}++mapCont :: (a->b) -> ((a->k)->k) -> ((b->k)->k)+mapCont a2b a2k2k = \b2k -> a2k2k (b2k . a2b)+{-# INLINE mapCont #-}++-- | An adaptation of megaparsec's 'pToken',+-- to handle 'attribute' properly.+pTokenAttr ::+ forall e m src.+ ReadConstraints src =>+ QName ->+ Set.Set (P.ErrorItem (P.Token (ReadStream src))) ->+ P.ParsecT e (ReadStream src) m (src EscapedAttr)+pTokenAttr an ps = P.ParsecT $ \st@(P.State s@(attrs,trees) o pst de) cok _ _ eerr ->+  case HM.lookup an attrs of+   Just av -> cok av (P.State (HM.delete an attrs, trees) (o+1) pst de) mempty+   Nothing -> eerr (P.TrivialError o us ps) st+    where+    us = case P.take1_ s of+     Nothing -> pure P.EndOfInput+     Just (t,_ts) -> (Just . P.Tokens . pure) t+{-# INLINE pTokenAttr #-}++-- | An adaptation of megaparsec's 'pToken',+-- to handle 'attributeMatch' properly.+pTokenAttrNameClass ::+ forall e m src.+ ReadConstraints src =>+ NameClass ->+ Set.Set (P.ErrorItem (P.Token (ReadStream src))) ->+ P.ParsecT e (ReadStream src) m (QName, src EscapedAttr)+pTokenAttrNameClass nc ps = P.ParsecT $ \st@(P.State s@(attrs,trees) o pst de) cok _ _ eerr ->+  case HM.toList attrs of+   a@(an,_av):_ | matchNameClass nc an -> cok a (P.State (HM.delete an attrs, trees) (o+1) pst de) mempty+   _ -> eerr (P.TrivialError o us ps) st+    where+    us = case P.take1_ s of+     Nothing -> pure P.EndOfInput+     Just (t,_ts) -> (Just . P.Tokens . pure) t+{-# INLINE pTokenAttrNameClass #-}++-- | An adaptation of megaparsec's 'pToken',+-- to handle 'pi' since 'NodePI' is ignored by 'P.take1_'.+pTokenPI ::+ forall e m src.+ UnSource src =>+ PName ->+ Set.Set (P.ErrorItem (P.Token (ReadStream src))) ->+ P.ParsecT e (ReadStream src) m TL.Text+pTokenPI n ps = P.ParsecT $ \st@(P.State s o pst de) cok _ _ eerr ->+  case take1 s of+   Nothing -> eerr (P.TrivialError o us ps) st+    where us = pure P.EndOfInput+   Just (c, cs)+    | Right (TS.Tree nod _) <- c+    , NodePI pn pv <- unSource nod+    , pn == n -> cok pv (P.State cs (o+1) pst de) mempty+    | otherwise -> eerr (P.TrivialError o us ps) st+      where+      us = case take1 s of+       Nothing -> pure P.EndOfInput+       Just (t,_ts) -> (Just . P.Tokens . pure) t+  where+  take1 = take1_ isIgnoredNode+    where+    isIgnoredNode = \case+     NodeComment{} -> True+     _ -> False++removeXMLNS ::+ HM.HashMap QName (src EscapedAttr) ->+ HM.HashMap QName (src EscapedAttr)+removeXMLNS =+  HM.filterWithKey $ \an _av ->+    case an of+     QName "" "xmlns" -> False+     QName ns _l -> ns /= xmlns_xmlns++removeSpaces :: UnSource src => Trees src -> Trees src+removeSpaces xs =+  if (`all` xs) $ \case+   TS.Tree nod _ts+    | NodeText (EscapedText et) <- unSource nod ->+    all (\case+     EscapedPlain t -> TL.all Char.isSpace t+     _ -> False) et+   _ -> True+  then (`Seq.filter` xs) $ \case+   TS.Tree nod _ts+    | NodeText EscapedText{} <- unSource nod -> False+   _ -> True+  else xs++-- | @readNested v xs@ returns a 'Read' parsing @xs@ entirely with @v@,+-- updating 'P.stateOffset' and re-raising any exception.+readNested ::+ Ord err =>+ ReadConstraints src =>+ Read src err f a ->+ ReadStream src ->+ Read src err f a+readNested (Read p) stateInput = Read $ do+  st <- P.getParserState+  (st', res) <- lift $ P.runParserT' (p <* P.eof) st+   { P.stateInput+   , P.stateOffset = P.stateOffset st+   }+  P.updateParserState (\s -> s{P.stateOffset = P.stateOffset st'})+  case res of+   Right a -> return a+   Left (P.ParseErrorBundle errs _) ->+    case NonEmpty.head errs of+     P.TrivialError _o us es -> P.failure us es+     P.FancyError _o es -> P.fancyFailure es++-- * Class 'DecodeText'+class DecodeText a where+  decodeText :: P.Parsec Void TL.Text a+instance DecodeText String where+  decodeText = TL.unpack . fst <$>+    P.match (P.skipMany P.anySingle)+instance DecodeText Text.Text where+  decodeText = TL.toStrict . fst <$>+    P.match (P.skipMany P.anySingle)+instance DecodeText TL.Text where+  decodeText = fst <$>+    P.match (P.skipMany P.anySingle)+instance DecodeText Bool where+  decodeText =+    False <$ (P.string "false" <|> P.string "0") <|>+    True  <$ (P.string "true"  <|> P.string "1")+instance DecodeText Integer where+  decodeText = P.signed (return ()) P.decimal+instance DecodeText Natural where+  decodeText = P.optional (P.char '+') *> P.decimal++-- * Megaparsec adaptations+-- | Rewrite 'P.parseErrorTextPretty' to keep 'Ord' of 'node's.+parseErrorTextPretty ::+ P.ShowErrorComponent err =>+ P.ParseError (ReadStream FileSourced) err -> String+parseErrorTextPretty (P.TrivialError o us ps) =+  if isNothing us && Set.null ps+  then "unknown parse error\n"+  else+    (case us of+     Just P.Tokens{} -> ""+     _ ->+      -- FIXME: this is not informative enough,+      -- but P.EndOfInput can not carry a source location,+      -- and retraversing the XML tree cannot be done+      -- exactly as the parser did only knowing the Offset,+      -- because of attributes being permutable.+      "node #"<>show o<>"\n"+    ) <>+    messageItemsPretty "unexpected "+     (showErrorItem px <$> maybeToList us) <>+    messageItemsPretty "expecting "+     (showErrorItem px <$> Set.toAscList ps)+  where px = Proxy :: Proxy s+parseErrorTextPretty err = P.parseErrorTextPretty err++messageItemsPretty :: String -> [String] -> String+messageItemsPretty prefix ts+ | null ts = ""+ | otherwise = prefix <> orList ts <> "\n"++orList :: IsString s => Monoid s => [s] -> s+orList [] = mempty+orList [x] = x+orList [x,y] = x <> " or " <> y+orList xs = mconcat (List.intersperse ", " (List.init xs)) <> ", or " <> List.last xs++showErrorItem ::+ (s ~ ReadStream (Sourced (FileSource Offset))) =>+ Proxy s -> P.ErrorItem (P.Token s) -> String+showErrorItem px = \case+ P.Tokens ts   -> P.showTokens px ts+ P.Label label -> NonEmpty.toList label+ P.EndOfInput  -> "end-of-node"
+ src/Symantic/XML/RelaxNG.hs view
@@ -0,0 +1,7 @@+module Symantic.XML.RelaxNG+ ( module Symantic.XML.RelaxNG.Language+ , module Symantic.XML.RelaxNG.Compact.Write+ ) where++import Symantic.XML.RelaxNG.Language+import Symantic.XML.RelaxNG.Compact.Write
+ src/Symantic/XML/RelaxNG/Compact/Write.hs view
@@ -0,0 +1,429 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE OverloadedStrings #-}+module Symantic.XML.RelaxNG.Compact.Write where++import Control.Applicative (Applicative(..), Alternative(..))+import Control.Monad (forM)+import Data.Bool+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..))+import Data.Function (($), (.), id, const)+import Data.Functor ((<$>))+import Data.Int (Int)+import Data.Maybe (Maybe(..), maybe, catMaybes, isNothing)+import Data.Monoid (Monoid(..))+import Data.Semigroup (Semigroup(..))+import Data.String (IsString(..), String)+import Numeric.Natural (Natural)+import Prelude (Integer)+import qualified Control.Monad.Trans.State.Strict as S+import qualified Data.HashMap.Strict as HM+import qualified Data.HashSet as HS+import qualified Data.List as List+import qualified Data.Map.Strict as Map+import qualified Data.Text as Text+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB++import Symantic.Base.Fixity+import Symantic.XML.Language+import Symantic.XML.RelaxNG.Language++-- | Get textual rendition of given 'RNCWriteSyn'.+writeRNC :: RNCWriteSyn a k -> TL.Text+writeRNC = TLB.toLazyText . runRNCWriteSyn++-- | Get textual rendition of given 'RNCWriteSyn'.+runRNCWriteSyn :: RNCWriteSyn a k -> TLB.Builder+runRNCWriteSyn RNCWriteSyn{..} =+  mconcat $+  List.concat+   [ [ "default namespace = \""<>textify (namespaces_default rncWriteInh_namespaces)<>"\"\n"+     | not $ TL.null $ unNamespace (namespaces_default rncWriteInh_namespaces)+     ]+   , [ "namespace "<>textify p<>" = \""<>textify n<>"\"\n"+     | (Namespace n, NCName p) <-+      HM.toList (namespaces_prefixes rncWriteInh_namespaces)+     ]+   , Map.foldrWithKey+     (\n v -> ((textify n<>" = "<>v<>"\n") :)) []+     defs+   ]+  where+  RNCWriteState{..} = rncWriteSyn_state $ RNCWriteState mempty mempty+  defs :: Map.Map DefineName TLB.Builder+  defs = Map.mapMaybe ($ inh) rncWriteState_defines+  inh = RNCWriteInh+   { rncWriteInh_namespaces+   , rncWriteInh_op = (infixN0, SideL)+   , rncWriteInh_pair = pairParen+   }+  rncWriteInh_namespaces :: Namespaces NCName+  rncWriteInh_namespaces = rncWriteState_namespaces+   { namespaces_prefixes =+    (`S.evalState` HS.empty) $+      forM prefixByNamespace $ \mp -> do+        usedPrefixes <- S.get+        let+         freshPrefix = maybe+           (freshNCName usedPrefixes)+           (freshifyNCName usedPrefixes)+           mp+        S.modify' $ HS.insert freshPrefix+        pure freshPrefix+   }+  prefixByNamespace :: HM.HashMap Namespace (Maybe NCName)+  prefixByNamespace =+    -- Add default prefixes if their 'Namespace' is used.+    HM.union+     (HM.intersectionWith (<|>)+       (namespaces_prefixes rncWriteState_namespaces)+       (Just <$> namespaces_prefixes defaultNamespaces)) $+    namespaces_prefixes rncWriteState_namespaces++-- * Type 'RNCWriteState'+-- | Chained values.+data RNCWriteState+ =   RNCWriteState+ {   rncWriteState_namespaces :: Namespaces (Maybe NCName)+     -- ^ The 'Namespaces' used throughout the 'RelaxNG' schema.+ ,   rncWriteState_defines    :: Map.Map DefineName (RNCWriteInh -> Maybe TLB.Builder)+     -- ^ Used to avoid infinite recursion,+     -- by looking up the 'DefineName' of 'define'.+ }++-- * Type 'RNCWriteSyn'+-- | Synthetized (bottom-up) values.+data RNCWriteSyn a k+ =   RNCWriteSyn+ {   rncWriteSyn_state  :: Chained RNCWriteState+ ,   rncWriteSyn_schema :: RNCWriteInh -> Maybe TLB.Builder+ }+instance IsString (RNCWriteSyn a k) where+  fromString s = RNCWriteSyn+   { rncWriteSyn_state = id+   , rncWriteSyn_schema = const $+    if List.null s then Nothing+    else Just (textify s)+   }++-- | Like the @State st ()@ monad, but without @()@.+-- The name comme from chained-attribute from Attribute Grammar.+type Chained a = a -> a++coerceRNCWriteSyn :: RNCWriteSyn a k -> RNCWriteSyn a' k'+coerceRNCWriteSyn RNCWriteSyn{..} = RNCWriteSyn{..}+{-# INLINE coerceRNCWriteSyn #-}++pairRNCWriteInh ::+ Semigroup s => IsString s =>+ RNCWriteInh -> Infix -> Maybe s -> Maybe s+pairRNCWriteInh inh op s =+  if isPairNeeded (rncWriteInh_op inh) op+  then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)+  else s+  where (o,c) = rncWriteInh_pair inh++-- ** Type 'RNCWriteInh'+-- Inherited (top-down) values.+data RNCWriteInh+ =   RNCWriteInh+ {   rncWriteInh_namespaces :: Namespaces NCName+ ,   rncWriteInh_op :: (Infix, Side)+ ,   rncWriteInh_pair :: Pair+ }++instance Emptyable RNCWriteSyn where+  empty = "empty"+instance Unitable RNCWriteSyn where+  unit = ""+instance Voidable RNCWriteSyn where+  void _a = coerceRNCWriteSyn+instance Constant RNCWriteSyn where+  constant _a = ""+instance Composable RNCWriteSyn where+  x <.> y = RNCWriteSyn+   (rncWriteSyn_state x . rncWriteSyn_state y) $ \inh ->+    let+     inh' side = inh+      { rncWriteInh_op   = (op, side)+      , rncWriteInh_pair = pairParen+      } in+    case rncWriteSyn_schema x (inh' SideL) of+     Nothing -> rncWriteSyn_schema y (inh' SideR)+     Just xw ->+      case rncWriteSyn_schema y (inh' SideR) of+       Nothing -> Just xw+       Just yw ->+        pairRNCWriteInh inh op $+          Just $ xw <> ", " <> yw+    where+    op = infixB SideL 2+instance Tupable RNCWriteSyn where+  x <:> y = coerceRNCWriteSyn x <.> coerceRNCWriteSyn y+instance Eitherable RNCWriteSyn where+  x <+> y = RNCWriteSyn+   (rncWriteSyn_state x . rncWriteSyn_state y) $ \inh ->+    pairRNCWriteInh inh op $+    rncWriteSyn_schema x inh+     { rncWriteInh_op   = (op, SideL)+     , rncWriteInh_pair = pairParen+     } <>+    Just " | " <>+    rncWriteSyn_schema y inh+     { rncWriteInh_op   = (op, SideR)+     , rncWriteInh_pair = pairParen+     }+    where op = infixB SideL 3+instance Optionable RNCWriteSyn where+  option = coerceRNCWriteSyn . optional . coerceRNCWriteSyn+  optional w = w{ rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh op $+    rncWriteSyn_schema w inh+     { rncWriteInh_op   = (op, SideL)+     , rncWriteInh_pair = pairParen+     } <> Just "?"+    }+    where op = infixN 9+instance Dimapable RNCWriteSyn where+  dimap _a2b _b2a = coerceRNCWriteSyn+instance Dicurryable RNCWriteSyn where+  dicurry _args _constr _destr = coerceRNCWriteSyn+instance Repeatable RNCWriteSyn where+  many0 w = w{ rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh op $+    rncWriteSyn_schema w inh+     { rncWriteInh_op   = (op, SideL)+     , rncWriteInh_pair = pairParen+     } <> Just "*"+    }+    where op = infixN 9+  many1 w = w{ rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh op $+    rncWriteSyn_schema w inh+     { rncWriteInh_op   = (op, SideL)+     , rncWriteInh_pair = pairParen+     } <> Just "+"+    }+    where op = infixN 9+instance Textable RNCWriteSyn where+  type TextConstraint RNCWriteSyn a = RNCText a+  text :: forall a k. TextConstraint RNCWriteSyn a => RNCWriteSyn (a -> k) k+  text = RNCWriteSyn+   { rncWriteSyn_state = \st ->+    case HM.lookup+     (qNameSpace (rncText_qname @a))+     (namespaces_prefixes (rncWriteState_namespaces st)) of+     Just{} -> st+     Nothing ->+      let ns = qNameSpace (rncText_qname @a) in+      if ns == xmlns_empty then st else st+       { rncWriteState_namespaces = (rncWriteState_namespaces st)+        { namespaces_prefixes =+        HM.insertWith (<|>) ns Nothing $+        namespaces_prefixes (rncWriteState_namespaces st) } }+   , rncWriteSyn_schema = \inh ->+    let n = rncText_qname @a in+    let t = if TL.null (unNamespace (qNameSpace n))+            then textify (qNameLocal n)+            else textify (prefixifyQName (rncWriteInh_namespaces inh) n)+    in if null (rncText_params @a)+    then Just t+    else+      pairRNCWriteInh inh (infixN 8) $+      Just $+      t<>" {"<>Map.foldMapWithKey+       (\k v -> " "<>textify k<>" = \""<>textify v<>"\"")+       (rncText_params @a)<>" }"+   }+instance XML RNCWriteSyn where+  namespace mp ns = RNCWriteSyn+   { rncWriteSyn_state = \st -> st+    { rncWriteState_namespaces =+      let nss = rncWriteState_namespaces st in+      Namespaces+       { namespaces_prefixes =+        HM.insertWith (<|>) ns mp (namespaces_prefixes nss)+       , namespaces_default =+        if isNothing mp+        then ns+        else namespaces_default nss+       }+    }+   , rncWriteSyn_schema = const Nothing+   }+  element n w = w+   { rncWriteSyn_state = \st ->+    rncWriteSyn_state w $ st+     { rncWriteState_namespaces = (rncWriteState_namespaces st)+       { namespaces_prefixes =+        -- Insert this 'qNameSpace' even if this is the default namespace,+        -- because the default namespace here may not end up+        -- being the global default namespace+        -- if there is a default 'namespace' declaration after this one.+        -- at worse this will just add a superfluous ns# declaration+        -- in the schema rendering.+        HM.insertWith (<|>) (qNameSpace n) Nothing+         (namespaces_prefixes (rncWriteState_namespaces st)) } }+   , rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh (infixN 8) $+    Just ("element "+     <> textify (prefixifyQName (rncWriteInh_namespaces inh) n)+     <> " {")+    <> rncWriteSyn_schema w inh+     { rncWriteInh_op   = (infixN0, SideR)+     , rncWriteInh_pair = pairBrace+     }+    <> Just "}"+   }+  attribute n w = w+   { rncWriteSyn_state = \st ->+    rncWriteSyn_state w $+    if qNameSpace n == xmlns_empty then st else st+     { rncWriteState_namespaces = (rncWriteState_namespaces st)+       { namespaces_prefixes =+        HM.insertWith (<|>) (qNameSpace n) Nothing+         (namespaces_prefixes (rncWriteState_namespaces st)) } }+   , rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh (infixN 8) $+    Just ("attribute "+     -- The namespace name for an unprefixed attribute name always has no value.+     <> textify (prefixifyQName (rncWriteInh_namespaces inh){namespaces_default=xmlns_empty} n)+     <> " {")+    <> rncWriteSyn_schema w inh+     { rncWriteInh_op   = (infixN0, SideR)+     , rncWriteInh_pair = pairBrace+     }+    <> Just "}"+   }+  literal lit = RNCWriteSyn+   { rncWriteSyn_state = id+   , rncWriteSyn_schema = \_inh -> Just ("\""<>textify lit<>"\"")+   }+  pi _n   = ""+  comment = ""+  cdata   = ""+instance Definable RNCWriteSyn where+  define n w = w+   { rncWriteSyn_state = \st ->+    let defs = rncWriteState_defines st in+    case Map.lookup n defs of+     Nothing ->+      rncWriteSyn_state w $ st+       { rncWriteState_defines =+        Map.insert n (rncWriteSyn_schema w) defs+       }+     Just{} -> st+   , rncWriteSyn_schema = const $ Just $ textify n+   }+instance Permutable RNCWriteSyn where+  type Permutation RNCWriteSyn = RNCWriteSynPerm+  permutable (RNCWriteSynPerm ps) = RNCWriteSyn+   { rncWriteSyn_state = List.foldl' (.) id (rncWriteSyn_state <$> ps)+   , rncWriteSyn_schema = case ps of+     [] -> const Nothing+     _ -> \inh ->+      case+        List.intersperse " & " $+        catMaybes $ (<$> ps) $ \w ->+          rncWriteSyn_schema w inh{rncWriteInh_op=(op, SideL)}+      of+       [] -> Nothing+       [x] -> Just x+       xs -> pairRNCWriteInh inh op $ Just $ mconcat xs+   }+    where op = infixR 3+  perm = RNCWriteSynPerm . pure+  noPerm = RNCWriteSynPerm []+  permWithDefault _def p = RNCWriteSynPerm+   [coerceRNCWriteSyn (optional p)]+instance RelaxNG RNCWriteSyn where+  elementMatch nc w = w+   { rncWriteSyn_state = \st ->+    rncWriteSyn_state w $ st+     { rncWriteState_namespaces = (rncWriteState_namespaces st)+       { namespaces_prefixes =+        namespacesNameClass nc <>+        namespaces_prefixes (rncWriteState_namespaces st)+       } }+   , rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh (infixN 8) $+    Just ("element "+     <> textify (rncWriteInh_namespaces inh, (infixN0,SideL), nc)+     <> " ")+    <> rncWriteSyn_schema w inh+     { rncWriteInh_op = (infixN 9, SideR)+     , rncWriteInh_pair = pairBrace+     }+   }+  attributeMatch nc w = w+   { rncWriteSyn_state = \st ->+    let nss = HM.delete xmlns_empty $ namespacesNameClass nc in+    rncWriteSyn_state w $+    if null nss then st else st+     { rncWriteState_namespaces = (rncWriteState_namespaces st)+       { namespaces_prefixes =+        HM.unionWith (<|>) nss $+        namespaces_prefixes (rncWriteState_namespaces st)+       } }+   , rncWriteSyn_schema = \inh ->+    pairRNCWriteInh inh (infixN 8) $+    Just ("attribute "+     <> textify ( (rncWriteInh_namespaces inh){namespaces_default=xmlns_empty}+              , (infixN0,SideL)+              , nc )+     <> " ")+    <> rncWriteSyn_schema w inh+     { rncWriteInh_op   = (infixN 9, SideR)+     , rncWriteInh_pair = pairBrace+     }+   }++-- ** Type 'RNCWriteSynPerm'+newtype RNCWriteSynPerm a k+ =      RNCWriteSynPerm+ {      rncWriteSynPerm_alternatives :: [RNCWriteSyn a k]+        -- ^ Collect alternatives for rendering+        -- them all at once in 'runPermutation'.+ }+instance Composable RNCWriteSynPerm where+  RNCWriteSynPerm x <.> RNCWriteSynPerm y =+    RNCWriteSynPerm $+      (coerceRNCWriteSyn <$> x) <>+      (coerceRNCWriteSyn <$> y)+instance Dimapable RNCWriteSynPerm where+  dimap _a2b _b2a (RNCWriteSynPerm x) =+    RNCWriteSynPerm (coerceRNCWriteSyn <$> x)+instance Tupable RNCWriteSynPerm where+  RNCWriteSynPerm x <:> RNCWriteSynPerm y =+    RNCWriteSynPerm $+      (coerceRNCWriteSyn <$> x) <>+      (coerceRNCWriteSyn <$> y)+instance Definable RNCWriteSynPerm where+  define n (RNCWriteSynPerm ps) =+    RNCWriteSynPerm $ pure $+      coerceRNCWriteSyn $ define n $+        permutable $ RNCWriteSynPerm $+          coerceRNCWriteSyn <$> ps++-- * Class 'RNCText'+class RNCText a where+  rncText_qname  :: QName+  rncText_params :: Map.Map TL.Text TL.Text+  rncText_params = mempty+instance RNCText String where+  rncText_qname = QName (Namespace "") "text"+instance RNCText Text.Text where+  rncText_qname = QName (Namespace "") "text"+instance RNCText TL.Text where+  rncText_qname = QName (Namespace "") "text"+instance RNCText Bool where+  rncText_qname = QName xmlns_xsd "boolean"+instance RNCText Int where+  rncText_qname = QName xmlns_xsd "int"+instance RNCText Integer where+  rncText_qname = QName xmlns_xsd "integer"+instance RNCText Natural where+  rncText_qname = QName xmlns_xsd "nonNegativeInteger"
+ src/Symantic/XML/RelaxNG/Language.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE OverloadedStrings #-}+module Symantic.XML.RelaxNG.Language where++import Data.Bool+import Data.Eq (Eq(..))+import Data.Function (($), (.))+import Data.Maybe (Maybe(..))+import Data.Semigroup (Semigroup(..))+import Data.String (String, IsString(..))+import Prelude (error)+import Text.Show (Show(..))+import qualified Data.List as List+import qualified Data.HashMap.Strict as HM++import Symantic.Base.Fixity+import Symantic.XML.Language++-- * Class 'RelaxNG'+class+ ( XML repr+ , Permutable repr+ , Definable repr+ ) => RelaxNG repr where+  default elementMatch ::+                  Transformable repr =>+                  RelaxNG (UnTrans repr) =>+                  NameClass -> repr a k -> repr (QName -> a) k+  -- | Like 'element' but with a matching pattern+  -- instead of a specific 'QName'.+  elementMatch :: NameClass -> repr a k -> repr (QName -> a) k+  elementMatch nc = noTrans . elementMatch nc . unTrans+  default attributeMatch ::+                  Transformable repr =>+                  RelaxNG (UnTrans repr) =>+                  NameClass -> repr a k -> repr (QName -> a) k+  -- | Like 'attribute' but with a matching pattern+  -- instead of a specific 'QName'.+  attributeMatch :: NameClass -> repr a k -> repr (QName -> a) k+  attributeMatch nc = noTrans . attributeMatch nc . unTrans++-- * Type 'Definable'+class Definable repr where+  -- | @(define name expr)@ declares a rule named @(name)@+  -- and matching the 'RelaxNG' schema @(expr)@.+  --+  -- Useful for rendering the 'RelaxNG' schema,+  -- and necessary to avoid infinite recursion when+  -- printing a 'RelaxNG' schema calling itself recursively.+  --+  -- WARNING: 'DefineName's must be unique inside+  -- a whole 'RelaxNG' schema.+  define :: DefineName -> repr a k -> repr a k+  default define ::+   Transformable repr => RelaxNG (UnTrans repr) =>+   DefineName -> repr f k -> repr f k+  define n = noTrans . define n . unTrans++-- ** Type 'DefineName'+type DefineName = String++-- * Type 'NameClass'+data NameClass+ =   NameClass_Any+ |   (:::) Namespace NCName+ |   (:*) Namespace+ |   (:-:) NameClass NameClass+ |   (:|:) NameClass NameClass++infix 9 :::+infixr 2 :|:+infixl 6 :-:++(*:*) :: NameClass+(*:*) = NameClass_Any++-- | @('matchNameClass' nc q)@ returns 'True' iif. the 'NameClass' @(nc)@ matches the 'QName' @(q)@.+matchNameClass :: NameClass -> QName -> Bool+matchNameClass NameClass_Any _q = True+matchNameClass (ns:::nl) q = qNameSpace q == ns && qNameLocal q == nl+matchNameClass ((:*) ns) q = qNameSpace q == ns+matchNameClass (x:|:y) q = matchNameClass x q || matchNameClass y q+matchNameClass (x:-:y) q = matchNameClass x q && not (matchNameClass y q)++-- | Return the namespaces used by the given 'NameClass'+namespacesNameClass :: NameClass -> HM.HashMap Namespace (Maybe NCName)+namespacesNameClass = \case+ NameClass_Any -> HM.empty+ ns ::: _ -> HM.singleton ns Nothing+ (:*) ns -> HM.singleton ns Nothing+ x :|: y -> namespacesNameClass x <> namespacesNameClass y+ x :-: y -> namespacesNameClass x <> namespacesNameClass y++-- | Only parses "*", "{some-namespace}*", or "{some-namespace}some-localname".+instance IsString NameClass where+  fromString = \case+   "*" -> NameClass_Any+   full@('{':rest) ->+    case List.break (== '}') rest of+     (_, "") -> error $ "Invalid XML Clark notation: "<>show full+     (ns, "*") -> (:*) (fromString ns)+     (ns, local) -> fromString ns ::: fromString (List.drop 1 local)+   s -> let QName ns nl = fromString s in ns:::nl+instance Textify (Namespaces NCName, (Infix,Side), NameClass) where+  textify (nss,po,nc) = case nc of+   NameClass_Any -> textify '*'+   ns:::nl ->+    textify (prefixifyQName nss (QName ns nl))+   (:*) ns ->+    case HM.lookup ns (namespaces_prefixes nss) of+     Nothing -> "{"<>textify ns<>"}*"+     Just p -> textify p <> ":*"+   x :|: y -> pairIfNeeded pairParen po op $+    textify (nss,(op,SideL),x) <> " | " <> textify (nss,(op,SideR),y)+    where op = infixR 2+   x :-: y ->+    pairIfNeeded pairParen po op $+    textify (nss,(op,SideL),x) <> " - " <> textify (nss,(op,SideR),y)+    where op = infixL 6
+ src/Symantic/XML/Text.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+module Symantic.XML.Text where++import Data.Bool+import Data.Char (Char)+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..))+import Data.Function (($), (.))+import Data.Maybe (Maybe(..))+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Semigroup (Semigroup(..))+import Data.Sequence (Seq)+import Data.String (IsString(..), String)+import Text.Show (Show(..))+import qualified Data.Char as Char+import qualified Data.List as List+import qualified Data.Sequence as Seq+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB++import Symantic.XML.Namespace++-- * Type 'Escaped'+-- | 'EscapedText' lexemes.+data Escaped+ =   EscapedPlain     TL.Text+ |   EscapedEntityRef EntityRef+ |   EscapedCharRef   CharRef+ deriving (Eq, Ord, Show)++-- ** Type 'EntityRef'+data EntityRef+ =   EntityRef+ {   entityRef_name  :: NCName+ ,   entityRef_value :: TL.Text+ } deriving (Eq, Ord, Show)++entityRef_lt,+ entityRef_gt,+ entityRef_amp,+ entityRef_quot,+ entityRef_apos :: EntityRef+entityRef_lt   = EntityRef (NCName "lt") "<"+entityRef_gt   = EntityRef (NCName "gt") ">"+entityRef_amp  = EntityRef (NCName "amp") "&"+entityRef_quot = EntityRef (NCName "quot") "\""+entityRef_apos = EntityRef (NCName "apos") "'"++-- ** Type 'CharRef'+newtype CharRef = CharRef Char+ deriving (Eq, Ord, Show)++-- * Type 'EscapedText'+newtype EscapedText = EscapedText (Seq Escaped)+ deriving (Eq, Ord, Show)++instance IsString EscapedText where+  fromString = escapeText . fromString++unEscapedText :: EscapedText -> Seq Escaped+unEscapedText (EscapedText et) = et+{-# INLINE unEscapedText #-}++escapeText :: TL.Text -> EscapedText+escapeText s =+  EscapedText $+  -- Add '>' to escape "]]>" without adding a 'TL.replace'.+  case TL.span (`List.notElem` ("<&>"::String)) s of+   (t, r) | TL.null t -> escape r+          | otherwise -> EscapedPlain t Seq.<| escape r+  where+  escape t = case TL.uncons t of+   Nothing -> mempty+   Just (c, cs) -> escapeTextChar c Seq.<| et+     where EscapedText et = escapeText cs++escapeTextChar :: Char -> Escaped+escapeTextChar = \case+ '<'  -> EscapedEntityRef entityRef_lt+ '&'  -> EscapedEntityRef entityRef_amp+  -- Add '>' to escape "]]>".+ '>'  -> EscapedEntityRef entityRef_gt+ c    -> EscapedPlain $ TL.singleton c++unescapeText :: EscapedText -> TL.Text+unescapeText (EscapedText et) = (`foldMap` et) $ \case+ EscapedPlain t -> t+ EscapedEntityRef EntityRef{..} -> entityRef_value+ EscapedCharRef (CharRef c) -> TL.singleton c++-- * Type 'EscapedAttr'+newtype EscapedAttr = EscapedAttr (Seq Escaped)+ deriving (Eq, Ord, Show)++instance IsString EscapedAttr where+  fromString = escapeAttr . fromString++unEscapedAttr :: EscapedAttr -> Seq Escaped+unEscapedAttr (EscapedAttr et) = et+{-# INLINE unEscapedAttr #-}++escapeAttr :: TL.Text -> EscapedAttr+escapeAttr s =+  EscapedAttr $+  case TL.span (`List.notElem` ("<&\""::String)) s of+   (t, r) | TL.null t -> escape r+          | otherwise -> EscapedPlain t Seq.<| escape r+  where+  escape t = case TL.uncons t of+   Nothing -> mempty+   Just (c, cs) -> escapeAttrChar c Seq.<| et+     where EscapedAttr et = escapeAttr cs++escapeAttrChar :: Char -> Escaped+escapeAttrChar = \case+ '<'  -> EscapedEntityRef entityRef_lt+ '&'  -> EscapedEntityRef entityRef_amp+ -- Remove '\'' because 'textifyAttr' uses '"' for quoting.+ -- '\'' -> EscapedEntityRef entityRef_apos+ '"'  -> EscapedEntityRef entityRef_quot+ c    -> EscapedPlain $ TL.singleton c++unescapeAttr :: EscapedAttr -> TL.Text+unescapeAttr (EscapedAttr et) = unescapeText (EscapedText et)++-- * Class 'Textify'+class Textify a where+  textify :: a -> TLB.Builder+instance Textify Char.Char where+  textify = TLB.singleton+instance Textify String where+  textify = TLB.fromString+instance Textify TL.Text where+  textify = TLB.fromLazyText+instance Textify NCName where+  textify = textify . unNCName+instance Textify PName where+  textify PName{..} =+    case pNameSpace of+     Nothing -> textify pNameLocal+     Just p -> textify p<>":"<> textify pNameLocal+instance Textify Namespace where+  textify = textify . unNamespace+instance Textify EntityRef where+  textify EntityRef{..} = "&"<>textify entityRef_name<>";"+instance Textify CharRef where+  textify (CharRef c) = "&#"<>textify (show (Char.ord c))<>";"+instance Textify EscapedText where+  textify (EscapedText et) = (`foldMap` et) $ \case+   EscapedPlain     t -> textify t+   EscapedEntityRef r -> textify r+   EscapedCharRef   r -> textify r+instance Textify EscapedAttr where+  textify (EscapedAttr et) = "\""<>txt<>"\""+    where+    txt = (`foldMap` et) $ \case+     EscapedPlain     t -> textify t+     EscapedEntityRef r -> textify r+     EscapedCharRef   r -> textify r++textifyAttr :: PName -> EscapedAttr -> TLB.Builder+textifyAttr n v = " "<>textify n<>"="<>textify v
+ src/Symantic/XML/Tree.hs view
@@ -0,0 +1,11 @@+module Symantic.XML.Tree+ ( module Symantic.XML.Tree.Source+ , module Symantic.XML.Tree.Data+ , module Symantic.XML.Tree.Read+ , module Symantic.XML.Tree.Write+ ) where++import Symantic.XML.Tree.Source+import Symantic.XML.Tree.Data+import Symantic.XML.Tree.Read+import Symantic.XML.Tree.Write
+ src/Symantic/XML/Tree/Data.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Symantic.XML.Tree.Data+ ( module Symantic.XML.Tree.Data+ , TS.unTree+ , TS.subTrees+ ) where++import Control.Applicative (Applicative(..))+import Data.Bool+import Data.Either (Either(..))+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..))+import Data.Function (($), id)+import Data.Functor ((<$>))+import Data.Functor.Identity (Identity(..))+import Data.Maybe (Maybe(..))+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Semigroup (Semigroup(..))+import Prelude (error)+import Text.Show (Show(..))+import qualified Data.HashMap.Strict as HM+import qualified Data.Sequence as Seq+import qualified Data.Text.Lazy as TL+import qualified Data.TreeSeq.Strict as TS++import Symantic.Base+import Symantic.XML.Language+import Symantic.XML.RelaxNG.Language+import Symantic.XML.Write+import Symantic.XML.Tree.Source++-- * Type 'Tree'+type Tree src = TS.Tree (src (Node (src EscapedAttr)))++-- ** Type 'Trees'+type Trees src = TS.Trees (src (Node (src EscapedAttr)))++pattern Tree0 :: a -> TS.Tree a+pattern Tree0 a <- TS.Tree a (null -> True)+  where Tree0 a = TS.Tree a Seq.empty++-- ** Type 'Node'+data Node attr+   = NodeElem    QName (HM.HashMap QName attr) -- ^ Node.+   | NodePI      PName TL.Text -- ^ Leaf (except for @<?xml?>@ which has 'NodePI' children.+   | NodeText    EscapedText   -- ^ Leaf.+   | NodeComment TL.Text       -- ^ Leaf.+   | NodeCDATA   TL.Text       -- ^ Leaf.+   deriving (Eq, Ord, Show)++-- * Type 'TreeData'+newtype TreeData params k+ =      TreeData+ {    unTreeData :: ( HM.HashMap QName (Identity EscapedAttr) ->+                      TL.Text ->+                      Trees Identity -> k+                    ) -> params }++tree :: TreeData callers (Trees Identity) -> callers+tree (TreeData callers) = callers (\_as _txt ts -> ts)++type SourcedTree  src = Tree  (Sourced src)+type SourcedTrees src = Trees (Sourced src)+type FileSourcedTree  = SourcedTree  (FileSource Offset)+type FileSourcedTrees = SourcedTrees (FileSource Offset)++-- | Unify two 'Trees', merging border 'NodeText's if any.+union ::+ Semigroup (Sourced src EscapedText) =>+ SourcedTrees src -> SourcedTrees src -> SourcedTrees src+union x y =+  case (Seq.viewr x, Seq.viewl y) of+   (xs Seq.:> x0, y0 Seq.:< ys) ->+    case (x0,y0) of+     (  Tree0 (Sourced sx (NodeText tx))+      , Tree0 (Sourced sy (NodeText ty)) ) ->+      xs `union`+      Seq.singleton (Tree0 $ (NodeText <$>) $+        Sourced sx tx <> Sourced sy ty) `union`+      ys+     _ -> x <> y+   (Seq.EmptyR, _) -> y+   (_, Seq.EmptyL) -> x++unions ::+ Semigroup (Sourced src EscapedText) =>+ Foldable f => f (SourcedTrees src) -> SourcedTrees src+unions = foldl' union mempty++instance Emptyable TreeData where+  empty = TreeData (\k -> k mempty mempty mempty)+instance Unitable TreeData where+  unit = TreeData (\k () -> k mempty mempty mempty)+instance Voidable TreeData where+  void a (TreeData x) = TreeData (`x` a)+instance Dimapable TreeData where+  dimap _a2b b2a (TreeData x) = TreeData $ \k b ->+    x k (b2a b)+instance Dicurryable TreeData where+  dicurry (_::proxy args) _construct destruct (TreeData x) = TreeData $ \k r ->+    uncurryN @args (x k) (destruct r)+instance Composable TreeData where+  TreeData x <.> TreeData y = TreeData $ \k ->+    x (\ax vx tx -> y (\ay vy ty -> k (ax<>ay) (vx<>vy) (tx<>ty)))+instance Tupable TreeData where+  TreeData x <:> TreeData y = TreeData $ \k (a,b) ->+    x (\ax vx tx -> y (\ay vy ty -> k (ax<>ay) (vx<>vy) (tx<>ty)) b) a+instance Eitherable TreeData where+  TreeData x <+> TreeData y = TreeData $ \k -> \case+   Left  a -> x k a+   Right b -> y k b+instance Constant TreeData where+  constant _a = TreeData $ \k _a -> k mempty mempty mempty+instance Optionable TreeData where+  option = id+  optional (TreeData x) = TreeData $ \k ->+    \case+     Nothing -> k mempty mempty mempty+     Just a -> x k a+{-+instance Routable TreeData where+  TreeData x <!> TreeData y = TreeData $ \k ->+    x k :!: y k+-}+instance Repeatable TreeData where+  many0 (TreeData x) = TreeData $ \k -> \case+   [] -> k mempty mempty mempty+   a:as -> x (\ax vx tx ->+    unTreeData (many0 (TreeData x))+     (\aas vas tas -> k (ax<>aas) (vx<>vas) (tx<>tas)) as) a+  many1 (TreeData x) = TreeData $ \k -> \case+   [] -> k mempty mempty mempty+   a:as -> x (\ax vx tx ->+    unTreeData (many1 (TreeData x))+     (\aas vas tas -> k (ax<>aas) (vx<>vas) (tx<>tas)) as) a+instance Textable TreeData where+  type TextConstraint TreeData a = EncodeText a+  text = TreeData $ \k v ->+    let t = encodeText v in+    k mempty t $ pure $+      TS.Tree (Identity (NodeText (escapeText t))) mempty+instance XML TreeData where+  namespace _nm _ns = empty+  element n (TreeData x) = TreeData $ \k ->+    x $ \as _txt ts ->+      k mempty mempty $ pure $+        TS.Tree (Identity (NodeElem n as)) ts+  attribute n (TreeData x) = TreeData $ \k ->+    x $ \as txt _ts ->+      k (HM.insert n (Identity (escapeAttr txt)) as) mempty mempty+  literal lit = TreeData $ \k ->+    k mempty lit $ pure $+      TS.Tree (Identity (NodeText (escapeText lit))) mempty+  pi n = TreeData $ \k v ->+    k mempty mempty $ pure $+      TS.Tree (Identity (NodePI n v)) mempty+  comment = TreeData $ \k v ->+    k mempty mempty $ pure $+      TS.Tree (Identity (NodeComment v)) mempty+  cdata = TreeData $ \k v ->+    k mempty mempty $ pure $+      TS.Tree (Identity (NodeCDATA v)) mempty+instance Permutable TreeData where+  type Permutation TreeData = TreeDataPerm TreeData+  permutable = unTreeDataPerm+  perm = TreeDataPerm+  noPerm = TreeDataPerm empty+  permWithDefault _a = TreeDataPerm+instance Definable TreeData where+  define _n = id+instance RelaxNG TreeData where+  elementMatch nc x = TreeData $ \k n ->+    if matchNameClass nc n+    then error "elementMatch: given QName does not match expected NameClass"+    else unTreeData (element n x) k+  attributeMatch nc x = TreeData $ \k n ->+    if matchNameClass nc n+    then error "attributeMatch: given QName does not match expected NameClass"+    else unTreeData (attribute n x) k++-- ** Type 'TreeDataPerm'+newtype TreeDataPerm repr xml k+ =      TreeDataPerm+ {    unTreeDataPerm :: repr xml k }+instance Transformable (TreeDataPerm repr) where+  type UnTrans (TreeDataPerm repr) = repr+  noTrans = TreeDataPerm+  unTrans = unTreeDataPerm+instance Dimapable (TreeDataPerm TreeData)+instance Composable (TreeDataPerm TreeData)+instance Tupable (TreeDataPerm TreeData)
+ src/Symantic/XML/Tree/Read.hs view
@@ -0,0 +1,628 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Symantic.XML.Tree.Read where++import Control.Arrow (left)+import Control.Applicative (Applicative(..), Alternative(..))+import Control.Monad (Monad(..), void, unless, forM)+import Data.Bool+import Data.Char (Char)+import Data.Either (Either(..))+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..))+import Data.Function (($), (.), const)+import Data.Functor ((<$>), (<$))+import Data.Maybe (Maybe(..), maybe, catMaybes)+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Semigroup (Semigroup(..))+import Data.List.NonEmpty (NonEmpty(..))+import Data.String (String, IsString(..))+import Prelude (Num(..), Enum(..), Bounded(..), Integer, toInteger)+import System.IO (FilePath, IO)+import Text.Show (Show(..))+import qualified Control.Exception as Exn+import qualified Control.Monad.Trans.Reader as R+import qualified Data.ByteString.Lazy as BSL+import qualified Data.Char as Char+import qualified Data.Char.Properties.XMLCharProps as XC+import qualified Data.HashMap.Strict as HM+import qualified Data.List as List+import qualified Data.Set as Set+import qualified Data.Sequence as Seq+import qualified Data.Text.Encoding.Error as TL+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TL+import qualified Data.TreeSeq.Strict as TS+import qualified System.IO.Error as IO+import qualified Text.Megaparsec as P+import qualified Text.Megaparsec.Char as P++import Symantic.Base ()+import Symantic.XML.Language hiding (void)+import Symantic.XML.Tree.Source+import Symantic.XML.Tree.Data++readTree :: FilePath -> IO (Either String FileSourcedTrees)+readTree path =+  readUtf8 path >>= \case+   Left err -> return $ Left $ show err+   Right txt -> return $+    case runReadTree path txt of+     Right a -> Right a+     Left err -> Left $ P.errorBundlePretty err++runReadTree ::+ FilePath -> TL.Text ->+ Either (P.ParseErrorBundle TL.Text Error)+        FileSourcedTrees+runReadTree = P.runParser $ R.runReaderT p_document defaultReadTreeInh++-- * Type 'ErrorRead'+data ErrorRead+ =   ErrorRead_IO IO.IOError+ |   ErrorRead_Unicode TL.UnicodeException+ deriving (Show)+readUtf8 :: FilePath -> IO (Either ErrorRead TL.Text)+readUtf8 path =+  (left ErrorRead_Unicode . TL.decodeUtf8' <$> BSL.readFile path)+  `Exn.catch` \e ->+    if IO.isAlreadyInUseError e+    || IO.isDoesNotExistError e+    || IO.isPermissionError   e+    then return $ Left $ ErrorRead_IO e+    else IO.ioError e++-- * Type 'ReadTree'+-- | Convenient alias.+type ReadTree e s a =+ ReadTreeConstraints e s a =>+ R.ReaderT ReadTreeInh (P.Parsec e s) a++-- ** Type 'ReadTreeConstraints'+type ReadTreeConstraints e s a =+ ( P.Stream s+ , P.Token s ~ Char+ , Ord e+ , IsString (P.Tokens s)+ , P.ShowErrorComponent e+ )++-- ** Type 'ReadTreeInh'+data ReadTreeInh+ =   ReadTreeInh+ {   readTreeInh_source     :: FileSource Offset+ ,   readTreeInh_ns_scope   :: HM.HashMap NCName Namespace+ ,   readTreeInh_ns_default :: Namespace+ } deriving (Show)++defaultReadTreeInh :: ReadTreeInh+defaultReadTreeInh = ReadTreeInh+ { readTreeInh_source = FileSource $ pure $+  FileRange mempty mempty mempty+ , readTreeInh_ns_scope = HM.fromList+   [ ("xml"  , xmlns_xml)+   , ("xmlns", xmlns_xmlns)+   ]+ , readTreeInh_ns_default = ""+ }++p_Offset :: ReadTree e s Offset+p_Offset = Offset <$> P.getOffset+{-# INLINE p_Offset #-}++p_Sourced :: ReadTree e s a -> ReadTree e s (Sourced (FileSource Offset) a)+p_Sourced pa = do+  ReadTreeInh{readTreeInh_source} <- R.ask+  b <- P.getParserState+  let fileRange_path = P.sourceName $ P.pstateSourcePos $ P.statePosState b+  let fileRange_begin = Offset $ P.stateOffset b+  a <- pa+  e <- P.getParserState+  let fileRange_end = Offset $ P.stateOffset e+  return $ Sourced (setSource FileRange{..} readTreeInh_source) a++setSource :: FileRange pos -> FileSource pos -> FileSource pos+setSource fileRange (FileSource (_curr:|next)) = FileSource (fileRange:|next)++-- | Like 'p_Sourced' but uncoupled (through the use of 'p_SourcedEnd') for more flexibility.+p_SourcedBegin :: ReadTree e s a -> ReadTree e s a+p_SourcedBegin pa = do+  b <- P.getParserState+  let fileRange_path  = P.sourceName $ P.pstateSourcePos $ P.statePosState b+  let fileRange_begin = Offset $ P.stateOffset b+  let fileRange_end   = fileRange_begin+  (`R.local` pa) $ \inh@ReadTreeInh{..} ->+    inh{ readTreeInh_source = setSource FileRange{..} readTreeInh_source }++-- | WARNING: only to be used within a 'p_SourcedBegin'.+p_SourcedEnd :: ReadTree e s (a -> Sourced (FileSource Offset) a)+p_SourcedEnd = do+  ReadTreeInh{..} <- R.ask+  e <- P.getParserState+  let fileRange_end = Offset $ P.stateOffset e+  return $ Sourced $+     (\(FileSource (curr:|path)) -> FileSource (curr{fileRange_end}:|path))+     readTreeInh_source++-- * Type 'Error'+data Error+ =   Error_CharRef_invalid Integer+     -- ^ Well-formedness constraint: Legal Character.+     --+     -- Characters referred to using character references MUST match the production for Char.+ |   Error_EntityRef_unknown NCName+     -- ^ Well-formedness constraint: Entity Declared+     --+     -- In a document without any DTD, a document with only an internal DTD+     -- subset which contains no parameter entity references, or a document+     -- with " standalone='yes' ", for an entity reference that does not occur+     -- within the external subset or a parameter entity, the Name given in the+     -- entity reference MUST match that in an entity declaration that does not+     -- occur within the external subset or a parameter entity, except that+     -- well-formed documents need not declare any of the following entities:+     -- amp, lt, gt, apos, quot. The declaration of a general entity MUST+     -- precede any reference to it which appears in a default value in an+     -- attribute-list declaration.+     --+     -- Note that non-validating processors are not obligated to read and+     -- process entity declarations occurring in parameter entities or in the+     -- external subset; for such documents, the define that an entity must be+     -- declared is a well-formedness constraint only if standalone='yes'.+ |   Error_Closing_tag_unexpected QName QName+     -- ^ Well-formedness constraint: Element Type Match.+     --+     -- The Name in an element's end-tag MUST match the element type in the start-tag.+ |   Error_Attribute_collision QName+     -- ^ Well-formedness constraint: Unique Att Spec.+     --+     -- An attribute name MUST NOT appear more than once in the same start-tag or empty-element tag.+ |   Error_PI_reserved PName+     -- ^ The target names " XML ", " xml ", and so on are reserved for standardization.+ |   Error_Namespace_prefix_unknown NCName+     -- ^ Namespace constraint: Prefix Declared+     --+     -- The namespace prefix, unless it is xml or xmlns, MUST have been declared in a namespace declaration attribute in either the start-tag of the element where the prefix is used or in an ancestor element (i.e., an element in whose content the prefixed markup occurs). + |   Error_Namespace_empty NCName+     -- ^ Namespace constraint: No Prefix Undeclaring+     --+     -- In a namespace declaration for a prefix (i.e., where the NSAttName is a PrefixedAttName), the attribute value MUST NOT be empty.+ |   Error_Namespace_reserved Namespace+ |   Error_Namespace_reserved_prefix NCName+     -- ^ Namespace constraint: Reserved Prefixes and Namespace Names+     --+     -- The prefix xml is by definition bound to the namespace name+     -- http://www.w3.org/XML/1998/namespace. It MAY, but need not, be+     -- declared, and MUST NOT be bound to any other namespace name. Other+     -- prefixes MUST NOT be bound to this namespace name, and it MUST NOT be+     -- declared as the default namespace.+     --+     -- The prefix xmlns is used only to declare namespace bindings and is by+     -- definition bound to the namespace name http://www.w3.org/2000/xmlns/.+     -- It MUST NOT be declared . Other prefixes MUST NOT be bound to this+     -- namespace name, and it MUST NOT be declared as the default namespace.+     -- Element names MUST NOT have the prefix xmlns.+     --+     -- All other prefixes beginning with the three-letter sequence x, m, l, in+     -- any case combination, are reserved. This means that:+     --+     -- - users SHOULD NOT use them except as defined by later specifications+     -- - processors MUST NOT treat them as fatal errors.+ deriving (Eq,Ord,Show)+instance P.ShowErrorComponent Error where+  showErrorComponent = show++-- * Helpers+p_error :: e -> ReadTree e s a+p_error = P.fancyFailure . Set.singleton . P.ErrorCustom++p_quoted :: P.Tokens s ~ TL.Text => (Char -> ReadTree e s a) -> ReadTree e s a+p_quoted p =+  P.between (P.char '"') (P.char '"') (p '"') <|>+  P.between (P.char '\'') (P.char '\'') (p '\'')++p_until ::+ P.Tokens s ~ TL.Text =>+ (Char -> Bool) -> (Char, TL.Text) -> ReadTree e s TL.Text+p_until content (end, end_) =+  (TL.concat <$>) $ P.many $+    P.takeWhile1P Nothing (\c -> content c && c /= end) <|>+    P.try (TL.singleton <$> P.char end <* P.notFollowedBy (P.string end_))++p_until1 ::+ P.Tokens s ~ TL.Text =>+ (Char -> Bool) -> (Char, TL.Text) -> ReadTree e s TL.Text+p_until1 content (end, end_) =+  (TL.concat <$>) $ P.some $+    P.takeWhile1P Nothing (\c -> content c && c /= end) <|>+    P.try (TL.singleton <$> P.char end <* P.notFollowedBy (P.string end_))++-- * Document+p_document :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTrees+p_document = do+  ps <- p_prolog+  e  <- p_Element+  m  <- p_Miscs+  P.eof+  return (ps <> pure e <> m)++-- ** Prolog+p_prolog :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTrees+p_prolog = (<>)+ <$> P.option Seq.empty (pure <$> p_XMLDecl)+ <*> p_Miscs++-- ** Misc+p_Miscs :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTrees+p_Miscs = (Seq.fromList . catMaybes <$>) $ P.many $+  Just <$> p_Comment <|>+  Just <$> p_PI <|>+  Nothing <$ p_Spaces1++-- ** XMLDecl+p_XMLDecl :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_XMLDecl = do+  Sourced src as <- p_Sourced $ P.between (P.string "<?xml") (P.string "?>") $ do+    vi <- pure <$> p_VersionInfo+    ed <- P.option Seq.empty $ pure <$> p_EncodingDecl+    sd <- P.option Seq.empty $ pure <$> p_SDDecl+    p_Spaces+    return $ vi <> ed <> sd+  return $ TS.Tree (Sourced src $ NodePI "xml" "") as++p_VersionInfo :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_VersionInfo = do+  Sourced src v <- p_Sourced $ do+    P.try $ p_Spaces1 <* P.string "version"+    p_Eq+    p_quoted $ const $+      (<>)+       <$> P.string "1."+       <*> P.takeWhile1P Nothing Char.isDigit+  return $ TS.tree0 $ Sourced src $ NodePI "version" v++p_EncodingDecl :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_EncodingDecl = do+  Sourced src v <- p_Sourced $ do+    P.try $ p_Spaces1 <* P.string "encoding"+    p_Eq+    p_quoted $ const p_EncName+  return $ TS.tree0 $ Sourced src $ NodePI "encoding" v++p_EncName :: P.Tokens s ~ TL.Text => ReadTree Error s TL.Text+p_EncName = P.label "EncName" $ do+  P.notFollowedBy (P.satisfy $ not . isAlpha)+  P.takeWhile1P Nothing $ \c ->+    isAlpha c || Char.isDigit c ||+    c=='.' || c=='_' || c=='-'+  where isAlpha c = Char.isAsciiLower c || Char.isAsciiUpper c++-- *** SDDecl+p_SDDecl :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_SDDecl = do+  Sourced src v <- p_Sourced $ do+    P.try $ p_Spaces1 <* P.string "standalone"+    p_Eq+    p_quoted $ const $ P.string "yes" <|> P.string "no"+  return $ TS.tree0 $ Sourced src $ NodePI "standalone" v++-- ** CharData+p_CharData :: P.Tokens s ~ TL.Text => ReadTree e s EscapedText+p_CharData = P.label "[^<&]" $ escapeText <$>+  p_until1 (\c -> XC.isXmlChar c && c/='<' && c/='&') (']',"]>")++-- ** Comment+p_Comment :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_Comment = p_SourcedBegin $ P.string "<!--" *> p_Comment__+p_Comment_ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_Comment_ = P.string "--" *> p_Comment__+p_Comment__:: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_Comment__ = do+  c <- p_until XC.isXmlChar ('-', "-")+  void $ P.string "-->"+  src <- p_SourcedEnd+  return $ TS.tree0 $ src $ NodeComment c++-- ** CDATA+p_CDSect :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_CDSect = p_SourcedBegin $ P.string "<![CDATA[" *> p_CDSect__+p_CDSect_ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_CDSect_ = P.string "[CDATA[" *> p_CDSect__+p_CDSect__ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_CDSect__ = do+  c <- p_until XC.isXmlChar (']', "]>")+  void $ P.string "]]>"+  src <- p_SourcedEnd+  return $ TS.tree0 $ src $ NodeCDATA c++-- ** PI+p_PI :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_PI = p_SourcedBegin $ P.string "<?" *> p_PI__+p_PI_ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_PI_ = P.char '?' *> p_PI__+p_PI__ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_PI__ = do+  n <- p_PITarget+  v <- P.option "" $ p_Spaces1 *> p_until XC.isXmlChar ('?', ">")+  void $ P.string "?>"+  src <- p_SourcedEnd+  return $ TS.tree0 $ src $ NodePI n v+p_PITarget :: P.Tokens s ~ TL.Text => ReadTree Error s PName+p_PITarget = do+  n <- p_PName+  case n of+   PName{pNameSpace=Nothing, pNameLocal=NCName l}+    | "xml" == TL.toLower l -> p_error $ Error_PI_reserved n+   _ -> return n++-- ** Element+p_Element :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_Element = p_SourcedBegin $ (P.char '<' *> p_Element_)+p_Element_ :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_Element_ = p_STag++-- *** STag+p_STag :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTree+p_STag = do+  n  <- p_PName+  attrs <- P.many $ p_Attribute+  p_Spaces+  ro <- R.ask+  elemNS :: HM.HashMap NCName Namespace <-+    (HM.fromList . List.concat <$>) $ forM attrs $ \case+     (PName{..}, Sourced _ av)+      | ns <- Namespace $ unescapeAttr av+      , Nothing        <- pNameSpace+      , NCName "xmlns" <- pNameLocal ->+      -- Default namespace declaration+      case ns of+       _ |  ns == xmlns_xml   -- DOC: it MUST NOT be declared as the default namespace+         || ns == xmlns_xmlns -- DOC: it MUST NOT be declared as the default namespace+         -> p_error $ Error_Namespace_reserved ns+       _ -> return [(NCName "" , ns)]+      | ns <- Namespace $ unescapeAttr av+      , Just (NCName "xmlns") <- pNameSpace ->+      -- Namespace prefix declaration+      case unNCName pNameLocal of+       "xml" -- DOC: It MAY, but need not, be declared,+             -- and MUST NOT be bound to any other namespace name.+             | ns == xmlns_xml -> return []+             | otherwise -> p_error $ Error_Namespace_reserved_prefix pNameLocal+       "xmlns" -- DOC: It MUST NOT be declared+               -> p_error $ Error_Namespace_reserved_prefix pNameLocal+       local | "xml" <- TL.toLower $ TL.take 3 local -> return []+             -- DOC: All other prefixes beginning with the three-letter+             -- sequence x, m, l, in any case combination, are reserved.+             -- This means that: processors MUST NOT treat them as fatal errors.+       _ |  ns == xmlns_xml   -- DOC: Other prefixes MUST NOT be bound to this namespace name.+         || ns == xmlns_xmlns -- DOC: Other prefixes MUST NOT be bound to this namespace name.+         -> p_error $ Error_Namespace_reserved ns+       _ -> return [(pNameLocal, ns)]+      | otherwise -> return []+  let scopeNS = elemNS <> readTreeInh_ns_scope ro+  let defaultNS = HM.lookupDefault (readTreeInh_ns_default ro) (NCName "") scopeNS+  let+   lookupNamePrefix prefix =+    maybe (p_error $ Error_Namespace_prefix_unknown prefix) return $+    HM.lookup prefix scopeNS+  elemName :: QName <-+    -- Expand element's QName+    case pNameSpace n of+     Nothing -> return QName{qNameSpace=defaultNS, qNameLocal=pNameLocal n}+      -- DOC: If there is a default namespace declaration in scope,+      -- the expanded name corresponding to an unprefixed element name+      -- has the URI of the default namespace as its namespace name.+     Just prefix+      | NCName "xmlns" <- prefix ->+      -- DOC: Element names MUST NOT have the prefix xmlns.+      p_error $ Error_Namespace_reserved_prefix prefix+      | otherwise -> do+      ns <- lookupNamePrefix prefix+      return QName{qNameSpace=ns, qNameLocal=pNameLocal n}+  elemAttrs :: [(QName, FileSourced EscapedAttr)] <-+    -- Expand attributes' PName into QName+    forM attrs $ \(an, av) -> do+      ns <- maybe (return "") lookupNamePrefix $ pNameSpace an+      let qn = QName{qNameSpace=ns, qNameLocal=pNameLocal an}+      return (qn, av)+  -- Check for attribute collision+  let+   attrsByQName :: HM.HashMap QName [FileSourced EscapedAttr] =+    HM.fromListWith (<>) $ (<$> elemAttrs) $+     \(an, av) -> (an, [av])+  case HM.toList $ HM.filter (\x -> length x > 1) attrsByQName of+   (an, _):_ -> p_error $ Error_Attribute_collision an+   _ -> return ()+  content :: FileSourcedTrees <-+    mempty <$ P.string "/>" <|>+    R.local+     (const ro+       { readTreeInh_ns_scope   = scopeNS+       , readTreeInh_ns_default = defaultNS+       })+     (P.char '>' *> p_content <* p_ETag elemName)+  src <- p_SourcedEnd+  return $ TS.Tree (src $ NodeElem elemName (List.head <$> attrsByQName)) content++-- *** Attribute+-- | Note: despite the type, the returned 'FileSource'+-- encompasses also the attribute 'PName'.+-- It is pushed in the attribute value to fit the insertion+-- of the attribute into a 'HM.HashMap'.+p_Attribute :: P.Tokens s ~ TL.Text => ReadTree Error s (PName, FileSourced EscapedAttr)+p_Attribute =+  p_SourcedBegin $ do+    an <- P.try $ p_Spaces1 *> p_PName+    void p_Eq+    av <- p_AttrValue+    src <- p_SourcedEnd+    return (an, src av)++p_AttrValue :: P.Tokens s ~ TL.Text => ReadTree Error s EscapedAttr+p_AttrValue = p_quoted p_AttrValueText++p_AttrValueText :: P.Tokens s ~ TL.Text => Char -> ReadTree Error s EscapedAttr+p_AttrValueText q =+  EscapedAttr . Seq.fromList <$> P.many (+    p_Reference <|>+    -- Supplementary alternative to always escape the quote+    -- as expected by 'EscapedAttr'.+    (if q /= '\"' then EscapedEntityRef entityRef_quot <$ P.char '"' else P.empty) <|>+    EscapedPlain <$> P.label ("[^<&"<>[q]<>"]")+      (P.takeWhile1P Nothing $ \c ->+        XC.isXmlChar c &&+        c `List.notElem` (q:"<&")+      )+  )++-- * content+p_content :: P.Tokens s ~ TL.Text => ReadTree Error s FileSourcedTrees+p_content =+  (Seq.fromList <$>) $ P.many $+    (p_SourcedBegin $ do+      P.try $ P.char '<' *> P.notFollowedBy (P.char '/')+      p_Element_ <|> p_PI_ <|> (P.char '!' *> (p_Comment_ <|> p_CDSect_))+    )+    <|> (+    (TS.tree0 <$>) $+      p_Sourced $ NodeText . EscapedText . foldMap unEscapedText+       <$> P.some (+        p_CharData <|>+        EscapedText . pure <$> p_Reference+      )+    )++-- *** ETag+p_ETag :: P.Tokens s ~ TL.Text => QName -> ReadTree Error s ()+p_ETag expected = do+  got <- P.string "</" *> p_QName <* p_Spaces <* P.char '>'+  unless (got == expected) $+    p_error $ Error_Closing_tag_unexpected got expected++-- * PName+p_PName :: P.Tokens s ~ TL.Text => ReadTree e s PName+p_PName = do+  n <- p_NCName+  s <- P.optional $ P.try $ P.char ':' *> p_NCName+  return $ case s of+   Nothing -> PName{pNameSpace=Nothing, pNameLocal=n}+   Just l  -> PName{pNameSpace=Just n , pNameLocal=l}++-- * QName+p_QName :: P.Tokens s ~ TL.Text => ReadTree Error s QName+p_QName = do+  n <- p_NCName+  s <- P.optional $ P.try $ P.char ':' *> p_NCName+  ReadTreeInh{..} <- R.ask+  case s of+   Nothing -> return QName{qNameSpace=readTreeInh_ns_default, qNameLocal=n}+   Just l ->+    case HM.lookup n readTreeInh_ns_scope of+     Nothing -> p_error $ Error_Namespace_prefix_unknown n+     Just ns -> return QName{qNameSpace=ns, qNameLocal=l}++-- ** NCName+p_NCName :: P.Tokens s ~ TL.Text => ReadTree e s NCName+p_NCName = P.label "NCName" $ NCName+ <$  P.notFollowedBy (P.satisfy (not . XC.isXmlNCNameStartChar))+ <*> P.takeWhile1P Nothing XC.isXmlNCNameChar++-- * Reference+p_Reference :: P.Tokens s ~ TL.Text => ReadTree Error s Escaped+p_Reference =+  EscapedCharRef   <$> p_CharRef <|>+  EscapedEntityRef <$> p_EntityRef++-- ** EntityRef+p_EntityRef :: P.Tokens s ~ TL.Text => ReadTree Error s EntityRef+p_EntityRef = do+  ref <- P.char '&' *> p_NCName <* P.char ';'+  EntityRef ref <$> lookupEntityRef ref+  where+  -- Because entities are declared in the (unimplemented) DTD,+  -- only builtins entities are supported for now.+  lookupEntityRef (NCName "lt"  ) = pure "<"+  lookupEntityRef (NCName "gt"  ) = pure ">"+  lookupEntityRef (NCName "amp" ) = pure "&"+  lookupEntityRef (NCName "apos") = pure "'"+  lookupEntityRef (NCName "quot") = pure "\""+  lookupEntityRef n = p_error $ Error_EntityRef_unknown n++-- ** CharRef+p_CharRef :: P.Tokens s ~ TL.Text => ReadTree Error s CharRef+p_CharRef =+  do+    ref <- readHexadecimal+     <$  P.string "&#x"+     <*> P.some P.hexDigitChar+     <*  P.char ';'+    check ref+  <|> do+    ref <- readDecimal+     <$  P.string "&#"+     <*> P.some P.digitChar+     <*  P.char ';'+    check ref+  where+  check i =+    let c = toEnum (fromInteger i) in+    if i <= toInteger (fromEnum (maxBound::Char))+    && XC.isXmlChar c+    then pure $ CharRef c+    else p_error $ Error_CharRef_invalid i++readInt :: Integer -> String -> Integer+readInt base digits =+  sign * List.foldl' acc 0 (List.concatMap digToInt digits1)+  where+  acc q r = q*base + r+  (sign, digits1) =+    case digits of+     [] -> (1, digits)+     c:ds | c == '-'  -> (-1, ds)+          | c == '+'  -> ( 1, ds)+          | otherwise -> ( 1, digits)+  ord = toInteger . Char.ord+  digToInt c+   | Char.isDigit c      = [ord c - ord '0']+   | Char.isAsciiLower c = [ord c - ord 'a' + 10]+   | Char.isAsciiUpper c = [ord c - ord 'A' + 10]+   | otherwise           = []++readDecimal :: String -> Integer+readDecimal = readInt 10++readHexadecimal :: String -> Integer+readHexadecimal = readInt 16++-- * Char+p_Char :: P.Tokens s ~ TL.Text => ReadTree e s Char+p_Char = P.label "XmlChar" $ P.satisfy XC.isXmlCharCR <|> p_CRLF+{-# INLINE p_Char #-}++-- ** Space+-- | Map '\r' and '\r\n' to '\n'.+-- See: https://www.w3.org/TR/xml/#sec-line-ends+p_CRLF :: P.Tokens s ~ TL.Text => ReadTree e s Char+p_CRLF = P.char '\r' *> P.option '\n' (P.char '\n')++p_Space :: P.Tokens s ~ TL.Text => ReadTree e s Char+p_Space = P.label "space" $ P.satisfy XC.isXmlSpaceCharCR <|> p_CRLF+{-# INLINE p_Space #-}++p_Spaces :: P.Tokens s ~ TL.Text => ReadTree e s ()+p_Spaces = P.label "spaces" $ void $ P.takeWhileP Nothing XC.isXmlSpaceChar+{-# INLINE p_Spaces #-}++p_Spaces1 :: P.Tokens s ~ TL.Text => ReadTree e s ()+p_Spaces1 = P.label "spaces" $ void $ P.takeWhile1P Nothing XC.isXmlSpaceChar+{-# INLINE p_Spaces1 #-}++-- * Eq+p_separator :: P.Tokens s ~ TL.Text => Char -> ReadTree e s ()+p_separator c = P.try (() <$ p_Spaces <* P.char c) <* p_Spaces++p_Eq :: P.Tokens s ~ TL.Text => ReadTree e s ()+p_Eq = p_separator '='
+ src/Symantic/XML/Tree/Source.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Symantic.XML.Tree.Source where++import Control.Applicative (Applicative(..))+import Data.Bool+import Data.Eq (Eq(..))+import Data.Function (($), (.), const)+import Data.Functor (Functor)+import Data.Functor.Identity (Identity(..))+import Data.Monoid (Monoid(..))+import Data.Ord (Ord(..))+import Data.Semigroup (Semigroup(..))+import Data.List.NonEmpty (NonEmpty(..))+import Prelude (Num(..), Int)+import System.IO (FilePath)+import Text.Show (Show(..), shows, showChar, showParen, showString)++-- * Type family 'Source'+type family Source (src :: * -> *) :: *+type instance Source (Sourced src) = src+type instance Source Identity = ()++-- * Class 'NoSource'+class NoSource src where+  noSource :: a -> src a+  nullSource :: Source src -> Bool+  default nullSource ::+   Eq (Source src) =>+   SourceOf src =>+   Source src -> Bool+  nullSource = (==) (sourceOf @src (noSource @src ()))+instance NoSource Identity where+  noSource = Identity+  nullSource = const True++-- * Class 'UnSource'+class UnSource src where+  unSource :: src a -> a+instance UnSource Identity where+  unSource = runIdentity++-- * Class 'SourceOf'+class SourceOf src where+  sourceOf :: src a -> Source src+instance SourceOf Identity where+  sourceOf _ = ()++-- * Type 'FileSource'+newtype FileSource pos+ =      FileSource (NonEmpty (FileRange pos))+ deriving (Eq)+instance Show (FileRange pos) => Show (FileSource pos) where+  showsPrec _p (FileSource (s:|[])) = shows s+  showsPrec _p (FileSource (s:|s1:ss)) =+    shows s . showString "\n in " .+    shows (FileSource (s1:|ss))++-- ** Type 'FileSourced'+type FileSourced = Sourced (FileSource Offset)++-- ** Type 'FileRange'+data FileRange pos+ =   FileRange+ {   fileRange_path  :: FilePath+ ,   fileRange_begin :: pos+ ,   fileRange_end   :: pos+ } deriving (Eq, Ord)+instance Show (FileRange Offset) where+  showsPrec _p FileRange{..} =+    showString fileRange_path . showString " at char position " .+    showsPrec 10 fileRange_begin . showString " to " .+    showsPrec 10 fileRange_end+instance Show (FileRange LineColumn) where+  showsPrec _p FileRange{..} =+    showString fileRange_path . showString " at line:column position " .+    showsPrec 10 fileRange_begin . showString " to " .+    showsPrec 10 fileRange_end++-- *** Type 'Offset'+newtype Offset = Offset Int+ deriving (Eq, Ord)+instance Show Offset where+  showsPrec p (Offset o) = showsPrec p o+instance Semigroup Offset where+  Offset x <> Offset y = Offset (x+y)+instance Monoid Offset where+  mempty  = Offset 0+  mappend = (<>)++-- *** Type 'LineColumn'+-- | Absolute text file position.+data LineColumn = LineColumn+ { lineNum :: {-# UNPACK #-} Offset+ , colNum  :: {-# UNPACK #-} Offset+ } deriving (Eq, Ord)+instance Show LineColumn where+  showsPrec _p LineColumn{..} =+    showsPrec 11 lineNum .+    showChar ':' .+    showsPrec 11 colNum++-- * Type 'Sourced'+data Sourced src a+ =   Sourced+ {   source  :: src+ , unSourced :: a+ } deriving (Functor)+instance UnSource (Sourced src) where+  unSource = unSourced+instance NoSource (Sourced (FileSource Offset)) where+  noSource = Sourced $ FileSource $ pure $ FileRange mempty mempty mempty+instance SourceOf (Sourced src) where+  sourceOf (Sourced src _a) = src+-- | Ignore 'src'+instance Eq a => Eq (Sourced src a) where+  x == y = unSourced x == unSourced y+-- | Ignore 'src'+instance Ord a => Ord (Sourced src a) where+  x `compare` y = unSourced x `compare` unSourced y+instance+ (Show src, Show a, NoSource (Sourced src)) =>+ Show (Sourced src a) where+  showsPrec p (Sourced src a)+   | nullSource @(Sourced src) src = showsPrec p a+   | otherwise =+    showParen (p > 10) $+    showsPrec 10 a .+    showString " in " . showsPrec 10 src+instance Semigroup a => Semigroup (Sourced (FileSource Offset) a) where+  (<>)+   (Sourced rx@(FileSource (FileRange xf xb xe :|  xs)) x)+   (Sourced    (FileSource (FileRange yf yb ye :| _ys)) y)+   | xf == yf && xe == yb =+    Sourced (FileSource (FileRange xf xb ye :| xs)) $ x<>y+   | otherwise = Sourced rx (x<>y)
+ src/Symantic/XML/Tree/Write.hs view
@@ -0,0 +1,199 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+module Symantic.XML.Tree.Write where++import Data.Bool+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..), all)+import Data.Function (($), (.), const)+import Data.Maybe (Maybe(..))+import Data.Monoid (Monoid(..))+import Data.Semigroup (Semigroup(..))+import Data.String (IsString(..))+import Data.Traversable (Traversable(..))+import Data.Tuple (fst)+import System.IO (IO, FilePath)+import qualified Control.Monad.Trans.State as S+import qualified Data.ByteString.Lazy as BSL+import qualified Data.Char as Char+import qualified Data.HashMap.Strict as HM+import qualified Data.HashSet as HS+import qualified Data.List as List+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Encoding as TL+import qualified Data.TreeSeq.Strict as TS++import Symantic.XML.Language+import Symantic.XML.Tree.Source+import Symantic.XML.Tree.Data+import Symantic.XML.Write++writeTree :: UnSource src => Trees src -> TL.Text+writeTree ts = TLB.toLazyText $ unTreeWrite (write_Trees ts) defaultWriteInh++writeTreeIndented :: UnSource src => TL.Text -> Trees src -> TL.Text+writeTreeIndented ind xs =+  TLB.toLazyText $+  unTreeWrite (write_Trees xs) defaultWriteInh+   { writeInh_indent_delta = ind }++writeFile :: FilePath -> TL.Text -> IO ()+writeFile fp = BSL.writeFile fp . TL.encodeUtf8++-- * Type 'TreeWrite'+newtype TreeWrite+ =      TreeWrite+ {    unTreeWrite :: WriteInh -> TLB.Builder+ }+instance Semigroup TreeWrite where+  TreeWrite x <> TreeWrite y = TreeWrite (x <> y)+instance Monoid TreeWrite where+  mempty = TreeWrite (const "")+  mappend = (<>)+instance IsString TreeWrite where+  fromString = TreeWrite . const . fromString++write_Trees :: UnSource src => Trees src -> TreeWrite+write_Trees = foldMap write_Tree++write_Tree :: UnSource src => Tree src -> TreeWrite+write_Tree (TS.Tree node elemChilds) = TreeWrite $ \inh ->+ case unSource node of+  NodeText et@(EscapedText t)+   -- Remove spaces when indenting+   | not $ TL.null (writeInh_indent_delta inh)+   , all (\case+     EscapedPlain p -> TL.all Char.isSpace p+     _ -> False+    ) t -> mempty+   | otherwise -> textify et+  NodePI pn pv ->+    writeInh_indent inh <>+    "<?"<>textify pn<>+    (case pn of+     -- Special case: the value of the "xml" PI is parsed+     -- as children NodePI+     "xml" -> foldMap (\case+       TS.Tree nod _ ->+        case unSource nod of+         NodePI n v -> " "<>textify n<>"=\""<>textify v<>"\""+         _ -> mempty+      ) elemChilds+     _ -> s<>textify pv+    ) <> "?>" <> nl inh+    where s | TL.null pv = ""+            | otherwise  = " "+  NodeCDATA t ->+    writeInh_indent inh <>+    "<[CDATA[["<>textify (TL.replace "]]>" "]]&gt;" t)<>"]]>"<>nl inh+  NodeComment t ->+    writeInh_indent inh <>+    "<!--"<>textify (TL.replace "-->" "--&gt;" t)<>"-->"<>nl inh+  NodeElem elemQName elemAttrs ->+    writeInh_indent inh+     <> "<"+     <> write_elemPName+     <> write_xmlnsAttrs+     <> write_elemAttrs+     <> if noChild+    then "/>" <> nl inh+    else ">"+     <> (if hasIndenting then nl inh else mempty)+     <> write_elemChilds+     <> (if hasIndenting then writeInh_indent inh else mempty)+     <> "</"<>write_elemPName<>">"+     <> nl inh+    where+    -- Empty NodeText do not count as a child+    noChild =+      all (\case+       TS.Tree n _ts+        | NodeText (EscapedText t) <- unSource n ->+          all (\case+           EscapedPlain p -> TL.null p+           _ -> False+          ) t+        | otherwise -> False+      ) elemChilds+    -- Follow xmllint --format rules to detect indenting:+    -- if there is any NodeText it should only contain whites+    hasIndenting =+      (`all` elemChilds) $ \case+       TS.Tree n _ts+        | NodeText (EscapedText t) <- unSource n ->+          all (\case+           EscapedPlain p -> TL.all Char.isSpace p+           _ -> False+          ) t+        | otherwise -> True+    (usedNS, declNS) =+      HM.foldlWithKey' go (initUsedNS, initDeclNS) elemAttrs+      where+      initUsedNS = HS.singleton $ qNameSpace elemQName+      initDeclNS = (writeInh_namespaces inh){namespaces_prefixes=mempty}+      go acc@(uNS, dNS) an sav =+        case unSource sav of+         av+         -- xmlns:prefix="namespace"+          | qNameSpace an == xmlns_xmlns ->+          let ns = unescapeAttr av in+          (uNS, dNS+           { namespaces_prefixes =+            (if TL.null ns+            then HM.delete+            -- Empty namespace means removal+            -- of the prefix from scope.+            else (`HM.insert` qNameLocal an))+             (Namespace ns)+             (namespaces_prefixes dNS)+           })+         -- xmlns="namespace"+          | qNameSpace an == xmlns_empty+          , qNameLocal an == NCName "xmlns" ->+          (uNS, dNS{namespaces_default = Namespace (unescapeAttr av)})+         -- name="value"+          | qNameSpace an == xmlns_empty -> acc+         -- {namespace}name="value"+          | otherwise -> (HS.insert (qNameSpace an) uNS, dNS)+    -- The inherited namespaces,+    -- including those declared at this element.+    inhNS =+      HM.union+       (namespaces_prefixes declNS)+       (namespaces_prefixes (writeInh_namespaces inh))+    -- The namespaces used but not declared nor default,+    -- with fresh prefixes.+    autoNS =+      HM.delete (namespaces_default declNS) $+      (`S.evalState` HS.empty) $+      traverse+       (\() -> S.gets freshNCName)+       (HS.toMap usedNS `HM.difference` inhNS)+    write_xmlnsAttrs =+      foldMap (\(Namespace ns, qNameLocal) ->+        textifyAttr (PName (Just "xmlns") qNameLocal) (escapeAttr ns)) $+      List.sortOn fst $+      HM.toList autoNS+    scopeNS = declNS{ namespaces_prefixes = autoNS <> inhNS }+    write_elemPName = textify $ prefixifyQName scopeNS elemQName+    write_elemAttrs =+      foldMap (\(an, av) -> textifyAttr+       (prefixifyQName scopeNS{namespaces_default=xmlns_empty} an)+       (unSource av)) $+      List.sortOn fst $ -- This makes the rendition more predictible, but this is useless.+      HM.toList elemAttrs+    write_elemChilds = unTreeWrite (write_Trees elemChilds) inh+     { writeInh_namespaces = scopeNS+     -- Disable indenting unless hasIndenting.+     , writeInh_indent =+      if hasIndenting+      then+        writeInh_indent inh <>+        textify (writeInh_indent_delta inh)+      else mempty+     , writeInh_indent_delta =+      if hasIndenting+      then writeInh_indent_delta inh+      else mempty+     }
+ src/Symantic/XML/Write.hs view
@@ -0,0 +1,334 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE UndecidableInstances #-}+module Symantic.XML.Write where++import Control.Applicative (Applicative(..), Alternative((<|>)))+import Data.Bool+import Data.Either (Either(..))+import Data.Eq (Eq(..))+import Data.Foldable (Foldable(..))+import Data.Function (($), (.), id)+import Data.Functor ((<$>), (<$))+import Data.Int (Int)+import Data.Maybe (Maybe(..), fromMaybe)+import Data.Monoid (Monoid(..))+import Data.Semigroup (Semigroup(..))+import Data.String (String)+import Data.Traversable (Traversable(..))+import Data.Tuple (fst)+import Numeric.Natural (Natural)+import Prelude (Integer, error)+import System.IO (IO, FilePath)+import Text.Show (Show(..))+import qualified Control.Exception as Exn+import qualified Control.Monad.Trans.State as S+import qualified Data.ByteString.Lazy as BSL+import qualified Data.HashMap.Strict as HM+import qualified Data.HashSet as HS+import qualified Data.List as List+import qualified Data.Text as Text+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as TLB+import qualified Data.Text.Lazy.Encoding as TL+import qualified System.IO.Error as IO++import Symantic.Base.CurryN+import Symantic.XML.Language+import Symantic.XML.RelaxNG.Language++-- * Type 'Write'+newtype Write params k+ =      Write+ {    unWrite :: (WriteSyn -> k) -> params+ }++write :: Write params BSL.ByteString -> params+write = runWrite defaultWriteInh++runWrite :: WriteInh -> Write params BSL.ByteString -> params+runWrite def (Write params) = params $ \syn ->+  TL.encodeUtf8 $ TLB.toLazyText $+  fromMaybe mempty $ writeSyn_result syn def++writeUtf8 :: FilePath -> Write params (IO (Maybe ErrorWrite)) -> params+writeUtf8 path (Write params) = params $ \syn ->+  let txt =+       TL.encodeUtf8 $ TLB.toLazyText $+       fromMaybe mempty $+       writeSyn_result syn defaultWriteInh in+  (Nothing <$ BSL.writeFile path txt)+  `Exn.catch` \e ->+    if IO.isAlreadyInUseError e+    || IO.isPermissionError   e+    then pure $ Just e+    else IO.ioError e++-- ** Type 'Write'+type ErrorWrite = IO.IOError++-- ** Type 'WriteInh'+-- | Top-down inheritage.+data WriteInh+ =   WriteInh+ {   writeInh_namespaces   :: Namespaces NCName+     -- ^ 'Namespaces' from the parent element.+ ,   writeInh_indent       :: TLB.Builder+ ,   writeInh_indent_delta :: TL.Text+ }++defaultWriteInh :: WriteInh+defaultWriteInh = WriteInh+ { writeInh_namespaces   = defaultNamespaces+ , writeInh_indent       = mempty+ , writeInh_indent_delta = "  "+ }++-- ** Type 'WriteSyn'+-- | Bottom-up synthesis to build 'element' or 'attribute'.+data WriteSyn+ =   WriteSyn+ {   writeSyn_attrs :: HM.HashMap QName TL.Text+ ,   writeSyn_attr :: TL.Text+ ,   writeSyn_namespaces_default :: Maybe Namespace+ ,   writeSyn_namespaces_prefixes :: HM.HashMap Namespace NCName+ ,   writeSyn_result :: WriteInh -> Maybe TLB.Builder+ }++instance Semigroup WriteSyn where+  x <> y = WriteSyn+   { writeSyn_attrs = writeSyn_attrs x <> writeSyn_attrs y+   , writeSyn_attr = writeSyn_attr x <> writeSyn_attr y+   , writeSyn_namespaces_default = writeSyn_namespaces_default x <|> writeSyn_namespaces_default y+   , writeSyn_namespaces_prefixes = writeSyn_namespaces_prefixes x <> writeSyn_namespaces_prefixes y+   , writeSyn_result = writeSyn_result x <> writeSyn_result y+   }+instance Monoid WriteSyn where+  mempty = WriteSyn+   { writeSyn_attrs = mempty+   , writeSyn_attr = mempty+   , writeSyn_namespaces_default = Nothing+   , writeSyn_namespaces_prefixes = mempty+   , writeSyn_result = mempty+   }++instance Emptyable Write where+  empty = Write (\k -> k mempty)+instance Unitable Write where+  unit = Write (\k () -> k mempty)+instance Voidable Write where+  void a (Write x) = Write (\k -> x k a)+instance Dimapable Write where+  dimap _a2b b2a (Write x) = Write $ \k b ->+    x k (b2a b)+instance Dicurryable Write where+  dicurry (_::proxy args) _construct destruct (Write x) =+    Write $ \k r ->+      uncurryN @args (x k) (destruct r)+instance Composable Write where+  Write x <.> Write y = Write $ \k ->+    x (\mx -> y $ \my -> k (mx<>my))+instance Tupable Write where+  Write x <:> Write y = Write $ \k (a,b) ->+    x (\mx -> y (\my -> k (mx<>my)) b) a+instance Eitherable Write where+  Write x <+> Write y = Write $ \k -> \case+   Left  a -> x k a+   Right b -> y k b+instance Constant Write where+  constant _a = Write $ \k _a -> k mempty+instance Optionable Write where+  option = id+  optional (Write x) = Write $ \k ->+    \case+     Nothing -> k mempty+     Just a -> x k a+{-+instance Routable Write where+  Write x <!> Write y = Write $ \k ->+    x k :!: y k+-}+instance Repeatable Write where+  many0 (Write x) = Write $ \k -> \case+   [] -> k mempty+   a:as -> x (\ma ->+    unWrite (many0 (Write x))+     (\mas -> k (ma<>mas)) as) a+  many1 (Write x) = Write $ \k -> \case+   [] -> k mempty+   a:as -> x (\ma ->+    unWrite (many0 (Write x))+     (\mas -> k (ma<>mas)) as) a+instance Textable Write where+  type TextConstraint Write a = EncodeText a+  text = Write $ \k v ->+    let t = encodeText v in+    k mempty+     { writeSyn_attr = t+     , writeSyn_result = \_inh -> Just $ textify $ escapeText t+     }+instance XML Write where+  namespace nm ns = Write $ \k ->+    k $ case nm of+     Nothing -> mempty{writeSyn_namespaces_default=Just ns}+     Just p  -> mempty{writeSyn_namespaces_prefixes=HM.singleton ns p}+  element elemQName (Write x) = Write $ \k ->+    x $ \syn ->+      k mempty{ writeSyn_result = \inh ->+      let+        hasIndenting = not $ TL.null $ writeInh_indent_delta inh+        defNS = fromMaybe+         (namespaces_default (writeInh_namespaces inh))+         (writeSyn_namespaces_default syn)+        usedNS =+          HS.singleton (qNameSpace elemQName) <>+          HS.delete xmlns_empty (HS.fromList (qNameSpace <$> HM.keys (writeSyn_attrs syn)))+        -- The inherited namespaces,+        -- including those declared at this element.+        inhNS =+          HM.union+           (writeSyn_namespaces_prefixes syn)+           (namespaces_prefixes (writeInh_namespaces inh))+        -- The namespaces used but not declared nor default,+        -- with fresh prefixes.+        autoNS =+          -- HM.delete defNS $+          (`S.evalState` HS.empty) $+          traverse+           (\() -> S.gets freshNCName)+           (HS.toMap usedNS `HM.difference` inhNS)+        write_xmlnsAttrs =+          (if defNS == namespaces_default (writeInh_namespaces inh)+          then mempty+          else textifyAttr (PName Nothing "xmlns") (escapeAttr (unNamespace defNS))) <>+          HM.foldrWithKey (\(Namespace ns) qNameLocal acc ->+            textifyAttr (PName (Just "xmlns") qNameLocal) (escapeAttr ns) <> acc+           ) mempty+           (autoNS <> writeSyn_namespaces_prefixes syn)+        scopeNS = Namespaces+         { namespaces_prefixes = autoNS <> inhNS+         , namespaces_default = defNS+         }+        write_elemPName = textify $ prefixifyQName scopeNS elemQName+        write_elemAttrs =+          foldMap (\(an, av) -> textifyAttr+           (prefixifyQName scopeNS{namespaces_default=xmlns_empty} an)+           (escapeAttr av)) $+          List.sortOn fst $ -- This makes the rendition more predictible, but this is useless.+          HM.toList (writeSyn_attrs syn)+        write_elemChilds = writeSyn_result syn inh+         { writeInh_namespaces = scopeNS+         -- Disable indenting unless hasIndenting.+         , writeInh_indent =+          if hasIndenting+          then+            writeInh_indent inh <>+            textify (writeInh_indent_delta inh)+          else mempty+         , writeInh_indent_delta =+          if hasIndenting+          then writeInh_indent_delta inh+          else mempty+         }+      in Just $+      writeInh_indent inh+       <> "<"+       <> write_elemPName+       <> write_xmlnsAttrs+       <> write_elemAttrs+       <> case write_elemChilds of+       Nothing -> "/>" <> nl inh+       Just w -> ">"+         <> nl inh+         <> w+         <> (if hasIndenting then writeInh_indent inh else mempty)+         <> "</"<>write_elemPName<>">"+         <> nl inh+      }+  attribute n@(QName ans aln) (Write x) = Write $ \k ->+    x $ \syn ->+      if ans == xmlns_xmlns+      then unWrite (namespace (Just aln) (Namespace (writeSyn_attr syn))) k+      else if ans == xmlns_empty && aln == NCName "xmlns"+      then unWrite (namespace Nothing (Namespace (writeSyn_attr syn))) k+      else k mempty{writeSyn_attrs = HM.insert n (writeSyn_attr syn) (writeSyn_attrs syn)}+  literal lit = Write $ \k ->+    k mempty+     { writeSyn_attr = lit+     , writeSyn_result = \_inh ->+      Just $ textify $ escapeText lit+     }+  pi n = Write $ \k v ->+    k mempty{ writeSyn_result = \inh ->+      let s | TL.null v = ""+            | otherwise  = " " in+      Just $+      writeInh_indent inh <>+      "<?"<>textify n<>s <>+      textify (TL.replace "?>" "?&gt;" v) <>+      "?>"<>nl inh+    }+  comment = Write $ \k v ->+    k mempty{ writeSyn_result = \inh ->+      Just $+      writeInh_indent inh <>+      "<!--"<>textify (TL.replace "-->" "--&gt;" v)<>"-->"<>nl inh+    }+  cdata = Write $ \k v ->+    k mempty{ writeSyn_result = \inh ->+      Just $+      writeInh_indent inh <>+      "<[CDATA[["<>textify (TL.replace "]]>" "]]&gt;" v)<>"]]>"<>nl inh+    }+instance Permutable Write where+  type Permutation Write = WritePerm Write+  permutable = unWritePerm+  perm = WritePerm+  noPerm = WritePerm empty+  permWithDefault _a = WritePerm+instance Definable Write where+  define _n = id+instance RelaxNG Write where+  elementMatch nc x = Write $ \k n ->+    if matchNameClass nc n+    then error "elementMatch: given QName does not match expected NameClass"+    else unWrite (element n x) k+  attributeMatch nc x = Write $ \k n ->+    if matchNameClass nc n+    then error "attributeMatch: given QName does not match expected NameClass"+    else unWrite (attribute n x) k++-- ** Type 'WritePerm'+newtype WritePerm repr xml k+ =      WritePerm+ {    unWritePerm :: repr xml k }+instance Transformable (WritePerm repr) where+  type UnTrans (WritePerm repr) = repr+  noTrans = WritePerm+  unTrans = unWritePerm+instance Dimapable (WritePerm Write)+instance Composable (WritePerm Write)+instance Tupable (WritePerm Write)++nl :: WriteInh -> TLB.Builder+nl inh | TL.null (writeInh_indent_delta inh) = mempty+       | otherwise = "\n"++-- * Class 'EncodeText'+class EncodeText a where+  encodeText :: a -> TL.Text+  default encodeText :: Show a => a -> TL.Text+  encodeText = TL.pack . show+instance EncodeText String where+  encodeText = TL.pack+instance EncodeText Text.Text where+  encodeText = TL.fromStrict+instance EncodeText TL.Text where+  encodeText = id+instance EncodeText Bool where+  encodeText = \case+   False -> "0"+   True  -> "1"+instance EncodeText Int+instance EncodeText Integer+instance EncodeText Natural
stack.yaml view
@@ -1,9 +1,4 @@-resolver: lts-13.19-packages:-- '.'-- location: '../treeseq'-  extra-dep: true-- location: '../symantic/symantic-grammar'-  extra-dep: true+resolver: lts-15.4 extra-deps:-- megaparsec-7.0.4@sha256:a7397151601cbe6b8f831f8bdad1a10118dcd6d9a7ee50d6bbdcfbd1181b4ba2+- ../treeseq+- ../symantic-base
+ stack.yaml.lock view
@@ -0,0 +1,12 @@+# This file was autogenerated by Stack.+# You should not edit this file by hand.+# For more information, please see the documentation at:+#   https://docs.haskellstack.org/en/stable/lock_files++packages: []+snapshots:+- completed:+    size: 491163+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/15/4.yaml+    sha256: bc60043a06b58902b533baa80fb566c0ec495c41e428bc0f8c1e8c15b2a4c468+  original: lts-15.4
symantic-xml.cabal view
@@ -2,62 +2,65 @@ -- PVP:  +-+------- breaking API changes --       | | +----- non-breaking API additions --       | | | +--- code changes with no API change-version: 1.0.0.20190223-category: Data Structures-synopsis: Library for reading, validating and writing a subset of the XML format.-description: Symantics for an approximative implementation-             of XML (eXtensible Markup Language) and RNC (RelaxNG Compact).+version: 2.0.0.20200523+category: Text, XML+synopsis: Library for reading, validating and writing XML.+description: Symantics for XML (eXtensible Markup Language)+ and RNC (RelaxNG Compact).  .- Motivation: Other Haskell libraries do not fit my needs or are too heavy/complex.- I like the principle to parse XML using some symantics,- which can both generate a Megaparsec parser to validate the XML tree,- and a RNC rendition of the schema it validates.+ DISCLAIMER: This is an experimental library, use at your own risks.  .- DISCLAMER: My life being's too short, I'm NOT burning my brain- on seriously conforming to the too complex XML and RNC formats.- Still I try to respect a vague subset of those,- unless it makes the code more complex than I am comfortable with.+ Motivation: Writing a schema using Haskell combinators+ and deriving automatically a reader, a writer+ and a documentation from it.  .- WARNING: It's currently using an old symantic approach,- not the one developped in <https://hackage.haskell.org/package/symantic-http symantic-http>.- This may change when I'll get to it.+ Example:+ .+ * <symantic-atom https://hackage.haskell.org/package/symantic-atom> extra-doc-files: license: GPL-3 license-file: COPYING stability: experimental-author:      Julien Moutinho <julm+symantic-xml@autogeree.net>-maintainer:  Julien Moutinho <julm+symantic-xml@autogeree.net>-bug-reports: Julien Moutinho <julm+symantic-xml@autogeree.net>+author:      Julien Moutinho <julm+symantic-xml@sourcephile.fr>+maintainer:  Julien Moutinho <julm+symantic-xml@sourcephile.fr>+bug-reports: Julien Moutinho <julm+symantic-xml@sourcephile.fr> -- homepage:  build-type: Simple cabal-version: 1.24-tested-with: GHC==8.6.4+tested-with: GHC==8.8.3 extra-source-files:   stack.yaml+  stack.yaml.lock extra-tmp-files:  Source-Repository head-  location: git://git.autogeree.net/symantic-xml+  location: git://git.sourcephile.fr/haskell/symantic-xml   type:     git  Library+  hs-source-dirs: src   exposed-modules:-    Symantic.RNC-    Symantic.RNC.Sym-    Symantic.RNC.Validate-    Symantic.RNC.Write-    Symantic.RNC.Write.Fixity-    Symantic.RNC.Write.Namespaces     Symantic.XML-    Symantic.XML.Document+    Symantic.XML.Language+    Symantic.XML.Namespace     Symantic.XML.Read-    Symantic.XML.Read.Parser+    Symantic.XML.RelaxNG+    Symantic.XML.RelaxNG.Compact.Write+    Symantic.XML.RelaxNG.Language+    Symantic.XML.Text+    Symantic.XML.Tree+    Symantic.XML.Tree.Data+    Symantic.XML.Tree.Read+    Symantic.XML.Tree.Source+    Symantic.XML.Tree.Write     Symantic.XML.Write   default-language: Haskell2010   default-extensions:+    DefaultSignatures     FlexibleContexts     FlexibleInstances+    GeneralizedNewtypeDeriving     LambdaCase     MultiParamTypeClasses     NamedFieldPuns@@ -65,24 +68,22 @@     RecordWildCards     ScopedTypeVariables     TupleSections-    -- TypeFamilies+    TypeApplications+    TypeFamilies+    TypeOperators   ghc-options:     -Wall     -Wincomplete-uni-patterns     -Wincomplete-record-updates-    -fno-warn-tabs     -- -fhide-source-paths   build-depends:       base                 >= 4.10 && < 5     , bytestring           >= 0.10     , containers           >= 0.5-    , data-default-class   >= 0.1-    , filepath             >= 1.4     , hashable             >= 1.2.6     , hxt-charproperties   >= 9.2-    , megaparsec           >= 7.0.4-    -- , parser-combinators   >= 1.0-    , safe                 >= 0.3+    , megaparsec           >= 8.0+    , symantic-base        >= 0.0     , text                 >= 1.2     , transformers         >= 0.5     , treeseq              >= 1.0@@ -93,8 +94,8 @@   hs-source-dirs: test   main-is: Main.hs   other-modules:-    RNC.Parser-    RNC.Commoning+    RelaxNG.Commoning+    RelaxNG.Whatever     Golden     -- HUnit     -- QuickCheck@@ -104,28 +105,28 @@     NamedFieldPuns     NoImplicitPrelude     RecordWildCards+    TypeFamilies     ViewPatterns   ghc-options:     -Wall     -Wincomplete-uni-patterns     -Wincomplete-record-updates-    -fno-warn-tabs     -fhide-source-paths   build-depends:     symantic-xml+    , symantic-base >= 0.0     , base >= 4.10 && < 5     , bytestring >= 0.10     , containers >= 0.5-    , data-default-class   >= 0.1     , deepseq >= 1.4-    , filepath >= 1.4     , hashable >= 1.2.6     , megaparsec >= 7.0.4     , tasty >= 0.11     , tasty-golden >= 2.3+    -- , tasty-hunit     , text >= 1.2+    -- , time >= 1.9     , transformers >= 0.4     , treeseq >= 1.0     -- , QuickCheck >= 2.0-    -- , tasty-hunit     -- , tasty-quickcheck
test/Golden.hs view
@@ -1,41 +1,106 @@-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-} module Golden where -import Control.Arrow (left) import Control.Monad (Monad(..), sequence) import Data.Bool import Data.Either (Either(..))-import Data.Foldable (Foldable(..)) import Data.Function (($), (.)) import Data.Functor ((<$>))+import Data.Monoid (Monoid(..)) import Data.Semigroup (Semigroup(..)) import Data.String (String)-import Data.Void (Void)-import System.FilePath (FilePath)-import System.IO (IO)+import System.IO (IO, FilePath) import Text.Show (Show(..)) import qualified Data.ByteString.Lazy as BSL import qualified Data.List as List import qualified Data.Text.Lazy          as TL import qualified Data.Text.Lazy.Encoding as TL-import qualified Text.Megaparsec as P import qualified Data.TreeSeq.Strict as TS  import Test.Tasty import Test.Tasty.Golden -import Symantic.XML.Read.Parser (XMLs) import qualified Symantic.XML as XML-import qualified Symantic.RNC as RNC-import RNC.Parser ()-import qualified RNC.Commoning+import qualified Symantic.XML.RelaxNG as RelaxNG+import qualified RelaxNG.Commoning+import qualified RelaxNG.Whatever +goldensIO :: IO TestTree+goldensIO =+  testGroup "Golden" <$>+  sequence+   [ goldensXML+   , goldensRelaxNG+   ]++goldensXML :: IO TestTree+goldensXML = do+  inputFiles <- List.sort <$> findByExtension [".xml"] "test/Golden/XML"+  return $ testGroup "XML"+   [ testGroup "Read"+     [ testGolden inputFile ".read" $+      XML.readTree inputFile >>= \ast ->+        return $ TL.encodeUtf8 . TL.pack . TS.prettyTrees <$> ast+     | inputFile <- inputFiles+     ]+   , testGroup "Write" $ List.concat+     [+       [ testGolden inputFile ".write" $+        XML.readTree inputFile >>= \ast ->+          return $ TL.encodeUtf8 . XML.writeTree <$> ast+       , testGolden inputFile ".write.indented" $+        XML.readTree inputFile >>= \ast ->+          return $ TL.encodeUtf8 . XML.writeTreeIndented (TL.pack "  ") <$> ast+       ]+     | inputFile <- inputFiles+     , not $ List.isInfixOf "/Error/" inputFile+     ]+   ]++goldensRelaxNG :: IO TestTree+goldensRelaxNG = do+  inputFiles <- List.sort <$> findByExtension [".xml"] "test/Golden/RelaxNG"+  return $ testGroup "RelaxNG"+   [ testGroup "Validate"+     [ testGroup "Commoning" $ mconcat+       [+        let xml = XML.read RelaxNG.Commoning.schema inputFile in+        [ testGolden inputFile ".read" $+          ((TL.encodeUtf8 . TL.pack . show) <$>) <$> xml+        , testGolden inputFile ".write" $+          ((XML.write RelaxNG.Commoning.schema) <$>) <$> xml+        ]+       | inputFile <- inputFiles+       , "/Commoning/" `List.isInfixOf` inputFile+       ]+     , testGroup "Whatever" $ mconcat+       [+        let xml = XML.read RelaxNG.Whatever.schema inputFile in+        [ testGolden inputFile ".read" $+          ((TL.encodeUtf8 . TL.pack . show) <$>) <$> xml+        , testGolden inputFile ".write" $+          ((XML.write RelaxNG.Whatever.schema) <$>) <$> xml+        ]+       | inputFile <- inputFiles+       , "/Whatever/" `List.isInfixOf` inputFile+       ]+     ]+   , testGroup "Compact"+     [ testGroup "Write"+       [ testGolden "test/Golden/RelaxNG/Commoning" ".rnc" $+          return $ Right $ TL.encodeUtf8 $+            RelaxNG.writeRNC RelaxNG.Commoning.schema+       , testGolden "test/Golden/RelaxNG/Whatever" ".rnc" $+          return $ Right $ TL.encodeUtf8 $+            RelaxNG.writeRNC RelaxNG.Whatever.schema+       ]+     ]+   ]+ -- * Golden testing utilities testGolden :: TestName -> TestName -> IO (Either String BSL.ByteString) -> TestTree-testGolden inputFile expectedExt =-	goldenVsStringDiff inputFile diffGolden (inputFile <> expectedExt)-	 . (>>= unLeft)+testGolden testName expectedExt =+  goldenVsStringDiff testName diffGolden (testName <> expectedExt)+   . (>>= unLeft)  diffGolden :: FilePath -> FilePath -> [String] diffGolden ref new = ["diff", "-u", ref, new]@@ -44,67 +109,3 @@ unLeft = \case  Left err -> return $ TL.encodeUtf8 $ TL.pack err  Right a  -> return a--goldensIO :: IO TestTree-goldensIO =-	testGroup "Golden" <$>-	sequence-	 [ goldensXML-	 , goldensRNC-	 ]--goldensXML :: IO TestTree-goldensXML = do-	inputFiles <- List.sort <$> findByExtension [".xml"] "test/Golden/XML"-	return $ testGroup "XML"-	 [ testGroup "Read"-		 [ testGolden inputFile ".read" $-			readXML inputFile >>= \ast ->-				return $ TL.encodeUtf8 . TL.pack . TS.prettyTrees <$> ast-		 | inputFile <- inputFiles-		 ]-	 , testGroup "Write" $ List.concat-		 [-			 [ testGolden inputFile ".write" $-				readXML inputFile >>= \ast ->-					return $ TL.encodeUtf8 . XML.writeXML <$> ast-			 , testGolden inputFile ".write.indented" $-				readXML inputFile >>= \ast ->-					return $ TL.encodeUtf8 . XML.writeXMLIndented (TL.pack "  ") <$> ast-			 ]-		 | inputFile <- inputFiles-		 , not $ List.isInfixOf "/Error/" inputFile-		 ]-	 ]--readXML :: FilePath -> IO (Either String XMLs)-readXML inputFile =-	XML.readFile inputFile >>= \case-	 Left err -> return $ Left $ show err-	 Right input ->-		return $ left P.errorBundlePretty $-			XML.readXML inputFile input--goldensRNC :: IO TestTree-goldensRNC = do-	inputFiles <- List.sort <$> findByExtension [".xml"] "test/Golden/RNC"-	return $ testGroup "RNC"-	 [ testGroup "Validate"-		 [ testGolden inputFile ".read" $-			validateXML inputFile RNC.Commoning.commoning >>= \a ->-				return $ TL.encodeUtf8 . TL.pack . show <$> a-		 | inputFile <- inputFiles-		 , List.isInfixOf "/Commoning/" inputFile-		 ]-	 ]--validateXML :: FilePath -> P.Parsec Void XMLs a -> IO (Either String a)-validateXML inputFile rnc =-	(<$> readXML inputFile) $ \case-	 Left err -> Left err-	 Right xml -> do-		case RNC.validateXML rnc xml of-		 Right a -> Right a-		 Left err ->-			Left $ List.unlines $ toList $-				P.parseErrorTextPretty <$> P.bundleErrors err
test/Main.hs view
@@ -5,11 +5,13 @@  import Test.Tasty import Golden+--import HUnit  main :: IO () main = do-	goldens <- goldensIO-	defaultMain $-		testGroup "Symantic"-		 [ goldens-		 ]+  goldens <- goldensIO+  defaultMain $+    testGroup ""+     [ goldens+     --, hunits+     ]
− test/RNC/Commoning.hs
@@ -1,350 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE StrictData #-}-module RNC.Commoning where--import Control.Applicative (Applicative(..), Alternative(..))-import Control.Monad (Monad, void)-import Data.Default.Class (Default(..))-import Data.Eq (Eq)-import Data.Function (($), (.))-import Data.Functor ((<$>))-import Data.Hashable (Hashable)-import Data.Maybe (Maybe(..))-import Data.Ord (Ord)-import Data.Sequence (Seq)-import Text.Show (Show)-import qualified Data.Text.Lazy as TL-import qualified Data.TreeSeq.Strict as TS-import qualified Text.Megaparsec as P--import Symantic.RNC (Sym_Permutation(..))-import qualified Symantic.RNC as RNC-import qualified Symantic.XML as XML--import RNC.Parser---- * Type 'Commoning'-data Commoning = Commoning- { commoning_persons    :: Persons- , commoning_opinions   :: Opinions- , commoning_groups     :: Groups- , commoning_operations :: Operations- , commoning_resources  :: Resources- } deriving (Show)---- ** Type 'Person'-data Person = Person- { person_id     :: Ident- , person_fields :: Seq Fields- } deriving (Show)--- *** Type 'Persons'-type Persons = [Person]---- ** Type 'Group'-type Group = TS.Tree NodeGroup--- *** Type 'NodeGroup'-data NodeGroup = NodeGroup- { group_id      :: Ident- , group_name    :: Maybe Name- , group_fields  :: Seq Fields- , group_members :: Members- } deriving (Show)--- *** Type 'Groups'-type Groups = Seq Group---- ** Type 'Member'-newtype Member = Member- { member_person :: Ident- } deriving (Show)--- *** Type 'Members'-type Members = [Member]---- ** Type 'Resource'-type Resource = TS.Tree NodeResource--- *** Type 'NodeResource'-data NodeResource = NodeResource- { resource_name     :: Name- , resource_policies :: Policies- } deriving (Show)--- *** Type 'Resources'-type Resources = Seq Resource---- ** Type 'Policy'-data Policy = Policy- { policy_operation :: Name- , policy_by        :: Ident- , policy_toward    :: (Maybe Ident)- , policy_rules     :: Rules- } deriving (Show)--- *** Type 'Policies'-type Policies = [Policy]---- ** Type 'Rule'-data Rule = Rule- { rule_grades     :: Ident- , rule_gradeRange :: GradeRange- } deriving (Show)--- *** Type 'Rules'-type Rules = [Rule]---- *** Type 'GradeRange'-data GradeRange- = GradeRange_Single Name- | GradeRange_Min Name- | GradeRange_Max Name- | GradeRange Name Name- deriving (Show)---- * Type 'Opinions'-type Opinions = [Grades]---- ** Type 'Grade'-data Grade = Grade- { grade_name   :: Name- , grade_abbrev :: Maybe Name- , grade_color  :: Maybe Color- } deriving (Show)--- *** Type 'Grades'-data Grades = Grades- { grades_id   :: Ident- , grades_name :: Maybe Name- , grades_list :: [Grade]- } deriving (Show)--- *** Type 'Color'-type Color = TL.Text---- ** Type 'Operation'-type Operation = TS.Tree NodeOperation--- *** Type 'NodeOperation'-newtype NodeOperation = NodeOperation- { operation_id :: Ident- } deriving (Show)--- *** Type 'Operations'-type Operations = Seq Operation---- ** Type 'Field'-data Field = Field- { field_name  :: Name- , field_value :: TL.Text- } deriving (Show)--- *** Type 'Fields'-type Fields = TS.Tree NodeField--- **** Type 'NodeField'-data NodeField- = NodeField  Field- | NodeFields { fields_name :: Name }- deriving (Show)---- * Type 'Ident'-newtype Ident = Ident TL.Text- deriving (Eq,Ord,Show,Hashable)--- * Type 'Name'-newtype Name  = Name  TL.Text- deriving (Eq,Ord,Show,Hashable)---- * Class 'Sym_Commoning'-xmlns_commoning :: XML.Namespace-xmlns_commoning = "http://commonsoft.org/xml/2018/commoning.rnc"-element :: RNC.Sym_RNC repr => XML.NCName -> repr a -> repr a-element = RNC.element . XML.QName xmlns_commoning-attribute :: RNC.Sym_RNC repr => XML.NCName -> repr a -> repr a-attribute = RNC.attribute . XML.QName ""--class RNC.Sym_RNC repr => Sym_Commoning repr where-	commoning  :: repr Commoning-	persons    :: repr Persons-	person     :: repr Person-	opinions   :: repr Opinions-	grades     :: repr Grades-	grade      :: repr Grade-	fields     :: repr Fields-	field      :: repr Field-	groups     :: repr Groups-	group      :: repr Group-	members    :: repr Members-	member     :: repr Member-	operations :: repr Operations-	operation  :: repr Operation-	resources  :: repr Resources-	resource   :: repr Resource-	policy     :: repr Policy-	rule       :: repr Rule-	ident      :: repr Ident-	name       :: repr Name-	color      :: repr Color-	-	commoning = RNC.rule "commoning" $-		element "commoning" $-		runPermutation $-		Commoning-		 <$$> persons-		 <||> opinions-		 <||> groups-		 <||> operations-		 <||> resources-	persons = RNC.rule "persons" $-		element "persons" $ RNC.many person-	person  = RNC.rule "person" $-		element "person" $ attrs <*> RNC.manySeq fields-		where-		attrs =-			runPermutation $-			Person-			 <$$> attribute "id" ident-	opinions = RNC.rule "opinions" $-		element "opinions" $-			RNC.many grades-	grades = RNC.rule "grades" $-		element "grades" $ attrs <*> RNC.many grade-		where-		attrs =-			runPermutation $-			Grades-			 <$$> attribute "id" ident-			 <|?> (def, Just <$> attribute "name" name)-	grade = RNC.rule "grade" $-		element "grade" $ attrs-		where-		attrs =-			runPermutation $-			Grade-			 <$$> attribute "name" name-			 <|?> (def, Just <$> attribute "abbrev" name)-			 <|?> (def, Just <$> attribute "color" color)-	fields = RNC.rule "fields" $-		element "fields" $-			(TS.Tree <$> attrs <*>) $-			RNC.manySeq $-				TS.tree0 . NodeField <$> field-				<|> fields-		where-		attrs =-			runPermutation $-			NodeFields-			 <$$> attribute "name" name-	field = RNC.rule "field" $-		element "field" $ attrs <*> RNC.text-		where-		attrs =-			runPermutation $-			Field-			 <$$> attribute "name" name-	groups = RNC.rule "groups" $-		element "groups" $ RNC.manySeq group-	group = RNC.rule "group" $-		element "group" $-			(((TS.Tree <$>) $ attrs <*> RNC.manySeq fields <*> members) <*>) $-				RNC.manySeq group-		where-		attrs =-			runPermutation $-			NodeGroup-			 <$$> attribute "id" ident-			 <|?> (def, Just <$> attribute "name" name)-	members = RNC.rule "members" $ RNC.many member-	member = RNC.rule "member" $-		element "member" $ attrs-		where-		attrs =-			runPermutation $-			Member-			 <$$> attribute "person" ident-	operations = RNC.rule "operations" $-		element "operations" $ RNC.manySeq operation-	operation = RNC.rule "operation" $-		element "operation" $-			(((TS.Tree <$>) $ attrs) <*>) $-				RNC.manySeq operation-		where-		attrs =-			runPermutation $-			NodeOperation-			 <$$> attribute "id" ident-	resources = RNC.rule "resources" $-		element "resources" $ RNC.manySeq resource-	resource = RNC.rule "resource" $-		element "resource" $-			(((TS.Tree <$>) $ attrs <*> RNC.many policy) <*>) $-				RNC.manySeq resource-		where-		attrs =-			runPermutation $-			NodeResource-			 <$$> attribute "name" name-	policy = RNC.rule "policy" $-		element "policy" $ attrs-		where-		attrs =-			runPermutation $-			Policy-			 <$$> attribute "operation" name-			 <||> attribute "by" ident-			 <|?> (def, Just <$> attribute "toward" ident)-			 <|*> rule-	rule = RNC.rule "rule" $-		element "rule" $ attrs-		where-		attrs-		 =   RNC.try attrsGrade-		 <|> RNC.try attrsGradeMin-		 <|> attrsGradeMax-		attrsGrade =-			runPermutation $-			Rule-			 <$$> attribute "grades" ident-			 <||> (GradeRange_Single <$> attribute "grade" name)-		attrsGradeMin =-			runPermutation $-			(\gs gMin mgMax -> Rule gs $ case mgMax of-				 Nothing -> GradeRange_Min gMin-				 Just gMax -> GradeRange gMin gMax)-			 <$$> attribute "grades" ident-			 <||> attribute "gradeMin" name-			 <|?> (def, Just <$> attribute "gradeMax" name)-		attrsGradeMax =-			runPermutation $-			(\gs mgMin gMax -> Rule gs $ case mgMin of-				 Nothing -> GradeRange_Max gMax-				 Just gMin -> GradeRange gMin gMax)-			 <$$> attribute "grades" ident-			 <|?> (def, Just <$> attribute "gradeMin" name)-			 <||> attribute "gradeMax" name-	-	ident = RNC.rule "ident" $ Ident <$> RNC.text-	name  = RNC.rule "name" $ Name <$> RNC.text-	color = RNC.rule "color" $ RNC.text-instance Sym_Commoning RNC.NS-instance Sym_Commoning RNC.Writer-instance- ( Ord err- , Ord src- , XML.NoSource src- ) => Sym_Commoning (P.Parsec err (XML.XMLs src))---- newtype Forall cl a = Forall { unForall :: forall repr. cl repr => repr a }-rnc :: forall repr. Sym_Commoning repr => [repr ()]-rnc =- [ void $ RNC.namespace Nothing xmlns_commoning- , void $ commoning- , void $ persons- , void $ person- , void $ opinions- , void $ grades- , void $ grade- , void $ fields- , void $ field- , void $ groups- , void $ group- , void $ members- , void $ member- , void $ resources- , void $ resource- , void $ policy- , void $ rule- , void $ ident- , void $ name- , void $ color- ]
− test/RNC/Parser.hs
@@ -1,65 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module RNC.Parser where--import Control.Applicative (Applicative(..))-import Control.Monad (Monad(..))-import Data.Bool-import Data.Either (Either(..))-import Data.Foldable (Foldable(..))-import Data.Function (($), (.))-import Data.Functor ((<$>))-import Data.Maybe (Maybe(..))-import Data.Monoid (Monoid(..))-import Data.Ord (Ord(..))-import Data.Semigroup (Semigroup(..))-import Data.Sequence (ViewL(..))-import Prelude (error)-import Text.Show (Show(..))-import qualified Data.List as List-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Sequence as Seq-import qualified Text.Megaparsec as P--import Symantic.XML.Document (XML, XMLs)-import qualified Symantic.XML.Document as XML-import qualified Symantic.RNC.Validate as RNC--instance Ord src => P.Stream (XMLs src) where-	type Token  (XMLs src) = XML src-	type Tokens (XMLs src) = XMLs src-	take1_ s =-		case Seq.viewl s of-		 EmptyL -> Nothing-		 t@(XML.Tree XML.Sourced{XML.unSourced=n} _) :< ts-		  | RNC.isIgnoredNode n -> P.take1_ ts-		  | otherwise       -> Just (t, ts)-	takeN_ n s | n <= 0    = Just (mempty, s)-	           | null s    = Nothing-	           | otherwise =-		let (ns,rs) = Seq.splitAt n s in-		let (ko,ok) = Seq.partition (RNC.isIgnoredNode . XML.unSourced . XML.unTree) ns in-		case P.takeN_ (Seq.length ko) rs of-		 Nothing -> Just (ok, rs)-		 Just (ns',rs') -> Just (ok<>ns', rs')-	tokensToChunk _s  = Seq.fromList-	chunkToTokens _s  = toList-	chunkLength _s    = Seq.length-	takeWhile_        = Seq.spanl-	-- | NOTE: unimplemented: useless since each 'XML.Node' is annotated with its 'FileSource'.-	reachOffset       = error "[BUG] P.Stream XMLs: reachOffset is not helpful, please use annotated source locations"-	-- | NOTE: useless since each 'XML.Node' is annotated with its 'FileSource'.-	reachOffsetNoLine = error "[BUG] P.Stream XMLs: reachOffsetNoLine is not helpful, please use annotated source locations"-	showTokens _s toks = List.intercalate ", " $ toList $ showTree <$> toks-		where-		showTree (XML.Tree (XML.Sourced _src a) _ts) =-			case a of-			 XML.NodeElem n     -> "element "<>show n<>""-			 XML.NodeAttr n     -> "attribute "<>show n<>""-			 XML.NodeText _t    -> "text"-			 XML.NodeComment _c -> "comment"-			 XML.NodePI n _t    -> "processing-instruction "<>show n<>""-			 XML.NodeCDATA _t   -> "cdata"
+ test/RelaxNG/Commoning.hs view
@@ -0,0 +1,375 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+module RelaxNG.Commoning where++import Data.Eq (Eq)+import Data.Either (Either(..))+import Data.Foldable (toList)+import Data.Functor ((<$>))+import Data.Function (($), (.))+import Data.Hashable (Hashable)+import Data.Maybe (Maybe(..))+import Data.Ord (Ord)+import Data.Sequence (Seq)+import Data.Tuple (fst)+import Text.Show (Show)+import GHC.Generics (Generic)+import qualified Data.Sequence as Seq+import qualified Data.Text.Lazy as TL+import qualified Data.TreeSeq.Strict as TS+import qualified Text.Megaparsec as P++import Symantic.XML as XML+import Symantic.XML.RelaxNG as RelaxNG++schema =+  namespace Nothing xmlns_commoning <.>+  namespace (Just "xsd") "http://www/w3/org/2001/XMLSchema-datatypes" <.>+  commoning++-- * Class 'Commonable'+xmlns_commoning :: Namespace+xmlns_commoning = "2018/commoning.rnc"+elem = element . QName xmlns_commoning+attr n = attribute (QName "" n) text+many0Seq = dimap Seq.fromList toList . many0++-- * Type 'Ident'+newtype Ident = Ident TL.Text+ deriving (Eq,Ord,Show,Hashable)++instance RNCText Ident where+  rncText_qname = QName xmlns_xsd "id"+instance EncodeText Ident where+  encodeText (Ident t) = t+instance DecodeText Ident where+  decodeText = Ident . fst <$> P.match (P.many P.anySingle)++-- * Type 'Name'+newtype Name = Name TL.Text+ deriving (Eq,Ord,Show,Hashable)+instance RNCText Name where+  rncText_qname  = rncText_qname  @TL.Text+  rncText_params = rncText_params @TL.Text++instance EncodeText Name where+  encodeText (Name t) = t+instance DecodeText Name where+  decodeText = Name . fst <$> P.match (P.many P.anySingle)++-- * Type 'Commoning'+data Commoning+ =   Commoning+ {   commoning_persons    :: Persons+ ,   commoning_opinions   :: Opinions+ ,   commoning_groups     :: Groups+ ,   commoning_operations :: Operations+ ,   commoning_resources  :: Resources+ } deriving (Show, Generic)++commoning =+  define "commoning" $+  elem "commoning" $+  adt @Commoning $+    permutable $+    persons <&>+    opinions <&>+    groups <&>+    operations <&>+    perm resources++-- ** Type 'Person'+data Person+ =   Person+ {   person_id     :: Ident+ ,   person_fields :: Seq Fields+ } deriving (Show, Generic)++person =+  define "person" $+  adt @Person $+  elem "person" $+    attr "id" <:>+    many0Seq fields++-- *** Type 'Persons'+type Persons = [Person]++persons =+  define "persons" $+  elem "persons" $+    many0 person++-- * Type 'Opinions'+type Opinions = [Grades]++opinions =+  define "opinions" $+  elem "opinions" $+    many0 grades++-- ** Type 'Grade'+data Grade+ =   Grade+ {   grade_name   :: Name+ ,   grade_abbrev :: Maybe Name+ ,   grade_color  :: Maybe Color+ } deriving (Show, Generic)++grade =+  define "grade" $+  elem "grade" $+  adt @Grade $+    attr "name" <:>+    optional (attr "abbrev") <:>+    optional (attr "color")++-- *** Type 'Color'+type Color = TL.Text++-- *** Type 'Grades'+data Grades+ =   Grades+ {   grades_id   :: Ident+ ,   grades_name :: Maybe Name+ ,   grades_list :: [Grade]+ } deriving (Show, Generic)++grades =+  define "grades" $+  elem "grades" $+  adt @Grades $+    attr "id" <:>+    optional (attr "name") <:>+    many0 grade++-- ** Type 'Field'+data Field+ =   Field+ {   field_name  :: Name+ ,   field_value :: TL.Text+ } deriving (Show, Generic)++-- *** Type 'Fields'+type Fields = TS.Tree NodeField++-- **** Type 'NodeField'+data NodeField+ =   NodeField Field+ |   NodeFields { fields_name :: Name }+ deriving (Show, Generic)++fields =+  define "fields" $+  elem "fields" $+  adt @(TS.Tree NodeField) $+    (dimap NodeFields fields_name $+      attr "name")+    <:>+    many0Seq (+      dimap+      (\case+       Left f -> TS.tree0 $ NodeField f+       Right fs -> fs)+      (\case+       TS.Tree (NodeField f) _ -> Left f+       fs -> Right fs) $+      field+      <+>+      fields+    )++field =+  define "field" $+  elem "field" $+  adt @Field $+    attr "name" <:>+    text++-- ** Type 'Group'+type Group = TS.Tree NodeGroup++-- *** Type 'NodeGroup'+data NodeGroup+ =   NodeGroup+ {   group_id      :: Ident+ ,   group_name    :: Maybe Name+ ,   group_fields  :: Seq Fields+ ,   group_members :: Members+ } deriving (Show, Generic)++-- *** Type 'Groups'+type Groups = Seq Group++groups =+  define "groups" $+  elem "groups" $+    many0Seq group++group =+  define "group" $+  elem "group" $+  adt @(TS.Tree NodeGroup) $+    (adt @NodeGroup $+      attr "id" <:>+      optional (attr "name") <:>+      many0Seq fields <:>+      members+    ) <:>+    many0Seq group++-- ** Type 'Member'+newtype Member+ =      Member+ {      member_person :: Ident+ } deriving (Show, Generic)++-- *** Type 'Members'+type Members = [Member]++members = define "members" $ many0 member+member =+  define "member" $+  elem "member" $+  adt @Member $+   attr "person"++-- ** Type 'Operation'+type Operation = TS.Tree NodeOperation+-- *** Type 'NodeOperation'+newtype NodeOperation+ =      NodeOperation+ {      operation_id :: Ident+ } deriving (Show, Generic)+-- *** Type 'Operations'+type Operations = Seq Operation++operations =+  define "operations" $+  elem "operations" $+  many0Seq operation++operation =+  define "operation" $+  elem "operation" $+  adt @(TS.Tree NodeOperation) $+    (adt $ attr "id") <:>+    many0Seq operation++-- ** Type 'Resource'+type Resource = TS.Tree NodeResource+-- *** Type 'NodeResource'+data NodeResource+ =   NodeResource+ {   resource_name     :: Name+ ,   resource_policies :: Policies+ } deriving (Show, Generic)++-- *** Type 'Resources'+type Resources = Seq Resource++resources =+  define "resources" $+  elem "resources" $+    many0Seq resource++resource =+  define "resource" $+  elem "resource" $+  adt @(TS.Tree NodeResource) $+    (adt $ attr "name" <:> many0 policy) <:>+    many0Seq resource++-- ** Type 'Policy'+data Policy+ =   Policy+ {   policy_operation :: Name+ ,   policy_by        :: Ident+ ,   policy_toward    :: Maybe Ident+ ,   policy_rules     :: Rules+ } deriving (Show, Generic)++policy =+  define "policy" $+  adt @Policy $+  elem "policy" $+    attr "operation" <:>+    attr "by" <:>+    optional (attr "toward") <:>+    many0 rule++-- *** Type 'Policies'+type Policies = [Policy]++-- ** Type 'Rule'+data Rule+ =   Rule+ {   rule_grades     :: Ident+ ,   rule_gradeRange :: GradeRange+ } deriving (Show, Generic)++rule =+  define "rule" $+  adt @Rule $+  elem "rule" $+    attr "grades" <:>+    gradeRange++-- *** Type 'Rules'+type Rules = [Rule]++-- *** Type 'GradeRange'+data GradeRange+ =   GradeRange_Single Name+ |   GradeRange_Min    Name+ |   GradeRange_Max    Name+ |   GradeRange        Name Name+ deriving (Show, Generic)++gradeRange =+  define "gradeRange" $+  adt @GradeRange $+    attr "grade" <+>+    attr "gradeMin" <+>+    attr "gradeMax" <+> (+      attr "gradeMin" <:>+      attr "gradeMax"+    )++{-+rule = define "rule" $+  element "rule" attrs+  where+  attrs+   =   attrsGrade+   <+> attrsGradeMin+   <+> attrsGradeMax+  attrsGrade =+    permutable $+    Rule+     <$> attribute "grades" ident+     <*> (GradeRange_Single <$> attribute "grade" name)+  attrsGradeMin =+    permutable $+    (\gs gMin mgMax -> Rule gs $ case mgMax of+       Nothing   -> GradeRange_Min gMin+       Just gMax -> GradeRange gMin gMax)+     <$> attribute "grades" ident+     <*> attribute "gradeMin" name+     <*> optionalPerm (attribute "gradeMax" name)+  attrsGradeMax =+    permutable $+    (\gs mgMin gMax -> Rule gs $ case mgMin of+       Nothing   -> GradeRange_Max gMax+       Just gMin -> GradeRange gMin gMax)+     <$> attribute "grades" ident+     <*> optionalPerm (attribute "gradeMin" name)+     <*> attribute "gradeMax" name+-}
+ test/RelaxNG/Whatever.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StrictData #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+module RelaxNG.Whatever where++import Data.Function (($), (.))+import Data.Maybe (Maybe(..))+import Text.Show (Show)+import GHC.Generics (Generic)+import qualified Data.Text.Lazy as TL++import Symantic.XML as XML+import Symantic.XML.RelaxNG as RelaxNG++schema =+  namespace Nothing xmlns_whatever <.>+  namespace (Just "xsd") "http://www/w3/org/2001/XMLSchema-datatypes" <.>+  whatever++xmlns_whatever :: Namespace+xmlns_whatever = "2020/whatever.rnc"+elem = element . QName xmlns_whatever+attr n = attribute (QName "" n) text++newtype Whatever+ =   Whatever+ {   whatever_a :: TL.Text+ } deriving (Generic, Show)+whatever =+  define "root" $+  adt @Whatever $+  elem "root" $+    namespace Nothing xmlns_whatever <.>+    namespace (Just "whatever") xmlns_whatever <.>+    attr "a" <.>+    elem "child" (+      namespace (Just "what") xmlns_whatever <.>+      elem "sub-child" (+        namespace Nothing xmlns_empty <.>+        empty+      )+    )