module Text.XML.HXT.Parser.XmlCharParser
    ( XParser
    , SimpleXParser
    , XPState(..)
    , withNormNewline
    , withoutNormNewline
    , xmlChar                   
    , xmlNameChar
    , xmlNameStartChar
    , xmlNCNameChar
    , xmlNCNameStartChar
    , xmlLetter
    , xmlSpaceChar
    , xmlCRLFChar
    )
where
import Data.Char.Properties.XMLCharProps        ( isXmlCharCR
                                                , isXmlNameChar
                                                , isXmlNameStartChar
                                                , isXmlNCNameChar
                                                , isXmlNCNameStartChar
                                                , isXmlLetter
                                                , isXmlSpaceCharCR
                                                )
import Data.String.Unicode
import Text.ParserCombinators.Parsec
type XParser s a	= GenParser Char (XPState s) a
type SimpleXParser a    = XParser () a
data XPState s		= XPState
    { xps_normalizeNewline	:: ! Bool
    , xps_userState             :: s
    }
withNormNewline		:: a -> XPState a
withNormNewline x	= XPState True x
withoutNormNewline	:: a -> XPState a
withoutNormNewline x	= XPState False x
xmlChar                 :: XParser s Unicode
xmlChar                 = ( satisfy isXmlCharCR
                            <|>
                            xmlCRLFChar
                          )
                          <?> "legal XML character"
xmlNameChar             :: XParser s Unicode
xmlNameChar             = satisfy isXmlNameChar <?> "legal XML name character"
xmlNameStartChar        :: XParser s Unicode
xmlNameStartChar        = satisfy isXmlNameStartChar <?> "legal XML name start character"
xmlNCNameChar           :: XParser s Unicode
xmlNCNameChar           = satisfy isXmlNCNameChar <?> "legal XML NCName character"
xmlNCNameStartChar      :: XParser s Unicode
xmlNCNameStartChar      = satisfy isXmlNCNameStartChar <?> "legal XML NCName start character"
xmlLetter               :: XParser s Unicode
xmlLetter               = satisfy isXmlLetter <?> "legal XML letter"
xmlSpaceChar            :: XParser s Char
xmlSpaceChar            = ( satisfy isXmlSpaceCharCR
                            <|>
                            xmlCRLFChar
                          )
                          <?> "white space"
xmlCRLFChar            :: XParser s Char
xmlCRLFChar            = ( do
                           _ <- char '\r'
                           s <- getState
                           if xps_normalizeNewline s
                              then option '\n' (char '\n')
                              else return '\r'
                         )
                         <?> "newline"