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