{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE GADTs #-}
import Text.Parsec
import Text.Parsec.Pos
import Control.Arrow
import Control.Applicative ((<*>), (<$>), (*>), (<*), (<$))
-------------------------------------------------------------------------------
-- A couple of rewritten combinators for Chars
-------------------------------------------------------------------------------
-- Parse a lexeme which satisfies a predicate
satisfyP
:: (Show a
, Stream s m a
) => (a
-> Bool) -> ParsecT s u m a
satisfyP f
= tokenPrim
(\c
-> show c
) (\pos c
_cs
-> updatePosString pos
$ show c
) (\c -> if f c then Just c else Nothing)
-- Parse a lexeme which is equivalent to the given one
charP
:: (Show c
, Eq c
, Stream s m c
) => c
-> ParsecT s u m c
charP c
= satisfyP
(== c
) <?> show c
-- Parse any lexeme
anyCharP
:: (Show c
, Stream s m c
) => ParsecT s u m c
anyCharP
= satisfyP
$ const True
-- Parse a list of lexemes
stringP
:: (Eq c
, Show c
, Stream s m c
) => [c
] -> ParsecT s u m
[c
]
-------------------------------------------------------------------------------
-- Example of a lexer
-------------------------------------------------------------------------------
data Lex
= LInt
{ getInt
:: Integer} | LOper
Char | LBraceL
| LBraceR
lexer = many (lexeme <* many space) <* eof
lexeme = choice [l_int, l_oper, l_lbrace, l_rbrace]
l_int = (LInt 0 <$ char '0' <|> conv <$> digit1 <*> many digit) <* notFollowedBy letter where
conv x xs
= LInt
. read $ x : xs
digit1 = satisfy (\c -> '1' <= c && c <= '9')
l_oper = LOper <$> oneOf "+-*/"
l_lbrace = LBraceL <$ char '('
l_rbrace = LBraceR <$ char ')'
-- Get an integer literal lexeme from input
-- User-defined combinator
intLit = satisfyP isIntLit where
isIntLit (LInt _) = True
isIntLit _ = False
-------------------------------------------------------------------------------
-- Example of a parser
-------------------------------------------------------------------------------
data OpType = OAdd | OSub | OMul | ODiv
data Expr
= EInt
Integer | EOper OpType Expr Expr
parser = expr0 <* eof
expr0 = expr1 `chainl1` (EOper OAdd <$ charP (LOper '+') <|> EOper OSub <$ charP (LOper '-'))
expr1 = expr2 `chainl1` (EOper OMul <$ charP (LOper '*') <|> EOper ODiv <$ charP (LOper '/'))
expr2 = EInt . getInt <$> intLit <|> charP LBraceL *> expr0 <* charP LBraceR
-------------------------------------------------------------------------------
-- Evaluator
-------------------------------------------------------------------------------
div' x (Just 0) = Nothing div' x y
= liftM2
div x y
table
= [(OAdd
, liftM2
(+)), (OSub
, liftM2
(-)), (OMul
, liftM2
(*)), (ODiv
, div')]
eval :: Expr -> Maybe Integer
eval (EInt x) = return x
eval (EOper op l r) = do
oper <- lookup op table
eval l `oper` eval r
-------------------------------------------------------------------------------
-- Run it all.
-------------------------------------------------------------------------------
lexparse l p s = act lr where
act (Right lr) = parse p "" lr
act (Left e) = Left e
lr = parse l "" s
res e = show e ++ " = " ++ show (eval e)
main = do
test <- getLine
let expr = lexparse lexer parser test
putStrLn $ show ||| res $ expr
ey0jIExBTkdVQUdFIE5vTW9ub21vcnBoaXNtUmVzdHJpY3Rpb24gIy19CnstIyBMQU5HVUFHRSBHQURUcyAjLX0KaW1wb3J0IERhdGEuTWF5YmUKaW1wb3J0IFRleHQuUGFyc2VjCmltcG9ydCBUZXh0LlBhcnNlYy5Qb3MKaW1wb3J0IENvbnRyb2wuTW9uYWQKaW1wb3J0IENvbnRyb2wuQXJyb3cKaW1wb3J0IENvbnRyb2wuQXBwbGljYXRpdmUgKCg8Kj4pLCAoPCQ+KSwgKCo+KSwgKDwqKSwgKDwkKSkKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLS0gQSBjb3VwbGUgb2YgcmV3cml0dGVuIGNvbWJpbmF0b3JzIGZvciBDaGFycwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgotLSBQYXJzZSBhIGxleGVtZSB3aGljaCBzYXRpc2ZpZXMgYSBwcmVkaWNhdGUKc2F0aXNmeVAgOjogKFNob3cgYSwgU3RyZWFtIHMgbSBhKSA9PiAoYSAtPiBCb29sKSAtPiBQYXJzZWNUIHMgdSBtIGEKc2F0aXNmeVAgZiA9IHRva2VuUHJpbSAoXGMgLT4gc2hvdyBjKQogICAgICAgICAgICAgICAgICAgICAgIChccG9zIGMgX2NzIC0+IHVwZGF0ZVBvc1N0cmluZyBwb3MgJCBzaG93IGMpCiAgICAgICAgICAgICAgICAgICAgICAgKFxjIC0+IGlmIGYgYyB0aGVuIEp1c3QgYyBlbHNlIE5vdGhpbmcpCiAgICAJCQkJIAotLSBQYXJzZSBhIGxleGVtZSB3aGljaCBpcyBlcXVpdmFsZW50IHRvIHRoZSBnaXZlbiBvbmUKY2hhclAgICAgOjogKFNob3cgYywgRXEgYywgU3RyZWFtIHMgbSBjKSA9PiBjIC0+IFBhcnNlY1QgcyB1IG0gYwpjaGFyUCBjICAgPSBzYXRpc2Z5UCAoPT0gYykgPD8+IHNob3cgYyAKCi0tIFBhcnNlIGFueSBsZXhlbWUKYW55Q2hhclAgOjogKFNob3cgYywgU3RyZWFtIHMgbSBjKSA9PiBQYXJzZWNUIHMgdSBtIGMKYW55Q2hhclAgID0gc2F0aXNmeVAgJCBjb25zdCBUcnVlCgotLSBQYXJzZSBhIGxpc3Qgb2YgbGV4ZW1lcwpzdHJpbmdQICA6OiAoRXEgYywgU2hvdyBjLCBTdHJlYW0gcyBtIGMpID0+IFtjXSAtPiBQYXJzZWNUIHMgdSBtIFtjXQpzdHJpbmdQIHMgPSB0b2tlbnMgKGNvbmNhdCAuIG1hcCBzaG93KSAoXHAgY3MgLT4gdXBkYXRlUG9zU3RyaW5nIHAgJCBjb25jYXQgLiBtYXAgc2hvdyAkIGNzKSBzCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi0tIEV4YW1wbGUgb2YgYSBsZXhlcgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpkYXRhIExleCA9IExJbnQgeyBnZXRJbnQgOjogSW50ZWdlcn0gfCBMT3BlciBDaGFyIHwgTEJyYWNlTCB8IExCcmFjZVIKCWRlcml2aW5nIChFcSwgU2hvdykKCmxleGVyICAgID0gbWFueSAobGV4ZW1lIDwqIG1hbnkgc3BhY2UpIDwqIGVvZgpsZXhlbWUgICA9IGNob2ljZSBbbF9pbnQsIGxfb3BlciwgbF9sYnJhY2UsIGxfcmJyYWNlXQpsX2ludCAgICA9IChMSW50IDAgPCQgY2hhciAnMCcgPHw+IGNvbnYgPCQ+IGRpZ2l0MSA8Kj4gbWFueSBkaWdpdCkgPCogbm90Rm9sbG93ZWRCeSBsZXR0ZXIgd2hlcmUKCWNvbnYgeCB4cyA9IExJbnQgLiByZWFkICQgeCA6IHhzCmRpZ2l0MSAgID0gc2F0aXNmeSAoXGMgLT4gJzEnIDw9IGMgJiYgYyA8PSAnOScpCmxfb3BlciAgID0gTE9wZXIgPCQ+IG9uZU9mICIrLSovIgpsX2xicmFjZSA9IExCcmFjZUwgPCQgY2hhciAnKCcKbF9yYnJhY2UgPSBMQnJhY2VSIDwkIGNoYXIgJyknCgotLSBHZXQgYW4gaW50ZWdlciBsaXRlcmFsIGxleGVtZSBmcm9tIGlucHV0Ci0tIFVzZXItZGVmaW5lZCBjb21iaW5hdG9yCmludExpdCA9IHNhdGlzZnlQIGlzSW50TGl0IHdoZXJlCglpc0ludExpdCAoTEludCBfKSA9IFRydWUKCWlzSW50TGl0IF8gPSBGYWxzZQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQotLSBFeGFtcGxlIG9mIGEgcGFyc2VyCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCQpkYXRhIE9wVHlwZSA9IE9BZGQgfCBPU3ViIHwgT011bCB8IE9EaXYKCWRlcml2aW5nIChFcSwgU2hvdykKZGF0YSBFeHByID0gRUludCBJbnRlZ2VyIHwgRU9wZXIgT3BUeXBlIEV4cHIgRXhwcgoJZGVyaXZpbmcgKEVxLCBTaG93KQoKcGFyc2VyID0gZXhwcjAgPCogZW9mCmV4cHIwID0gZXhwcjEgYGNoYWlubDFgIChFT3BlciBPQWRkIDwkIGNoYXJQIChMT3BlciAnKycpIDx8PiBFT3BlciBPU3ViIDwkIGNoYXJQIChMT3BlciAnLScpKQpleHByMSA9IGV4cHIyIGBjaGFpbmwxYCAoRU9wZXIgT011bCA8JCBjaGFyUCAoTE9wZXIgJyonKSA8fD4gRU9wZXIgT0RpdiA8JCBjaGFyUCAoTE9wZXIgJy8nKSkKZXhwcjIgPSBFSW50IC4gZ2V0SW50IDwkPiBpbnRMaXQgPHw+IGNoYXJQIExCcmFjZUwgKj4gZXhwcjAgPCogY2hhclAgTEJyYWNlUgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQotLSBFdmFsdWF0b3IKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZGl2JyB4IChKdXN0IDApID0gTm90aGluZwpkaXYnIHggeSA9IGxpZnRNMiBkaXYgeCB5Cgp0YWJsZSA9IFsoT0FkZCwgbGlmdE0yICgrKSksIChPU3ViLCBsaWZ0TTIgKC0pKSwgKE9NdWwsIGxpZnRNMiAoKikpLCAoT0RpdiwgZGl2JyldCgpldmFsIDo6IEV4cHIgLT4gTWF5YmUgSW50ZWdlcgpldmFsIChFSW50IHgpID0gcmV0dXJuIHgKZXZhbCAoRU9wZXIgb3AgbCByKSA9IGRvCglvcGVyIDwtIGxvb2t1cCBvcCB0YWJsZQoJZXZhbCBsIGBvcGVyYCBldmFsIHIKCQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi0tIFJ1biBpdCBhbGwuCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmxleHBhcnNlIGwgcCBzID0gYWN0IGxyIHdoZXJlCglhY3QgKFJpZ2h0IGxyKSA9IHBhcnNlIHAgIiIgbHIKCWFjdCAoTGVmdCBlKSA9IExlZnQgZQoJbHIgPSBwYXJzZSBsICIiIHMKCnJlcyBlID0gc2hvdyBlICsrICIgPSAiICsrIHNob3cgKGV2YWwgZSkKCQptYWluID0gZG8KCXRlc3QgPC0gZ2V0TGluZQoJbGV0IGV4cHIgPSBsZXhwYXJzZSBsZXhlciBwYXJzZXIgdGVzdAoJcHV0U3RyTG4gJCBzaG93IHx8fCByZXMgJCBleHBy