diff options
Diffstat (limited to 'Expr.hs')
| -rw-r--r-- | Expr.hs | 66 |
1 files changed, 66 insertions, 0 deletions
@@ -0,0 +1,66 @@ +module Expr (parseE, Expr(..)) where + +import Text.Parsec +import Text.Parsec.Language +import Text.Parsec.Token +import Text.Parsec.Expr +import qualified Data.Functor.Identity + +data Expr = Plus Expr Expr + | Negate Expr + | Minus Expr Expr + | Times Expr Expr + | Div Expr Expr + | EInt Integer + | EFloat Double + | E + | Pi + | Log Expr + | Sin Expr + | Cos Expr + | Sqrt Expr + +tokenParser :: TokenParser st +tokenParser = haskell + +parseNumber :: Parsec String u Expr +parseNumber = do n <- naturalOrFloat tokenParser + case n of + Left i -> return (EInt i) + Right d -> return (EFloat d) + +tokenS :: String -> Parsec String u () +tokenS s = () <$ try (symbol tokenParser s) + +inner :: Parsec String u Expr +inner = parseNumber <|> E <$ tokenS "e" <|> Pi <$ tokenS "pi" <|> parens tokenParser parseExpr + +binary :: String -> (a -> a -> a) -> Assoc + -> Operator String u Data.Functor.Identity.Identity a +binary name fun assoc = + Infix (fun <$ tokenS name) assoc + +prefix :: String -> (a -> a) + -> Operator String u Data.Functor.Identity.Identity a +prefix name fun = Prefix (fun <$ tokenS name) + +table :: [[Operator String u Data.Functor.Identity.Identity Expr]] +table = [ [ prefix "log" Log, prefix "sin" Sin, prefix "cos" Cos, prefix "sqrt" Sqrt ] + , [ prefix "-" Negate ] + , [ binary "*" Times AssocLeft + , binary "/" Div AssocLeft + ] + , [ binary "+" Plus AssocLeft + , binary "-" Minus AssocLeft + ] + ] + +parseExpr :: Parsec String u Expr +parseExpr = buildExpressionParser table inner + +parser :: Parsec String u Expr +parser = do whiteSpace tokenParser + parseExpr + +parseE :: String -> Either ParseError Expr +parseE s = parse parser "" s |
