22Module : Parsing
33Description : Simple Monadic Parsing Library
44Maintainer : Thomas Hallgren
5+
56A Simple Monadic Parsing Library
7+
68Used in the course Functional Programming GU/Chalmers.
7- Original author: David Sands.
89
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.
2811-}
12+
2913module Parsing
3014 ( -- * The Parser type
3115 Parser -- exports the type name but not the constructors
@@ -47,51 +31,94 @@ module Parsing
4731 ,(*>)
4832 -- ** Return a result without consuming any input
4933 , 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+ ----------------------}
5161where
62+
5263import Data.Char
5364import Data.Maybe (listToMaybe )
5465-- boilerplate for GHC 10.7 compatibility:
5566import Control.Applicative (Applicative (.. ),Alternative (.. ))
5667import Control.Monad (liftM , ap )
68+
5769------------------
5870
71+
72+
73+
5974-- | The abstract data type representing a Parser
6075newtype Parser a = P (String -> Maybe (a ,String ))
76+
6177-- | Runs the parser on the given string
6278-- to return maybe a thing and a string
6379parse :: Parser a -> String -> Maybe (a ,String )
6480parse (P f ) s = f s
81+
6582-- | A parser for anything in the Read class,
6683-- satisfying
6784--
6885-- prop> parse readsP s == listToMaybe (reads s)
86+
6987readsP :: Read a => Parser a
7088readsP = P $ listToMaybe . reads
89+
7190-------------------
7291-- | Parser than can never succeed
7392failure :: Parser a -- always fails
7493failure = P $ \ s ->
7594 Nothing
95+
7696-- | Parser that succeeds without looking at the String
7797success :: a -> Parser a
7898success a = P $ \ s ->
7999 Just (a,s)
100+
80101-- | Parse any single character
81102item = P $ \ s ->
82103 case s of
83104 (c: s') -> Just (c,s')
84105 " " -> Nothing
106+
107+
85108infixr 3 +++
86109-- | Try the first parser and if it fails try the second
87110(+++) :: Parser a -> Parser a -> Parser a
88111p +++ q = P $ \ s ->
89112 case parse p s of
90113 Nothing -> parse q s
91114 r -> r
115+
116+
92117-- (p >*> f) parse using p to produce a.
93118-- Then parse using f a
119+
94120infixl 1 >*>
121+
95122(>*>) :: Parser a -> (a -> Parser b ) -> Parser b
96123p >*> f = P $ \ s ->
97124 case parse p s of
@@ -100,42 +127,57 @@ p >*> f = P $ \s ->
100127-----------------------------------------------
101128-- Parsers below do not depend on the internal
102129-- representation of Parser
130+
103131-- | parse a single character satisfying property p
104132sat :: (Char -> Bool ) -> Parser Char
105133sat p = item >*> \ a -> if p a then success a else failure
134+
106135-- | parse a digit character
107136digit :: Parser Char
108137digit = sat isDigit
138+
109139-- | Parse a specific character
110140char c = sat (== c)
141+
111142-- example: parse any lowercase letter
112143-- followed by its uppercase equivalent aA or bB etc.
113144ex1 = sat isAsciiLower >*> char . toUpper
145+
114146-- pmap modifies the result of a parser
147+
148+
115149-- | Parse a thing, then parse a list of things, and
116150-- return the first thing followed by the list of things
117151(<:>) :: Parser a -> Parser [a ] -> Parser [a ]
118152p <:> q = p >*> \ a -> fmap (a: ) q
153+
119154-- | Parse zero or more things
120155zeroOrMore :: Parser a -> Parser [a ]
121156zeroOrMore p = oneOrMore p +++ success []
157+
122158-- | Parse one or more things
123159oneOrMore :: Parser a -> Parser [a ]
124160oneOrMore p = p <:> zeroOrMore p
161+
125162-- | Parse a list of as, separated by bs
126163chain :: Parser a -> Parser b -> Parser [a ]
127164chain p q = p <:> zeroOrMore (q *> p)
165+
128166-- example: comma separated digits "1,2,3"
167+
129168-- Standard definition for Functor and Applicative for
130169-- GHC>=7.10 compatibility
131170instance Functor Parser where
132171 fmap = liftM
172+
133173instance Applicative Parser where
134174 pure = success
135175 (<*>) = ap
176+
136177instance Monad Parser where
137178 (>>=) = (>*>)
138179 return = pure
180+
139181instance Alternative Parser where
140182 empty = failure
141183 (<|>) = (+++)
0 commit comments