import qualified Data.Char as Ctype main = do cs <- getContents print $ calculate $ parse cs -- TODO: op n1 n2 以外の式にも対応 calculate :: [Token] -> Int calculate (op:n1:n2:rest) = case [op, n1, n2] of [Add , (TokenNumber i1), (TokenNumber i2)] -> i1 + i2 [Subtract, (TokenNumber i1), (TokenNumber i2)] -> i1 - i2 [Multiply, (TokenNumber i1), (TokenNumber i2)] -> i1 * i2 [Divide , (TokenNumber i1), (TokenNumber i2)] -> i1 `div` i2 otherwise -> error "invalid expression" parse = parse' [getOp, getNum, getNum] parse' :: [(String -> (Token, String))] -> String -> [Token] parse' [] cs = [] parse' (tokenize:ts) cs = let (token, rest) = tokenize cs in token : (parse' ts $ dropWhile Ctype.isSpace rest) data Token = Add | Subtract | Multiply | Divide | TokenNumber Int deriving Show getOp ('+':rest) = (Add, rest) getOp ('-':rest) = (Subtract, rest) getOp ('*':rest) = (Multiply, rest) getOp ('/':rest) = (Divide, rest) getOp (token:rest) = error $ "unknown token '" ++ [token] ++ "'." -- TODO: 2桁以上、単項マイナスに対応 getNum (token:rest) | Ctype.isNumber token = (TokenNumber (read [token] :: Int), rest) getNum (token:_) = error $ "expected number, but got token '" ++ [token] ++ "'."