Skip to content

Instantly share code, notes, and snippets.

@tyru
Forked from anonymous/pn.hs
Created December 19, 2011 01:24
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 tyru/1495039 to your computer and use it in GitHub Desktop.
Save tyru/1495039 to your computer and use it in GitHub Desktop.
Polish Notation
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] ++ "'."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment