module System.DotFS.Core.ExpressionParsers where
import Prelude hiding (lex,lookup)
import Control.Applicative ((<$>))
import System.DotFS.Core.Datatypes
import System.DotFS.Core.Lexers
import Data.Functor.Identity
import Text.Parsec
import Text.Parsec.Token as P
import Text.Parsec.Expr
exprP :: VarParser DFSExpr
exprP = buildExpressionParser table factor <?> "expression"
table :: [[ Operator String st Identity DFSExpr ]]
table = [
[pre "!" (UniOp Not)],
[ op "&&" (BiOp And) AssocNone ],
[ op "||" (BiOp Or) AssocNone ],
[ op "*" (BiOp Mul) AssocLeft, op "/" (BiOp Div) AssocLeft ],
[ op "+" (BiOp Add) AssocLeft, op "-" (BiOp Sub) AssocLeft ],
[ op "==" (BiOp Eq) AssocNone
, op ">" (BiOp GTOp) AssocNone
, op "<" (BiOp LTOp) AssocNone
, op "<=" (BiOp LEQ) AssocNone
, op ">=" (BiOp GEQ) AssocNone
, op "!=" (BiOp NEQ) AssocNone
]
]
where
op s f = Infix (do { reservedOp lex s; return f } <?> "operator")
pre s f = Prefix (do { reservedOp lex s; return f })
factor :: ParsecT String DFSState Identity DFSExpr
factor = parens lex exprP
<|> ((Prim . VInt) <$> integer lex)
<|> ((Prim . VBool) <$> boolTerm)
<|> ((Prim . VString) <$> stringLiteral lex)
<|> Var <$> identifier lex
<|> ifTerm
<?> "simple expression or variable"
boolTerm :: forall u. ParsecT String u Identity Bool
boolTerm = do { _ <- symbol lex "true"
; return True
}
<|> do { _ <- symbol lex "false"
; return False
}
ifTerm :: ParsecT String DFSState Identity DFSExpr
ifTerm = do { reservedOp lex "if"
; condition <- parens lex exprP
; _ <- symbol lex "{"
; thenbody <- exprP
; _ <- symbol lex "}"
; reservedOp lex "else"
; _ <- symbol lex "{"
; elsebody <- exprP
; _ <- symbol lex "}"
; return (If condition thenbody elsebody)
}