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

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

-- ------------------------------------------------------------
--
-- DTD declaration tokenizer

dtdDeclTokenizer        :: GenParser Char state XmlTree
dtdDeclTokenizer
    = do
      (dcl, al) <- dtdDeclStart
      content <- many1 dtdToken
      dtdDeclEnd
      return $! mkDTDElem dcl al content

dtdDeclStart :: GenParser Char state (DTDElem, Attributes)
dtdDeclStart
    = foldr1 (<|>) $
      map (uncurry dtdStart) $
              [ ("ELEMENT",  ELEMENT )
              , ("ATTLIST",  ATTLIST )
              , ("ENTITY",   ENTITY  )
              , ("NOTATION", NOTATION)
              ]
    where
    dtdStart    :: String -> DTDElem -> GenParser Char state (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      :: GenParser Char state ()
dtdDeclEnd
    = do
      _ <- XT.gt
      return ()

dtdToken        :: GenParser Char state XmlTree
dtdToken
    = dtdChars
      <|>
      attrValue
      <|>
      try peReference           -- first try parameter entity ref %xxx;
      <|>
      percent                   -- else % may be indicator for parameter entity declaration
      <?> "DTD token"

peReference     :: GenParser Char state XmlTree
peReference
    = do
      r <- XT.peReference
      return $! (mkDTDElem PEREF [(a_peref, r)] [])

attrValue       :: GenParser Char state XmlTree
attrValue
    = do
      v <- XT.attrValue
      return $! mkText v

dtdChars        :: GenParser Char state 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         :: GenParser Char state XmlTree
percent
    = do
      c <- char '%'
      return $! mkText [c]

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