content: -- ------------------------------------------------------------
  
  {- |
     Module     : Text.XML.HXT.Parser.XmlDTDTokenParser
     Copyright  : Copyright (C) 2005 Uwe Schmidt
     License    : MIT
  
     Maintainer : Uwe Schmidt (uwe@fh-wedel.de)
     Stability  : experimental
     Portability: portable
  
     Parsec parser for tokenizing DTD declarations for ELEMENT, ATTLIST, ENTITY and NOTATION
  
  -}
  
  -- ------------------------------------------------------------
  
  module Text.XML.HXT.Parser.XmlDTDTokenParser where
  
  import           Text.ParserCombinators.Parsec
  
  import           Text.XML.HXT.DOM.Interface
  import           Text.XML.HXT.DOM.XmlNode               ( mkDTDElem'
                                                          , mkText'
                                                          )
  import qualified Text.XML.HXT.Parser.XmlTokenParser     as XT
  import           Text.XML.HXT.Parser.XmlCharParser      ( XParser )
  
  -- ------------------------------------------------------------
  --
  -- DTD declaration tokenizer
  
  dtdDeclTokenizer        :: XParser s XmlTree
  dtdDeclTokenizer
      = do
        (dcl, al) <- dtdDeclStart
        content <- many1 dtdToken
        dtdDeclEnd
        return $ mkDTDElem' dcl al content
  
  dtdDeclStart :: XParser s (DTDElem, Attributes)
  dtdDeclStart
      = foldr1 (<|>) $
        map (uncurry dtdStart) $
                [ ("ELEMENT",  ELEMENT )
                , ("ATTLIST",  ATTLIST )
                , ("ENTITY",   ENTITY  )
                , ("NOTATION", NOTATION)
                ]
      where
      dtdStart    :: String -> DTDElem -> XParser s (DTDElem, Attributes)
      dtdStart dcl element
          = try ( do
                  _ <- string "<!"
                  _ <- string dcl
                  pos <- getPosition
                  return (element, [ (a_source, sourceName pos)
                                   , (a_line,   show (sourceLine pos))
                                   , (a_column, show (sourceColumn pos))
                                   ]
                         )
                )
  
  dtdDeclEnd      :: XParser s ()
  dtdDeclEnd
      = do
        _ <- XT.gt
        return ()
  
  dtdToken        :: XParser s XmlTree
  dtdToken
      = dtdChars
        <|>
        entityValue
        <|>
        try peReference           -- first try parameter entity ref %xxx;
        <|>
        percent                   -- else % may be indicator for parameter entity declaration
        <?> "DTD token"
  
  peReference     :: XParser s XmlTree
  peReference
      = do
        r <- XT.peReference
        return $! (mkDTDElem' PEREF [(a_peref, r)] [])
  
  entityValue       :: XParser s XmlTree
  entityValue
      = do
        v <- XT.entityValue
        return $ mkText' v
  
  dtdChars        :: XParser s XmlTree
  dtdChars
      = do
        v <- many1 (XT.singleChar "%\"'<>[]")             -- everything except string constants, < and >, [ and ] (for cond sections)
        return $ mkText' v                                -- all illegal chars will be detected later during declaration parsing
  
  percent         :: XParser s XmlTree
  percent
      = do
        c <- char '%'
        return $ mkText' [c]
  
  -- ------------------------------------------------------------
  