Skip to content

Instantly share code, notes, and snippets.

@bartavelle
Created May 22, 2014 18:51
Show Gist options
  • Save bartavelle/2ece96ee5394b79da8f6 to your computer and use it in GitHub Desktop.
Save bartavelle/2ece96ee5394b79da8f6 to your computer and use it in GitHub Desktop.
calculator
module Main where
import Text.Parsec.String (Parser)
import Text.Parsec.Prim (parse)
import Text.Parser.Expression
import Text.Parser.Token
import Control.Applicative
import Control.Monad
data Expr = Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| Neg Expr
| Term Double
deriving Show
eval :: Expr -> Double
eval (Term d) = d
eval (Add a b) = eval a + eval b
eval (Sub a b) = eval a - eval b
eval (Mul a b) = eval a * eval b
eval (Div a b) = eval a / eval b
eval (Neg a) = negate (eval a)
expr :: Parser Expr
expr = buildExpressionParser table term
where
table = [ [prefix "-" Neg, prefix "+" id ]
, [binary "*" Mul AssocLeft, binary "/" Div AssocLeft ]
, [binary "+" Add AssocLeft, binary "-" Sub AssocLeft ]
]
binary name fun = Infix (fun <$ symbol name)
prefix name fun = Prefix (fun <$ symbol name)
term :: Parser Expr
term = parens expr
<|> token num
num :: Parser Expr
num = Term . toDouble <$> integerOrDouble
where toDouble (Left i) = fromIntegral i
toDouble (Right d) = d
main :: IO ()
main = forever $ do
putStrLn "enter a math expression (+ - * /, floats, parentheses) or enter to exit:"
o <- parse expr "stdin" <$> getLine
case o of
Left rr -> print rr
Right ast -> print ast >> print (eval ast)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment