-
Notifications
You must be signed in to change notification settings - Fork 0
/
ParsingExt.hs
80 lines (69 loc) · 2.05 KB
/
ParsingExt.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
-- /
-- Author : Yasser Bennani
-- CW 2 Part 2 - Exam
-- /
module ParsingExt (module Parsing, evaluate, eval, isError) where
-- This module extends the Parsing module by Graham Hutton (modified)
-- and adds support for fractional numbers as well as evaluation
-- expression based on grammar rules described below
import Parsing
import Text.Read (readMaybe)
import Data.List (isInfixOf)
-- Add support for parsing fractional numbers
dbl :: Parser Double
dbl = do number <- some digit
char '.'
fractional <- some digit
return (read $ number ++ '.' : fractional)
double :: Parser Double
double = dbl
<|> do char '-'
d <- dbl
return (-d)
<|> integer
-- implementing addition
-- expr = expr + term | expr - term | term
expr :: Parser Double
expr = do t <- term
symbol "+"
e <- expr
return (t + e)
<|> do t <- term
symbol "-"
e <- expr
return (t - e)
<|> term
-- implementing multiplication
-- term = term * factor | term / factor | factor
term :: Parser Double
term = do f <- factor
symbol "*"
t <- term
return (f * t)
<|> do f <- factor
symbol "/"
t <- term
return (f / t)
<|> factor
-- implemeting support for parentheses
-- factor = (expr) | double
factor :: Parser Double
factor = do symbol "("
e <- expr
symbol ")"
return e
<|> double
-- evaluate parsed expression using the parse
-- function from the imported Parsing library
eval :: String -> String
eval exp = case parse expr exp of
[(a,[])] -> show a
[(_, i)] -> incompleteErr ++ show i
[] -> invalidErr
evaluate :: String -> Maybe Double
evaluate input = readMaybe $ eval input
incompleteErr, invalidErr :: String
incompleteErr = "Incomplete expression: "
invalidErr = "Invalid expression..."
isError :: String -> Bool
isError inp = isInfixOf incompleteErr inp || inp == invalidErr