Skip to content

Instantly share code, notes, and snippets.

@tiqwab
Created October 16, 2016 23:10
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save tiqwab/5f62ebf25b30aa0fe034d037e5c9e36e to your computer and use it in GitHub Desktop.
import System.Environment
import Text.Parsec
import Text.ParserCombinators.Parsec hiding (try)
{-
Implement calculator with `Parsec` package.
-}
{-
# EBNF
expr = term, {("+", term) | ("-", term)}
term = factor, {("*", factor) | ("/", factor)}
factor = "(", expr, ")" | integer
integer = non-zero-digit, {digit}
digit = "0" | non-zero-digit
non-zero-digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
-}
{-
chainl1 :: (Stream s m t) => ParsecT s u m a
-> ParsecT s u m (a -> a -> a)
-> ParsecT s u m a
chainl1 p op = do{ x <- p; rest x }
where
rest x = do{ f <- op
; y <- p
; rest (f x y)
}
<|> return x
-}
expr = term `chainl1` addop
term = factor `chainl1` mulop
factor = between (char '(') (char ')') expr
<|> integer
addop = char '+' *> return (+)
<|> char '-' *> return (-)
mulop = char '*' *> return (*)
<|> char '/' *> return div
integer = read <$> many1 digit
-- :main "(1+2)+5*(2+3)"
-- -> 28
main = do args <- getArgs
parseTest (expr :: CharParser () Int) (head args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment