) where
import Control.Applicative (Applicative(..), Alternative(..))
-import Control.Monad (Monad(..))
import Data.Eq (Eq)
import Data.Function ((.), id)
import Data.Functor (Functor(..), (<$>))
import qualified Language.Symantic.RNC.Sym as RNC
validateXML ::
- Ord e => P.Parsec e XMLs a -> XMLs ->
- Either (P.ParseErrorBundle XMLs e) a
+ 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_satisfyMaybe :: P.MonadParsec e s m => (P.Token s -> Maybe a) -> m a
p_satisfyMaybe = (`P.token` Set.empty)
-instance Ord e => RNC.Sym_RNC (P.Parsec e XMLs) where
+instance (Ord err, Ord src, XML.NoSource src) => RNC.Sym_RNC (P.Parsec err (XMLs src)) where
{-
none = P.label "none" $ P.eof
-}
try = P.try
fail = P.label "fail" $ P.failure Nothing mempty
-instance Ord e => RNC.Sym_Permutation (P.ParsecT e XMLs m) where
+instance (Ord err, Ord src) => RNC.Sym_Permutation (P.ParsecT err (XMLs src) m) where
runPermutation (P value parser) = optional parser >>= f
where
-- NOTE: copy Control.Applicative.Permutations.runPermutation
-- so that the 'P.TrivialError' has an unexpected token
-- which is an 'XML.Node' containing a 'XML.FileSource' useful when reporting errors.
data Permutation m a = P (Maybe a) (m (Permutation m a))
-type instance RNC.Permutation (P.ParsecT e XMLs m) = Permutation (P.ParsecT e XMLs m)
+type instance RNC.Permutation (P.ParsecT err (XMLs src) m) = Permutation (P.ParsecT err (XMLs src) m)
instance Functor m => Functor (Permutation m) where
fmap f (P v p) = P (f <$> v) (fmap f <$> p)
instance Alternative m => Applicative (Permutation m) where
lhsAlt = (<*> rhs) <$> v
rhsAlt = (lhs <*>) <$> w
-instance Ord e => RNC.Sym_Rule (P.ParsecT e XMLs m) where
+instance (Ord err, Ord 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 ()
module Language.Symantic.XML
( module Language.Symantic.XML.Document
, module Language.Symantic.XML.Parser
- , Offset
- , LineColumn(..)
- , FileRange(..)
- , NoSource(..)
- , Sourced(..)
, readXML
, readFile
, writeXML
, TS.tree0
) where
-import Control.Applicative (Applicative(..), Alternative(..))
+import Control.Applicative (Alternative(..))
import Data.Bool
import Data.Char (Char)
import Data.Default.Class (Default(..))
import Data.Sequence (Seq)
import Data.String (String, IsString(..))
import GHC.Generics (Generic)
-import Prelude ((+), (-), error, fromIntegral)
+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.HashSet as HS
import qualified Data.List as List
import qualified Data.Sequence as Seq
-import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.TreeSeq.Strict as TS
-- * Type 'XML'
-type XML = TS.Tree (Sourced (FileSource Offset) Node)
-type XMLs = Seq 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 :: XMLs -> XMLs -> XMLs
+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) ->
(Seq.EmptyR, _) -> y
(_, Seq.EmptyL) -> x
-unions :: Foldable f => f XMLs -> XMLs
+unions ::
+ Semigroup (Sourced src EscapedText) =>
+ Foldable f => f (XMLs src) -> XMLs src
unions = foldl' union mempty
pattern Tree0 :: a -> TS.Tree a
import Data.Ord (Ord(..))
import Data.Semigroup (Semigroup(..))
import Data.Sequence (ViewL(..))
-import Data.String (String)
import Prelude (error)
import Text.Show (Show(..))
import qualified Data.List as List
XML.NodeCDATA{} -> True
_ -> False
-instance P.Stream XMLs where
- type Token XMLs = XML
- type Tokens XMLs = XMLs
+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
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 -> String
- showTree (XML.Tree a _ts) =
- showCell a $ \case
+ 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"
-
- showCell (XML.Sourced path@(XML.FileRange{XML.fileRange_file} NonEmpty.:| _) a) f =
- if null fileRange_file
- then f a
- else f a <> foldMap (\p -> "\n in "<>show p) path
-- | @subParser p xs@ returns a parser parsing @xs@ entirely with @p@,
-- updating 'P.stateOffset' and re-raising any exception.
-subParser :: Ord err => P.Parsec err XMLs a -> XMLs -> P.Parsec err XMLs a
+subParser ::
+ Ord err => Ord src =>
+ P.Parsec err (XMLs src) a -> XMLs src -> P.Parsec err (XMLs src) a
subParser p xs = do
st <- P.getParserState
let (st', res) = P.runParser' (p <* P.eof) st
import qualified Text.Megaparsec as P
import qualified Text.Megaparsec.Char as P
-import Language.Symantic.XML.Document
+import Language.Symantic.XML.Document hiding (XML, XMLs)
import Language.Symantic.XML.Read.Parser
readXML :: FilePath -> TL.Text -> Either (P.ParseErrorBundle TL.Text Error) XMLs
import qualified Text.Megaparsec as P
import qualified Text.Megaparsec.Char as P
-import Language.Symantic.XML.Document
+import Language.Symantic.XML.Document hiding (XML, XMLs)
+import qualified Language.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.
import Language.Symantic.XML.Document as XML
-writeXML :: XMLs -> TL.Text
+writeXML :: NoSource src => XMLs src -> TL.Text
writeXML xs = TLB.toLazyText $ write xs `R.runReader` def
-writeXMLIndented :: TL.Text -> XMLs -> TL.Text
+writeXMLIndented :: NoSource src => TL.Text -> XMLs src -> TL.Text
writeXMLIndented ind xs =
TLB.toLazyText $
write xs `R.runReader` def
write :: a -> Write
instance Writeable NCName where
write = return . TLB.fromLazyText . unNCName
-instance Writeable XMLs where
+instance NoSource src => Writeable (XMLs src) where
write xs = do
ro <- R.ask
if TL.null (reader_indent_delta ro)
EscapedPlain t -> TL.all Char.isSpace t
_ -> False) et
_ -> True
-instance Writeable XML where
+instance NoSource src => Writeable (XML src) where
write (Tree (Sourced _src nod) xs) = do
ro <- R.ask
case nod of
| c == '\"' -> """
| otherwise -> build c
-removeSpaces :: XMLs -> XMLs
+removeSpaces :: XMLs src -> XMLs src
removeSpaces xs =
if (`all` xs) $ \case
Tree (Sourced _ (NodeText (EscapedText et))) _ts ->