module System.DotFS.Core.BodyParser where
import Prelude hiding (lex,lookup)
import System.DotFS.Core.Datatypes
import System.DotFS.Core.Lexers
import System.DotFS.Core.ExpressionParsers
import System.DotFS.Core.HelperParsers
import System.DotFS.Core.HeaderParser
import Data.Map
import Control.Applicative ((<$>), (<*), (*>), (<$), (<*>))
import Text.Parsec
import Text.Parsec.Token as P
bodyP :: VarParser (Header,Body)
bodyP = do { b <- id <$ headerP *> blocksP <* eof <?> "body with annotations"
; h <- getState
; return (h,b)
}
blocksP :: VarParser Body
blocksP = many blockP
blockP :: VarParser BodyElem
blockP = try conditionalBlockP
<|> try exprBlockP
<|> verbBlockP <?> "body element (if, reference or verbatim)"
conditionalBlockP :: VarParser BodyElem
conditionalBlockP = do{ state <- getState
; _ <- symbol lex (extractTagStart state)
; _ <- symbol lex "if"
; cond <- exprP
; _ <- string (extractTagStop state)
; content <- blocksP
; _ <- symbol lex (extractTagStart state)
; _ <- symbol lex "endif" <|> symbol lex "/if" <|> symbol lex "fi"
; _ <- string (extractTagStop state)
; return $ Cond cond content
}
exprBlockP :: VarParser BodyElem
exprBlockP = do{ state <- getState
; _ <- symbol lex (extractTagStart state)
; _ <- symbol lex "var"
; var <- exprP
; _ <- string (extractTagStop state)
; return $ Ref var
}
verbBlockP :: VarParser BodyElem
verbBlockP = do{ state <- getState
; let opentag = const () <$> try (string (extractTagStart state))
endofVerb = lookAhead (eof <|> opentag)
in Verb <$> many1Till anyChar endofVerb
}
extractTagStart,extractTagStop :: Map String DFSExpr -> String
extractTagStart m = case lookup "tagstart" m of
Just (Prim (VString s)) -> s
_ -> "<<"
extractTagStop m = case lookup "tagstop" m of
Just (Prim (VString s)) -> s
_ -> ">>"