{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
module Data.NML.Parse (NMLPair(..), NMLElem(..), parseNML) where
import Control.Applicative
import Data.Attoparsec.Text
import Data.Char (isAlpha,isNumber)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8)
import Data.Word (Word8)
import Prelude hiding (takeWhile)
data NMLPair = NMLPair
{ pName :: Text
, pAttrs :: [NMLPair]
, pElems :: [NMLElem]
} deriving (Eq, Show)
data NMLElem
= EEntity Text
| EPair NMLPair
| EText Text
deriving (Eq, Show)
parseNML :: Text -> Either String NMLPair
parseNML = parseOnly prElement
----
isNameStartChar :: Char -> Bool
isNameStartChar = inClass ":_A-Za-z"
isNameChar :: Char -> Bool
isNameChar = inClass "-:_A-Za-z.0-9"
prName :: Parser Text
prName = do
c <- satisfy isNameStartChar
cs <- many (satisfy isNameChar)
return (T.pack (c:cs))
----
prElement :: Parser NMLPair
prElement = do
string "<"
pName <- prName
skipSpace
pAttrs <- many (prElement <* skipSpace)
prFinish pName pAttrs <|> prElems pName pAttrs
prEElement :: Parser NMLElem
prEElement = fmap EPair prElement
prFinish :: Text -> [NMLPair] -> Parser NMLPair
prFinish pName pAttrs = do
string ">"
return (NMLPair { .. })
where pElems = []
prElems :: Text -> [NMLPair] -> Parser NMLPair
prElems pName pAttrs = do
string "|"
pElems <- many (prEElement <|> prEntity <|> prText)
string ">"
return (NMLPair { .. })
prEntity :: Parser NMLElem
prEntity = do
string "["
en <- takeWhile1 (not . (== ']'))
string "]"
return (EEntity en)
prText :: Parser NMLElem
prText = do
t <- takeWhile1 (not . (inClass "<>|"))
return (EText t)