2
2
Module : Parsing
3
3
Description : Simple Monadic Parsing Library
4
4
Maintainer : Thomas Hallgren
5
+
5
6
A Simple Monadic Parsing Library
7
+
6
8
Used in the course Functional Programming GU/Chalmers.
7
- Original author: David Sands.
8
9
9
- ---------------------
10
- Aim: reusable Parser combinators including
11
- a new type for the Parser,
12
- but no export of the constructor
13
- Changes (v3 2016) Thomas Hallgren
14
- Export <* and *> from class Applicative instead of the combinators <-< and >->
15
- Export <|> from class Alternative instead of +++
16
- Changes (v2 2015)
17
- For compatibility with GHC>=7.10 Parser
18
- is now also instance Applicative
19
- Removal: Class Functor, Applicative and Monad provide a number of
20
- functions that were previously exported explicitly, in particular
21
- (>*>) is available as the bind operation (>>=),
22
- success is return, pmap is fmap.
23
- Additional function:
24
- readsP :: Read a => Parser a
25
- -- satisfies
26
- -- parse readsP s == listToMaybe (reads s)
27
- ---------------------
10
+ Original author: David Sands.
28
11
-}
12
+
29
13
module Parsing
30
14
( -- * The Parser type
31
15
Parser -- exports the type name but not the constructors
@@ -47,51 +31,94 @@ module Parsing
47
31
,(*>)
48
32
-- ** Return a result without consuming any input
49
33
, return
50
- )
34
+ )
35
+
36
+ {- ---------------------
37
+
38
+ Aim: reusable Parser combinators including
39
+ a new type for the Parser,
40
+ but no export of the constructor
41
+
42
+ Changes (v3 2016) Thomas Hallgren
43
+ Export <* and *> from class Applicative instead of the combinators <-< and >->
44
+ Export <|> from class Alternative instead of +++
45
+
46
+ Changes (v2 2015)
47
+ For compatibility with GHC>=7.10 Parser
48
+ is now also instance Applicative
49
+
50
+ Removal: Class Functor, Applicative and Monad provide a number of
51
+ functions that were previously exported explicitly, in particular
52
+ (>*>) is available as the bind operation (>>=),
53
+ success is return, pmap is fmap.
54
+
55
+ Additional function:
56
+ readsP :: Read a => Parser a
57
+ -- satisfies
58
+ -- parse readsP s == listToMaybe (reads s)
59
+
60
+ ----------------------}
51
61
where
62
+
52
63
import Data.Char
53
64
import Data.Maybe (listToMaybe )
54
65
-- boilerplate for GHC 10.7 compatibility:
55
66
import Control.Applicative (Applicative (.. ),Alternative (.. ))
56
67
import Control.Monad (liftM , ap )
68
+
57
69
------------------
58
70
71
+
72
+
73
+
59
74
-- | The abstract data type representing a Parser
60
75
newtype Parser a = P (String -> Maybe (a ,String ))
76
+
61
77
-- | Runs the parser on the given string
62
78
-- to return maybe a thing and a string
63
79
parse :: Parser a -> String -> Maybe (a ,String )
64
80
parse (P f ) s = f s
81
+
65
82
-- | A parser for anything in the Read class,
66
83
-- satisfying
67
84
--
68
85
-- prop> parse readsP s == listToMaybe (reads s)
86
+
69
87
readsP :: Read a => Parser a
70
88
readsP = P $ listToMaybe . reads
89
+
71
90
-------------------
72
91
-- | Parser than can never succeed
73
92
failure :: Parser a -- always fails
74
93
failure = P $ \ s ->
75
94
Nothing
95
+
76
96
-- | Parser that succeeds without looking at the String
77
97
success :: a -> Parser a
78
98
success a = P $ \ s ->
79
99
Just (a,s)
100
+
80
101
-- | Parse any single character
81
102
item = P $ \ s ->
82
103
case s of
83
104
(c: s') -> Just (c,s')
84
105
" " -> Nothing
106
+
107
+
85
108
infixr 3 +++
86
109
-- | Try the first parser and if it fails try the second
87
110
(+++) :: Parser a -> Parser a -> Parser a
88
111
p +++ q = P $ \ s ->
89
112
case parse p s of
90
113
Nothing -> parse q s
91
114
r -> r
115
+
116
+
92
117
-- (p >*> f) parse using p to produce a.
93
118
-- Then parse using f a
119
+
94
120
infixl 1 >*>
121
+
95
122
(>*>) :: Parser a -> (a -> Parser b ) -> Parser b
96
123
p >*> f = P $ \ s ->
97
124
case parse p s of
@@ -100,42 +127,57 @@ p >*> f = P $ \s ->
100
127
-----------------------------------------------
101
128
-- Parsers below do not depend on the internal
102
129
-- representation of Parser
130
+
103
131
-- | parse a single character satisfying property p
104
132
sat :: (Char -> Bool ) -> Parser Char
105
133
sat p = item >*> \ a -> if p a then success a else failure
134
+
106
135
-- | parse a digit character
107
136
digit :: Parser Char
108
137
digit = sat isDigit
138
+
109
139
-- | Parse a specific character
110
140
char c = sat (== c)
141
+
111
142
-- example: parse any lowercase letter
112
143
-- followed by its uppercase equivalent aA or bB etc.
113
144
ex1 = sat isAsciiLower >*> char . toUpper
145
+
114
146
-- pmap modifies the result of a parser
147
+
148
+
115
149
-- | Parse a thing, then parse a list of things, and
116
150
-- return the first thing followed by the list of things
117
151
(<:>) :: Parser a -> Parser [a ] -> Parser [a ]
118
152
p <:> q = p >*> \ a -> fmap (a: ) q
153
+
119
154
-- | Parse zero or more things
120
155
zeroOrMore :: Parser a -> Parser [a ]
121
156
zeroOrMore p = oneOrMore p +++ success []
157
+
122
158
-- | Parse one or more things
123
159
oneOrMore :: Parser a -> Parser [a ]
124
160
oneOrMore p = p <:> zeroOrMore p
161
+
125
162
-- | Parse a list of as, separated by bs
126
163
chain :: Parser a -> Parser b -> Parser [a ]
127
164
chain p q = p <:> zeroOrMore (q *> p)
165
+
128
166
-- example: comma separated digits "1,2,3"
167
+
129
168
-- Standard definition for Functor and Applicative for
130
169
-- GHC>=7.10 compatibility
131
170
instance Functor Parser where
132
171
fmap = liftM
172
+
133
173
instance Applicative Parser where
134
174
pure = success
135
175
(<*>) = ap
176
+
136
177
instance Monad Parser where
137
178
(>>=) = (>*>)
138
179
return = pure
180
+
139
181
instance Alternative Parser where
140
182
empty = failure
141
183
(<|>) = (+++)
0 commit comments