1 {-# LANGUAGE DefaultSignatures #-}
2 {-# LANGUAGE PatternSynonyms #-}
3 {-# LANGUAGE TemplateHaskell #-}
4 module Symantic.Parser.Grammar.Combinators where
5 import Data.Function ((.), flip, const)
6 import Data.Bool (Bool(..), not, (||))
7 import Data.Char (Char)
8 import Data.Either (Either(..))
9 import Data.Eq (Eq(..))
11 import Data.Kind (Type)
12 import Data.Maybe (Maybe(..))
13 import Data.String (String)
14 import Language.Haskell.TH (TExpQ)
15 import qualified Data.Functor as F
16 import qualified Prelude as Pre
17 import qualified Data.List as List
19 import Symantic.Base.Univariant
20 import qualified Symantic.Parser.Staging as S
22 -- * Class 'Applicable'
23 class Applicable repr where
24 (<$>) :: S.Runtime (a -> b) -> repr a -> repr b
25 (<$>) f = (pure f <*>)
27 (<&>) :: repr a -> S.Runtime (a -> b) -> repr b
30 (<$) :: S.Runtime a -> repr b -> repr a
33 ($>) :: repr a -> S.Runtime b -> repr b
36 --type Pure repr :: Type -> Type
37 pure :: S.Runtime a -> repr a
39 Liftable repr => Applicable (Unlift repr) =>
43 (<*>) :: repr (a -> b) -> repr a -> repr b
45 Liftable repr => Applicable (Unlift repr) =>
46 repr (a -> b) -> repr a -> repr b
49 liftA2 :: S.Runtime (a -> b -> c) -> repr a -> repr b -> repr c
50 liftA2 f x = (<*>) (f <$> x)
52 (*>) :: repr a -> repr b -> repr b
53 x *> y = (S.id <$ x) <*> y
55 (<*) :: repr a -> repr b -> repr a
59 (<**>) :: repr a -> repr (a -> b) -> repr b
60 (<**>) = liftA2 (\a f -> f a)
62 infixl 4 <$>, <&>, <$, $>, <*>, <*, *>
65 (<**>) :: Applicable repr => repr a -> repr (a -> b) -> repr b
66 (<**>) = liftA2 (S.flip S..@ (S.$))
68 -- * Class 'Alternable'
69 class Alternable repr where
70 (<|>) :: repr a -> repr a -> repr a
72 try :: repr a -> repr a
74 Liftable repr => Alternable (Unlift repr) =>
75 repr a -> repr a -> repr a
77 Liftable repr => Alternable (Unlift repr) =>
80 Liftable repr => Alternable (Unlift repr) =>
88 (<+>) :: Applicable repr => Alternable repr => repr a -> repr b -> repr (Either a b)
89 p <+> q = S.Runtime (S.Eval Left) (S.Code [||Left||]) <$> p <|>
90 S.Runtime (S.Eval Right) (S.Code [||Right||]) <$> q
92 optionally :: Applicable repr => Alternable repr => repr a -> S.Runtime b -> repr b
93 optionally p x = p $> x <|> pure x
95 optional :: Applicable repr => Alternable repr => repr a -> repr ()
96 optional = flip optionally S.unit
98 option :: Applicable repr => Alternable repr => S.Runtime a -> repr a -> repr a
99 option x p = p <|> pure x
101 choice :: Alternable repr => [repr a] -> repr a
102 choice = List.foldr (<|>) empty
104 maybeP :: Applicable repr => Alternable repr => repr a -> repr (Maybe a)
105 maybeP p = option (S.Runtime (S.Eval Nothing) (S.Code [||Nothing||]))
106 (S.Runtime (S.Eval Just) (S.Code [||Just||]) <$> p)
108 manyTill :: Applicable repr => Alternable repr => repr a -> repr b -> repr [a]
109 manyTill p end = let go = end $> S.nil <|> p <:> go in go
111 -- * Class 'Selectable'
112 class Selectable repr where
113 branch :: repr (Either a b) -> repr (a -> c) -> repr (b -> c) -> repr c
115 Liftable repr => Selectable (Unlift repr) =>
116 repr (Either a b) -> repr (a -> c) -> repr (b -> c) -> repr c
117 branch = lift3 branch
119 class Matchable repr where
121 Eq a => [S.Runtime (a -> Bool)] -> [repr b] -> repr a -> repr b -> repr b
122 default conditional ::
123 Unliftable repr => Liftable repr => Matchable (Unlift repr) =>
124 Eq a => [S.Runtime (a -> Bool)] -> [repr b] -> repr a -> repr b -> repr b
125 conditional cs bs = lift2 (conditional cs (unlift Pre.<$> bs))
127 match :: Eq a => [S.Runtime a] -> repr a -> (S.Runtime a -> repr b) -> repr b -> repr b
128 match as a a2b b = conditional (S.eq Pre.<$> as) (a2b Pre.<$> as) a b
130 -- * Class 'Foldable'
131 class Foldable repr where
132 chainPre :: repr (a -> a) -> repr a -> repr a
133 chainPost :: repr a -> repr (a -> a) -> repr a
135 Liftable repr => Foldable (Unlift repr) =>
136 repr (a -> a) -> repr a -> repr a
138 Liftable repr => Foldable (Unlift repr) =>
139 repr a -> repr (a -> a) -> repr a
140 chainPre = lift2 chainPre
141 chainPost = lift2 chainPost
144 conditional :: Selectable repr => [(S.Runtime (a -> Bool), repr b)] -> repr a -> repr b -> repr b
145 conditional cs p def = match p fs qs def
146 where (fs, qs) = List.unzip cs
149 -- * Class 'Charable'
150 class Charable repr where
151 satisfy :: S.Runtime (Char -> Bool) -> repr Char
153 Liftable repr => Charable (Unlift repr) =>
154 S.Runtime (Char -> Bool) -> repr Char
155 satisfy = lift . satisfy
157 -- * Class 'Lookable'
158 class Lookable repr where
159 look :: repr a -> repr a
160 negLook :: repr a -> repr ()
161 default look :: Liftable repr => Lookable (Unlift repr) => repr a -> repr a
162 default negLook :: Liftable repr => Lookable (Unlift repr) => repr a -> repr ()
164 negLook = lift1 negLook
168 (<:>) :: Applicable repr => repr a -> repr [a] -> repr [a]
169 (<:>) = liftA2 S.cons
171 sequence :: Applicable repr => [repr a] -> repr [a]
172 sequence = List.foldr (<:>) (pure S.nil)
174 traverse :: Applicable repr => (a -> repr b) -> [a] -> repr [b]
175 traverse f = sequence . List.map f
177 repeat :: Applicable repr => Int -> repr a -> repr [a]
178 repeat n p = traverse (const p) [1..n]
180 between :: Applicable repr => repr o -> repr c -> repr a -> repr a
181 between open close p = open *> p <* close
183 string :: Applicable repr => Charable repr => String -> repr String
184 string = traverse char
186 -- oneOf :: [Char] -> repr Char
187 -- oneOf cs = satisfy (makeQ (flip elem cs) [||\c -> $$(ofChars cs [||c||])||])
189 noneOf :: Charable repr => [Char] -> repr Char
190 noneOf cs = satisfy ((S.Runtime (S.Eval (not . flip List.elem cs)) (S.Code [||\c -> not $$(ofChars cs [||c||])||])))
192 ofChars :: [Char] -> TExpQ Char -> TExpQ Bool
193 ofChars = List.foldr (\c rest qc -> [|| c == $$qc || $$(rest qc) ||]) (const [||False||])
195 token :: Applicable repr => Alternable repr => Charable repr => String -> repr String
198 eof :: Charable repr => Lookable repr => repr ()
201 more :: Applicable repr => Charable repr => Lookable repr => repr ()
202 more = look (void item)
204 char :: Applicable repr => Charable repr => Char -> repr Char
205 char c = satisfy (S.eq (S.char c)) $> S.char c
207 item :: Charable repr => repr Char
208 item = satisfy (S.const S..@ S.bool True)
210 -- Composite Combinators
211 -- someTill :: repr a -> repr b -> repr [a]
212 -- someTill p end = negLook end *> (p <:> manyTill p end)
214 void :: Applicable repr => repr a -> repr ()
217 unit :: Applicable repr => repr ()
222 constp :: Applicable repr => repr a -> repr (b -> a)
223 constp = (S.const <$>)
228 (>>) :: Applicable repr => repr a -> repr b -> repr b
231 -- Monoidal Operations
234 (<~>) :: Applicable repr => repr a -> repr b -> repr (a, b)
235 (<~>) = liftA2 (S.runtime (,))
238 (<~) :: Applicable repr => repr a -> repr b -> repr a
242 (~>) :: Applicable repr => repr a -> repr b -> repr b
248 S.Runtime (a -> b -> c) -> repr a -> repr b -> repr c
249 liftA2 f x = (<*>) (fmap f x)
253 S.Runtime (a -> b -> c -> d) -> repr a -> repr b -> repr c -> repr d
254 liftA3 f a b c = liftA2 f a b <*> c
260 Applicable repr => Foldable repr =>
261 S.Runtime (a -> b -> b) -> S.Runtime b -> repr a -> repr b
262 pfoldr f k p = chainPre (f <$> p) (pure k)
265 Applicable repr => Foldable repr =>
266 S.Runtime (a -> b -> b) -> S.Runtime b -> repr a -> repr b
267 pfoldr1 f k p = f <$> p <*> pfoldr f k p
270 Applicable repr => Foldable repr =>
271 S.Runtime (b -> a -> b) -> S.Runtime b -> repr a -> repr b
272 pfoldl f k p = chainPost (pure k) ((S.flip <$> pure f) <*> p)
275 Applicable repr => Foldable repr =>
276 S.Runtime (b -> a -> b) -> S.Runtime b -> repr a -> repr b
277 pfoldl1 f k p = chainPost (f <$> pure k <*> p) ((S.flip <$> pure f) <*> p)
281 Applicable repr => Foldable repr =>
282 S.Runtime (a -> b) -> repr a -> repr (b -> a -> b) -> repr b
283 chainl1' f p op = chainPost (f <$> p) (S.flip <$> op <*> p)
286 Applicable repr => Foldable repr =>
287 repr a -> repr (a -> a -> a) -> repr a
288 chainl1 = chainl1' S.id
291 chainr1' :: ParserOps rep => rep (a -> b) -> repr a -> repr (a -> b -> b) -> repr b
292 chainr1' f p op = newRegister_ S.id $ \acc ->
293 let go = bind p $ \x ->
294 modify acc (S.flip (S..@) <$> (op <*> x)) *> go
298 chainr1 :: repr a -> repr (a -> a -> a) -> repr a
299 chainr1 = chainr1' S.id
301 chainr :: repr a -> repr (a -> a -> a) -> S.Runtime a -> repr a
302 chainr p op x = option x (chainr1 p op)
306 Applicable repr => Alternable repr => Foldable repr =>
307 repr a -> repr (a -> a -> a) -> S.Runtime a -> repr a
308 chainl p op x = option x (chainl1 p op)
310 -- Derived Combinators
312 Applicable repr => Foldable repr =>
314 many = pfoldr S.cons S.nil
317 Applicable repr => Foldable repr =>
318 Int -> repr a -> repr [a]
319 manyN n p = List.foldr (const (p <:>)) (many p) [1..n]
322 Applicable repr => Foldable repr =>
327 Applicable repr => Foldable repr =>
329 --skipMany p = let skipManyp = p *> skipManyp <|> unit in skipManyp
330 skipMany = void . pfoldl S.const S.unit -- the void here will encourage the optimiser to recognise that the register is unused
333 Applicable repr => Foldable repr =>
334 Int -> repr a -> repr ()
335 skipManyN n p = List.foldr (const (p *>)) (skipMany p) [1..n]
338 Applicable repr => Foldable repr =>
340 skipSome = skipManyN 1
343 Applicable repr => Alternable repr => Foldable repr =>
344 repr a -> repr b -> repr [a]
345 sepBy p sep = option S.nil (sepBy1 p sep)
348 Applicable repr => Alternable repr => Foldable repr =>
349 repr a -> repr b -> repr [a]
350 sepBy1 p sep = p <:> many (sep *> p)
353 Applicable repr => Alternable repr => Foldable repr =>
354 repr a -> repr b -> repr [a]
355 endBy p sep = many (p <* sep)
358 Applicable repr => Alternable repr => Foldable repr =>
359 repr a -> repr b -> repr [a]
360 endBy1 p sep = some (p <* sep)
363 Applicable repr => Alternable repr => Foldable repr =>
364 repr a -> repr b -> repr [a]
365 sepEndBy p sep = option S.nil (sepEndBy1 p sep)
368 Applicable repr => Alternable repr => Foldable repr =>
369 repr a -> repr b -> repr [a]
371 let seb1 = p <**> (sep *> (S.flip S..@ S.cons <$> option S.nil seb1)
372 <|> pure (S.flip S..@ S.cons S..@ S.nil))
376 sepEndBy1 :: repr a -> repr b -> repr [a]
377 sepEndBy1 p sep = newRegister_ S.id $ \acc ->
378 let go = modify acc ((S.flip (S..)) S..@ S.cons <$> p)
379 *> (sep *> (go <|> get acc) <|> get acc)