Skip to content

Instantly share code, notes, and snippets.

@m00nlight
Created March 30, 2015 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m00nlight/2868363ec217f97072b4 to your computer and use it in GitHub Desktop.
Save m00nlight/2868363ec217f97072b4 to your computer and use it in GitHub Desktop.
Simple Haskell arithmetic parser and evaluator
import Text.Parsec
import Text.Parsec.Expr
import Text.Parsec.Combinator
import Data.Functor
data Exp = Num Int
| Add Exp Exp
| Sub Exp Exp
| Mul Exp Exp
| Div Exp Exp
| Pos Exp
| Neg Exp
expr = buildExpressionParser table factor <?> "expr"
table = [[prefix "-" (Neg), prefix "+" (Pos)]
,[op "*" (Mul) AssocRight, op "/" (Div) AssocRight]
,[op "+" (Add) AssocLeft, op "-" (Sub) AssocLeft]]
where op s f assoc = Infix (f <$ string s) assoc
prefix s f = Prefix (f <$ string s)
factor = between (char '(') (char ')') expr
<|> (Num . read <$> many1 digit) <?> "factor"
eval :: (Num a, Integral a) => Exp -> a
eval e = case e of
Num x -> fromIntegral x
Pos a -> eval a
Neg a -> negate $ eval a
Add a b -> eval a + eval b
Sub a b -> eval a - eval b
Mul a b -> eval a * eval b
Div a b -> eval a `div` eval b
solution :: (Num a, Integral a) => String -> a
solution = either (error . show) eval . parse expr ""
main = do
line <- getLine
putStrLn $ show $ solution (filter (/=' ') line)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment