dotfs-0.1.1.3: System/DotFS/Core/HeaderParser.hs
{-# LANGUAGE NoImplicitPrelude, GADTs, ExistentialQuantification #-}
{-# LANGUAGE Haskell98 #-}
module System.DotFS.Core.HeaderParser where
import Prelude hiding (lex)
import System.DotFS.Core.Datatypes
import System.DotFS.Core.Lexers
import System.DotFS.Core.ExpressionParsers
import System.DotFS.Core.ExpressionEvaluator
import System.DotFS.Core.HelperParsers (eatEverything)
import Control.Applicative ((<*))
import Text.Parsec hiding (parseTest)
import Text.Parsec.Token as P
import Data.Map
headerRecogniseP = do { _ <- symbol lex "<<dotfs"
; return ()
}
-- parse the header, no whitespace around it is eaten
headerP :: VarParser DFSState
headerP = do { _ <- symbol lex "<<dotfs"
; whiteSpace lex
; _ <- many assignmentP
; _ <- string ">>\n"
; getState -- returns the state
}
-- parse an assignment
assignmentP :: VarParser ()
assignmentP = (try tagstyleP
<|> try commentstyleP
<|> try shellCommandP
<|> assignState
) <* ( semi lex <* whiteSpace lex) <?> "assignment"
-- we must prevent comment tags from being ignored by the lexer,
-- so use the alternative lexer with great care
tagstyleP,commentstyleP :: VarParser ()
tagstyleP = do{ _ <- symbol lex "tagstyle"
; _ <- symbol styleLex "="
; s1 <- operator styleLex
; _ <- symbol styleLex "tag"
; s2 <- operator lex
; updateState (insert "tagstart" (Prim(VString s1)))
; updateState (insert "tagstop" (Prim(VString s2)))
}
commentstyleP = do{ _ <- symbol lex "commentstyle"
; _ <- symbol styleLex "="
; s1 <- operator styleLex
; updateState (insert "commentstart" (Prim(VString s1)))
; _ <- symbol styleLex "comment"
; optional (do s2 <- operator lex
updateState (insert "commentstop" (Prim(VString s2))))
}
-- | this parses a shell command. These are denoted by using := instead
-- of = for assignment. This is because backticks are a pain to parse, and
-- we prefer the built-in stringLiteral parser.
shellCommandP :: VarParser ()
shellCommandP = do { name <- identifier lex
; whiteSpace lex
; _ <- symbol lex ":="
; whiteSpace lex
; command <- exprP
; s <- getState
; let finalCommand = eval s command
; let e = eval s (Sys (show finalCommand))
; updateState (insert name (Prim e))
}
-- | assignState parses an assignment. That is, an identifier, an equals (=)
-- symbol, and then an expression.
assignState :: VarParser ()
assignState = do{ name <- identifier lex
; whiteSpace lex
; _ <- symbol lex "="
; whiteSpace lex
; val <- exprP
; s <- getState
; let e = eval s val
; updateState (insert name (Prim e))
}