bookhound-0.1.3.0: src/Parsers/Xml.hs
module Parsers.Xml (xml, branchExpr, leafExpr, literal) where
import Parser (Parser)
import ParserCombinators (IsMatch(..), (<|>), (|*), (|+), maybeWithin)
import Parsers.Char (doubleQuote)
import Parsers.String (withinDoubleQuotes, withinAngleBrackets, spacing)
import SyntaxTrees.Xml ( XmlExpression(..), literalExpression )
import qualified Data.Map as Map
import Data.Map(Map)
xml :: Parser XmlExpression
xml = maybeWithin ((header <|> comment) |+) $
maybeWithin spacing $ branchExpr <|> leafExpr
field :: Parser (String, String)
field = do x <- text
is '='
y <- quotedText
pure (x, y) where
quotedText = withinDoubleQuotes (inverse doubleQuote |*)
fullTag :: Parser (String, Map String String)
fullTag = do tag <- text
flds <- Map.fromList <$> ((spacing *> field) |*)
pure (tag, flds)
branchExpr :: Parser XmlExpression
branchExpr = do (tag, flds) <- withinAngleBrackets fullTag
exprs <- (xml |+) <|> literal
maybeWithin spacing (is ("</" ++ tag ++ ">"))
pure $ XmlExpression { tagName = tag, fields = flds, expressions = exprs }
literal :: Parser [XmlExpression]
literal = pure . literalExpression <$> maybeWithin spacing (isNot '<' |*)
leafExpr :: Parser XmlExpression
leafExpr = do (tag, flds) <- withinAngleBrackets (fullTag <* is '/')
pure $ XmlExpression { tagName = tag, fields = flds, expressions = [] }
header :: Parser String
header = maybeWithin spacing $ is "<?" *> (isNot '?' |*) <* is "?>"
comment :: Parser String
comment = maybeWithin spacing $ is "<!--" *> (isNot '-' |*) <* is "-->"
text :: Parser String
text = (noneOf ['/', '>', ' ', '='] |+)