48 lines
977 B
Haskell
48 lines
977 B
Haskell
{-# LANGUAGE FlexibleContexts #-}
|
|
|
|
import Text.Parsec
|
|
import Text.Parsec.Expr
|
|
import Text.Parsec.Combinator
|
|
import Data.Functor
|
|
import Data.Function (on)
|
|
|
|
data Exp
|
|
= Num Int
|
|
| Add Exp
|
|
Exp
|
|
| Sub Exp
|
|
Exp
|
|
| Mul Exp
|
|
Exp
|
|
| Div Exp
|
|
Exp
|
|
|
|
expr
|
|
:: Stream s m Char
|
|
=> ParsecT s u m Exp
|
|
expr = buildExpressionParser table factor
|
|
where
|
|
table =
|
|
[ [op "*" Mul AssocLeft, op "/" Div AssocLeft]
|
|
, [op "+" Add AssocLeft, op "-" Sub AssocLeft]
|
|
]
|
|
op s f = Infix (f <$ string s)
|
|
factor = (between `on` char) '(' ')' expr <|> (Num . read <$> many1 digit)
|
|
|
|
eval
|
|
:: Integral a
|
|
=> Exp -> a
|
|
eval (Num x) = fromIntegral x
|
|
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 `div` eval b
|
|
|
|
solution
|
|
:: Integral a
|
|
=> String -> a
|
|
solution = either (const (error "Did not parse")) eval . parse expr ""
|
|
|
|
main :: IO ()
|
|
main = print $ solution "(1+3)*7"
|