-- ------------------------------------------------------------

{- |
   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]

-- ------------------------------------------------------------