2 import Text.ParserCombinators.Parsec
3 import Text.ParserCombinators.Parsec.Expr
4 import qualified Text.ParserCombinators.Parsec.Token as P
5 import Text.ParserCombinators.Parsec.Language
8 lexer :: P.TokenParser ()
9 lexer = P.makeTokenParser (haskellDef { reservedOpNames = ["*","/","+","-","**"] })
11 naturalOrFloat = P.naturalOrFloat lexer
12 parens = P.parens lexer
13 reservedOp = P.reservedOp lexer
16 expr = buildExpressionParser table factor <?> "expression"
19 [unary "-" negate, unary "+" id],
20 [op "**" (**) AssocRight],
21 [op "*" (*) AssocLeft, op "/" (/) AssocLeft],
22 [op "+" (+) AssocLeft, op "-" (-) AssocLeft]
24 op s f assoc = Infix (do{ reservedOp s; return f } <?> "operator") assoc
25 unary s f = Prefix (do{ reservedOp s; return f })
27 factor :: Parser Double
32 norf <- naturalOrFloat;
34 Left i -> return $ fromInteger i
39 repl :: String -> (String -> Bool) -> (String -> String) -> IO ()
40 repl prompt bQuit eval = loop
47 else putStrLn (eval s) >> loop
50 calc = repl "> " (== ":q") (tostring . parse stmt "")
52 tostring (Right v) = show v
53 tostring (Left err) = show err
59 main = hSetBuffering stdout NoBuffering >> putStrLn "type ':q' to quit." >> calc >> putStrLn "Bye"