Skip to content

Commit 0a8cdf6

Browse files
committed
Add first set of solutions to the chapter exercise
1 parent 704d5f2 commit 0a8cdf6

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import Control.Applicative
2+
import Data.Char
3+
4+
-----------------------------------------------------------------------------
5+
-- 1.
6+
comment :: Parser ()
7+
comment = do
8+
string "--"
9+
many $ sat (/= '\n')
10+
return ()
11+
12+
-----------------------------------------------------------------------------
13+
-- 2.
14+
-- expr
15+
-- / | \
16+
-- / + \
17+
-- expr expr
18+
-- / | \ \
19+
-- / + \ \
20+
-- expr expr term
21+
-- | | |
22+
-- term term factor
23+
-- | | |
24+
-- factor factor nat
25+
-- | | |
26+
-- nat nat 4
27+
-- | |
28+
-- 2 3
29+
30+
-----------------------------------------------------------------------------
31+
-- 3.
32+
-- expr
33+
-- / | \
34+
-- / + \
35+
-- term expr
36+
-- | |
37+
-- factor term
38+
-- | |
39+
-- nat factor
40+
-- | |
41+
-- 2 nat
42+
-- |
43+
-- 3
44+
45+
-----------------------------------------------------------------------------
46+
-- 4.
47+
-- Answer: Each number would end up being parsed multiple times before
48+
-- recognizing that it could be an expression.
49+
50+
-----------------------------------------------------------------------------
51+
-- 5.
52+
data Expr = Val Int
53+
| Add Expr Expr
54+
| Sub Expr Expr
55+
deriving Show
56+
57+
expr' :: Parser Expr
58+
expr' = do
59+
t <- term
60+
do symbol "+"
61+
e <- expr'
62+
return (Add (Val t) e)
63+
<|> do symbol "-"
64+
e <- expr'
65+
return (Sub (Val t) e)
66+
<|> return (Val t)
67+
68+
-----------------------------------------------------------------------------
69+
70+
expr :: Parser Int
71+
expr = do
72+
t <- term
73+
do symbol "+"
74+
e <- expr
75+
return (t + e)
76+
<|> do symbol "-"
77+
e <- expr
78+
return (t - e)
79+
<|> return t
80+
81+
term :: Parser Int
82+
term = do
83+
f <- factor
84+
do symbol "*"
85+
t <- term
86+
return (f * t)
87+
<|> do symbol "/"
88+
t <- term
89+
return (f `div` t)
90+
<|> return f
91+
92+
factor :: Parser Int
93+
factor = do symbol "("
94+
e <- expr
95+
symbol ")"
96+
return e
97+
<|> nat
98+
-----------------------------------------------------------------------------
99+
newtype Parser a = P (String -> [(a, String)])
100+
101+
parse :: Parser a -> String -> [(a, String)]
102+
parse (P p) inp = p inp
103+
104+
item :: Parser Char
105+
item = P $ \inp ->
106+
case inp of
107+
[] -> []
108+
(x:xs) -> [(x, xs)]
109+
110+
sat :: (Char -> Bool) -> Parser Char
111+
sat p = do
112+
x <- item
113+
if p x
114+
then return x
115+
else empty
116+
117+
symbol :: String -> Parser String
118+
symbol xs = token (string xs)
119+
120+
token :: Parser a -> Parser a
121+
token p = do
122+
space
123+
v <- p
124+
space
125+
return v
126+
127+
space :: Parser ()
128+
space = do
129+
many (sat isSpace)
130+
return ()
131+
132+
nat :: Parser Int
133+
nat = do
134+
xs <- some digit
135+
return (read xs)
136+
137+
digit :: Parser Char
138+
digit = sat isDigit
139+
140+
string :: String -> Parser String
141+
string [] = return []
142+
string (x:xs) = do
143+
char x
144+
string xs
145+
return (x:xs)
146+
147+
char :: Char -> Parser Char
148+
char x = sat (== x)
149+
150+
instance Functor Parser where
151+
fmap f p = P $ \inp ->
152+
case parse p inp of
153+
[] -> []
154+
[(v, out)] -> [(f v, out)]
155+
156+
instance Applicative Parser where
157+
pure v = P $ \inp -> [(v, inp)]
158+
159+
pf <*> px = P $ \inp ->
160+
case parse pf inp of
161+
[] -> []
162+
[(f, out)] -> parse (fmap f px) out
163+
164+
instance Monad Parser where
165+
p >>= f = P $ \inp ->
166+
case parse p inp of
167+
[] -> []
168+
[(v, out)] -> parse (f v) out
169+
170+
instance Alternative Parser where
171+
empty = P $ \inp -> []
172+
173+
p <|> q = P $ \inp ->
174+
case parse p inp of
175+
[] -> parse q inp
176+
[(v, out)] -> [(v, out)]

0 commit comments

Comments
 (0)