Skip to content

Commit c8362cd

Browse files
author
matteB10
committed
removed desktop.ini
2 parents 96c25a8 + 0d3b245 commit c8362cd

File tree

5 files changed

+422
-3
lines changed

5 files changed

+422
-3
lines changed

Expr.hs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
module Expr where
2+
import Data.List
3+
import Parsing
4+
5+
6+
-- A --
7+
data Expr = Num Double
8+
| MonoOp MonoFunc Expr
9+
| BinOp BinFunc Expr Expr
10+
| Var Char
11+
deriving (Eq, Show)
12+
13+
data MonoFunc = Sin | Cos
14+
deriving (Eq, Show)
15+
16+
data BinFunc = Add | Mul
17+
deriving (Eq, Show)
18+
19+
x :: Expr
20+
x = Var 'x'
21+
num :: Double -> Expr
22+
num d = Num d
23+
sin, cos :: Expr -> Expr
24+
sin exp = MonoOp Sin exp
25+
cos exp = MonoOp Cos exp
26+
add, mul :: Expr -> Expr -> Expr
27+
add exp1 exp2 = BinOp Add exp1 exp2
28+
mul exp1 exp2 = BinOp Mul exp1 exp2
29+
30+
-- Test data --
31+
e1 = add (mul (Num 3) (Var 'x')) (Num 17.3) -- 3*x + 17.3
32+
e2 = mul (add (Num 4) (Num 3)) (add (Num 1) (Num 1)) -- (4+3)*(1+1) = 14
33+
e3 = mul (Num 5) (add (Num 2) (Num 3)) -- 5 * (2+3) = 25
34+
e4 = mul (Var 'x') (Num 4) -- x*4
35+
---------------
36+
37+
-- B --
38+
showExpr :: Expr -> String
39+
showExpr (Num n) = show n
40+
showExpr (Var _) = "x"
41+
showExpr (MonoOp Sin e) = "sin" ++ showExpr e
42+
showExpr (MonoOp Cos e) = "cos" ++ showExpr e
43+
showExpr (BinOp Add e1 e2) = showPlus e1 e2
44+
showExpr (BinOp Mul e1 e2) = showFactor e1 ++ "*" ++ showFactor e2
45+
46+
showFactor (BinOp Add e1 e2) = "(" ++ showPlus e1 e2 ++ ")"
47+
showFactor e = showExpr e
48+
49+
showPlus e1 e2 = showExpr e1 ++ "+" ++ showExpr e2
50+
51+
-- C --
52+
eval :: Expr -> Double -> Double
53+
eval (Num n) _ = n
54+
eval (Var _) n = n
55+
eval (MonoOp Sin e) n = Prelude.sin $ eval e n
56+
eval (MonoOp Cos e) n = Prelude.cos $ eval e n
57+
eval (BinOp Add e1 e2) n = eval e1 n + eval e2 n
58+
eval (BinOp Mul e1 e2) n = eval e1 n * eval e2 n
59+
60+
-- D --
61+
expr, term, factor :: Parser Expr
62+
expr = foldl1 add <$> chain term (char '+')
63+
term = foldl1 mul <$> chain factor (char '*')
64+
factor = Num <$> number
65+
<|> Var <$> char 'x'
66+
<|> char '(' *> expr <* char ')'
67+
68+
readExpr :: String -> Maybe Expr
69+
readExpr s = do
70+
(exp, "") <- parse expr s
71+
return exp
72+
73+
number :: Parser Double
74+
number = read <$> oneOrMore digit
75+
76+
function :: Parser Expr
77+
function = undefined

ParsingExamples.hs

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
-- | Parsing
2+
-- Examples to illustrate how to write parsers using parsing combinators
3+
-- Functional Programming course 2018.
4+
-- Thomas Hallgren
5+
6+
{-
7+
This started as a skeleton, the definitions were filled in
8+
during the lecture.
9+
-}
10+
module ParsingExamples where
11+
import Data.Char(isDigit)
12+
import Parsing hiding (chain,digit)
13+
import Control.Monad(forever)
14+
15+
--------------------------------------------------------------------------------
16+
-- * A first example
17+
-- Writing a recursive decent parser directly
18+
-- Using functions of type String -> Maybe (a,String)
19+
20+
{- BNF:
21+
digit = "0".."9".
22+
number = digit{digit}.
23+
addition = number "+" number.
24+
-}
25+
26+
type ParserFun a = String -> Maybe (a, String)
27+
28+
num :: ParserFun Integer
29+
num s = case span isDigit s of
30+
(d:ds, rest) -> Just (read (d:ds), rest) -- Only use read if we know it succeeds (not empty and not characters)
31+
_ -> Nothing
32+
33+
number_v1 :: String -> Maybe (Integer,String)
34+
number_v1 s = case span isDigit s of
35+
("",_) -> Nothing
36+
(ds,r) -> Just (read ds,r)
37+
38+
39+
addition0 :: ParserFun Integer
40+
addition0 s = case num s of
41+
Just (n, '+':r) -> case num r of
42+
Just (m, r') -> Just (n+m, r')
43+
_ -> Nothing
44+
_ -> Nothing
45+
46+
47+
addition_v1 :: String -> Maybe (Integer,String)
48+
addition_v1 s = case number_v1 s of
49+
Just (n1,'+':r1) -> case number_v1 r1 of
50+
Just (n2,r2) -> Just (n1+n2,r2)
51+
_ -> Nothing
52+
_ -> Nothing
53+
54+
55+
{- A small extension to the BNF
56+
multiplication ::= number "*" number.
57+
calculation ::= addition | multiplication.
58+
-}
59+
60+
multiplication_v1 :: String -> Maybe (Integer,String)
61+
multiplication_v1 s = case number_v1 s of
62+
Just (n1,'*':r1) -> case number_v1 r1 of
63+
Just (n2,r2) -> Just (n1*n2,r2)
64+
_ -> Nothing
65+
_ -> Nothing
66+
67+
68+
calculation_v1 :: String -> Maybe (Integer,String)
69+
calculation_v1 s = case addition_v1 s of
70+
Nothing -> multiplication_v1 s
71+
result -> result
72+
73+
74+
--------------------------------------------------------------------------------
75+
-- * Rewriting our first example using parsing combinators
76+
77+
-- | Parse a digit (also available in the Parsing module)
78+
digit :: Parser Char
79+
digit = sat isDigit
80+
81+
-- | Parse a number
82+
number :: Parser Integer
83+
number = read <$> oneOrMore digit
84+
--do ds <- oneOrMore digit
85+
-- return (read ds)
86+
87+
-- | Parse two numbers, separated by +, and add them
88+
addition :: Parser Integer
89+
{-
90+
addition = do n1 <- number
91+
char '+'
92+
n2 <- number
93+
return (n1+n2) -}
94+
95+
96+
{-
97+
addition = do n1 <- number
98+
char '+'
99+
n2 <- number
100+
return (n1+n2)
101+
-}
102+
addition = operator '+' (+)
103+
104+
-- | Parse two numbers, separated by *, and multiply them
105+
multiplication :: Parser Integer
106+
{-
107+
multiplication =do n1 <- number
108+
char '*'
109+
n2 <- number
110+
return (n1*n2)
111+
-}
112+
multiplication = operator '*' (*)
113+
114+
operator c op = do n1 <- number
115+
char c
116+
n2 <- number
117+
return (n1 `op` n2)
118+
119+
120+
calculation :: Parser Integer
121+
calculation = addition <|> multiplication
122+
123+
--------------------------------------------------------------------------------
124+
-- * An expression parser (version 1)
125+
126+
data Expr = Num Integer
127+
| Add Expr Expr
128+
| Mul Expr Expr
129+
deriving (Eq,Show)
130+
131+
eval :: Expr -> Integer
132+
eval (Num n) = n
133+
eval (Add a b) = eval a + eval b
134+
eval (Mul a b) = eval a * eval b
135+
136+
{- EBNF:
137+
expr ::= term {"+" term}.
138+
term ::= factor {"*" factor}.
139+
factor ::= number | "(" expr ")".
140+
-}
141+
{-
142+
expr, term, factor :: Parser Expr
143+
144+
expr = do t <- term
145+
ts <- zeroOrMore (do char '+'; term)
146+
return (foldl1 Add (t:ts))
147+
148+
term = do f <- factor
149+
fs <- zeroOrMore (do char '*'; factor)
150+
return (foldl1 Mul (f:fs))
151+
152+
factor = -- Num <$> number
153+
do n <- number
154+
return (Num n)
155+
<|>
156+
do char '('
157+
e <- expr
158+
char ')'
159+
return e
160+
-}
161+
--------------------------------------------------------------------------------
162+
-- * A more elegant expression parser
163+
164+
165+
expr, term, factor :: Parser Expr
166+
expr = leftAssoc Add term (char '+')
167+
term = leftAssoc Mul factor (char '*')
168+
factor = (Num <$> number) <|> (char '(' *> expr <* char ')')
169+
170+
171+
172+
-- | Parse a list of items with separators
173+
-- (also available in the Parsing module)
174+
chain :: Parser item -> Parser sep -> Parser [item]
175+
chain item sep = do i <- item
176+
is <- zeroOrMore (do sep; item)
177+
return (i:is)
178+
179+
leftAssoc :: (t->t->t) -> Parser t -> Parser sep -> Parser t
180+
leftAssoc op item sep = do is <- chain item sep
181+
return (foldl1 op is)
182+
183+
rightAssoc op item sep = undefined -- exercise
184+
185+
--------------------------------------------------------------------------------
186+
-- * The simple calculator example
187+
188+
main = do putStrLn "Welcome to the simple calculator!"
189+
forever readEvalPrint
190+
191+
readEvalPrint = do putStr "Expression? "
192+
s <- getLine
193+
case parse expr s of
194+
Just (e,"") -> do putStr "Value: "
195+
print (eval e)
196+
_ -> putStrLn "Syntax error!"
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
--------------------------------------------------------------------------------
211+
-- * More examples
212+
213+
-- ** Data types with infix operatos
214+
infixl 6 :+
215+
infixl 7 :*
216+
217+
data Expr2 = C Integer
218+
| Expr2 :+ Expr2
219+
| Expr2 :* Expr2
220+
deriving (Show,Read) -- gives us almost what we want
221+
222+
ex1 = C 2
223+
ex2 = ex1 :+ ex1
224+
ex3 = C 1 :+ C 2 :* C 3
225+
ex4 = (C 1 :+ C 2) :* C 3
226+
227+
228+
-- | Parse a specific sequence of characters
229+
string :: String -> Parser String
230+
string "" = return ""
231+
string (c:s) = do c' <- char c
232+
s' <- string s
233+
return (c':s')

ParsingMB.hs

+5-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module Parsing
3333
, return
3434
)
3535

36+
<<<<<<< HEAD:ParsingMB.hs
3637
{----------------------
3738
3839
Aim: reusable Parser combinators including
@@ -58,6 +59,9 @@ readsP :: Read a => Parser a
5859
-- parse readsP s == listToMaybe (reads s)
5960
6061
----------------------}
62+
=======
63+
64+
>>>>>>> 0d3b2453122b330de7594a8a1c229e5b55a35fb9:Parsing.hs
6165
where
6266

6367
import Data.Char
@@ -180,4 +184,4 @@ instance Monad Parser where
180184

181185
instance Alternative Parser where
182186
empty = failure
183-
(<|>) = (+++)
187+
(<|>) = (+++)

0 commit comments

Comments
 (0)