-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMiniParse.hs
89 lines (60 loc) · 2.28 KB
/
MiniParse.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
81
82
83
84
85
86
87
88
89
module MiniParse where
import Control.Applicative
import Control.Monad(ap)
-- Definition and instances of a simple monadic parser. Failure
-- is coded by the empty list in nondeterministic parsing
-- and by Nothing in deterministic parsing.
----------------------------------------------------------------------
newtype Parser a = P (String -> [ (a, String) ])
-- Non-determinisitc parse. This is what makes Parser a monad.
ndParse :: Parser a -> String -> [ (a, String) ]
ndParse (P f) s = f s
-- Forced deterministic parse. Discards the return value.
parse :: Parser a -> String -> Maybe a
parse p s = case ndParse p s of
(x, _) : _ -> Just x
_ -> Nothing
instance Monad Parser where
return x = P $ \ s -> [ (x, s) ]
p >>= pf = P $ \ s -> do (x, s) <- ndParse p s
ndParse (pf x) s
fail _ = P $ const []
instance Applicative Parser where
pure = return
(<*>) = ap
instance Functor Parser where
fmap = liftA
instance Alternative Parser where
empty = P $ const []
p1 <|> p2 = P $ \s -> case (ndParse p1 s, ndParse p2 s) of
(x : _, _) -> [x]
(_, y : _) -> [y]
_ -> []
-- Some useful parsers and parser combinators.
----------------------------------------------------------------------
-- Reads one charcter.
getCh :: Parser Char
getCh = P $ \ s -> case s of
"" -> []
c : cs -> [(c, cs)]
-- Succeeds only on the empty string.
end :: Parser ()
end = P $ \ s -> case s of
"" -> [((), "")]
_ -> []
-- final p succeeds only if p consumes all the input.
final :: Parser a -> Parser a
final p = do x <- p
end
return x
-- Picks a single character satisfying the predicate, fails otherwise.
satisfy :: (Char -> Bool) -> Parser Char
satisfy f = do c <- getCh
if (f c) then return c else empty
-- Picks the given character, fails otherwise.
char :: Char -> Parser Char
char c = satisfy (== c)
-- This is nondeterministic choice. Combines all possible
-- results. Note that <|> is deterministic.
choose :: Parser a -> Parser a -> Parser a
choose p1 p2 = P (\ s -> ndParse p1 s ++ ndParse p2 s)