MonadFail proposal, phase 1
[ghc.git] / libraries / base / Text / ParserCombinators / ReadPrec.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE NoImplicitPrelude #-}
3 {-# LANGUAGE CPP #-}
4
5 -----------------------------------------------------------------------------
6 -- |
7 -- Module : Text.ParserCombinators.ReadPrec
8 -- Copyright : (c) The University of Glasgow 2002
9 -- License : BSD-style (see the file libraries/base/LICENSE)
10 --
11 -- Maintainer : libraries@haskell.org
12 -- Stability : provisional
13 -- Portability : non-portable (uses Text.ParserCombinators.ReadP)
14 --
15 -- This library defines parser combinators for precedence parsing.
16
17 -----------------------------------------------------------------------------
18
19 module Text.ParserCombinators.ReadPrec
20 (
21 ReadPrec,
22
23 -- * Precedences
24 Prec,
25 minPrec,
26
27 -- * Precedence operations
28 lift,
29 prec,
30 step,
31 reset,
32
33 -- * Other operations
34 -- | All are based directly on their similarly-named 'ReadP' counterparts.
35 get,
36 look,
37 (+++),
38 (<++),
39 pfail,
40 choice,
41
42 -- * Converters
43 readPrec_to_P,
44 readP_to_Prec,
45 readPrec_to_S,
46 readS_to_Prec,
47 )
48 where
49
50
51 import Text.ParserCombinators.ReadP
52 ( ReadP
53 , ReadS
54 , readP_to_S
55 , readS_to_P
56 )
57
58 import qualified Text.ParserCombinators.ReadP as ReadP
59 ( get
60 , look
61 , (+++), (<++)
62 , pfail
63 )
64
65 import GHC.Num( Num(..) )
66 import GHC.Base
67
68 #if __GLASGOW_HASKELL__ > 710
69 import qualified Control.Monad.Fail as MonadFail
70 #endif
71
72 -- ---------------------------------------------------------------------------
73 -- The readPrec type
74
75 newtype ReadPrec a = P (Prec -> ReadP a)
76
77 -- Functor, Monad, MonadPlus
78
79 instance Functor ReadPrec where
80 fmap h (P f) = P (\n -> fmap h (f n))
81
82 instance Applicative ReadPrec where
83 pure x = P (\_ -> pure x)
84 (<*>) = ap
85
86 instance Monad ReadPrec where
87 fail s = P (\_ -> fail s)
88 P f >>= k = P (\n -> do a <- f n; let P f' = k a in f' n)
89
90 #if __GLASGOW_HASKELL__ > 710
91 instance MonadFail.MonadFail ReadPrec where
92 fail s = P (\_ -> fail s)
93 #endif
94
95 instance MonadPlus ReadPrec where
96 mzero = pfail
97 mplus = (+++)
98
99 instance Alternative ReadPrec where
100 empty = mzero
101 (<|>) = mplus
102
103 -- precedences
104 type Prec = Int
105
106 minPrec :: Prec
107 minPrec = 0
108
109 -- ---------------------------------------------------------------------------
110 -- Operations over ReadPrec
111
112 lift :: ReadP a -> ReadPrec a
113 -- ^ Lift a precedence-insensitive 'ReadP' to a 'ReadPrec'.
114 lift m = P (\_ -> m)
115
116 step :: ReadPrec a -> ReadPrec a
117 -- ^ Increases the precedence context by one.
118 step (P f) = P (\n -> f (n+1))
119
120 reset :: ReadPrec a -> ReadPrec a
121 -- ^ Resets the precedence context to zero.
122 reset (P f) = P (\_ -> f minPrec)
123
124 prec :: Prec -> ReadPrec a -> ReadPrec a
125 -- ^ @(prec n p)@ checks whether the precedence context is
126 -- less than or equal to @n@, and
127 --
128 -- * if not, fails
129 --
130 -- * if so, parses @p@ in context @n@.
131 prec n (P f) = P (\c -> if c <= n then f n else ReadP.pfail)
132
133 -- ---------------------------------------------------------------------------
134 -- Derived operations
135
136 get :: ReadPrec Char
137 -- ^ Consumes and returns the next character.
138 -- Fails if there is no input left.
139 get = lift ReadP.get
140
141 look :: ReadPrec String
142 -- ^ Look-ahead: returns the part of the input that is left, without
143 -- consuming it.
144 look = lift ReadP.look
145
146 (+++) :: ReadPrec a -> ReadPrec a -> ReadPrec a
147 -- ^ Symmetric choice.
148 P f1 +++ P f2 = P (\n -> f1 n ReadP.+++ f2 n)
149
150 (<++) :: ReadPrec a -> ReadPrec a -> ReadPrec a
151 -- ^ Local, exclusive, left-biased choice: If left parser
152 -- locally produces any result at all, then right parser is
153 -- not used.
154 P f1 <++ P f2 = P (\n -> f1 n ReadP.<++ f2 n)
155
156 pfail :: ReadPrec a
157 -- ^ Always fails.
158 pfail = lift ReadP.pfail
159
160 choice :: [ReadPrec a] -> ReadPrec a
161 -- ^ Combines all parsers in the specified list.
162 choice ps = foldr (+++) pfail ps
163
164 -- ---------------------------------------------------------------------------
165 -- Converting between ReadPrec and Read
166
167 readPrec_to_P :: ReadPrec a -> (Int -> ReadP a)
168 readPrec_to_P (P f) = f
169
170 readP_to_Prec :: (Int -> ReadP a) -> ReadPrec a
171 readP_to_Prec f = P f
172
173 readPrec_to_S :: ReadPrec a -> (Int -> ReadS a)
174 readPrec_to_S (P f) n = readP_to_S (f n)
175
176 readS_to_Prec :: (Int -> ReadS a) -> ReadPrec a
177 readS_to_Prec f = P (\n -> readS_to_P (f n))
178