1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 module Parsers.Utils.Attoparsec where
4 import Control.Applicative hiding (some)
5 import Control.Monad (Monad(..), MonadPlus)
6 import Data.Attoparsec.Combinator
7 import Data.Bool (Bool(..))
8 import Data.Char (Char)
9 import Data.Either (Either(..))
10 import Data.Eq (Eq(..))
11 import Data.Function (flip, ($), id)
12 import Data.Functor (void)
13 import Data.Maybe (Maybe(..), maybe)
14 import Data.String (String)
15 import Data.Word (Word8)
16 import qualified Data.List as List
17 import qualified Data.Text as T
18 import qualified Data.ByteString as BS
19 import qualified Data.Attoparsec.Internal.Types as AP
20 import qualified Data.Attoparsec.ByteString as AP.ByteString
21 import qualified Data.Attoparsec.ByteString.Char8 as AP.ByteString.Char8
22 import qualified Data.Attoparsec.Text as AP.Text
24 -- * Class 'Inputable'
25 class AP.Chunk inp => Inputable inp where
29 uncons :: inp -> Maybe (Token inp, inp)
30 satisfy :: (Token inp -> Bool) -> AP.Parser inp (Token inp)
31 char :: Char -> AP.Parser inp Char
32 notInClass :: String -> Token inp -> Bool
33 instance Inputable T.Text where
34 type Token T.Text = Char
38 satisfy = AP.Text.satisfy
40 notInClass = AP.Text.notInClass
41 instance Inputable BS.ByteString where
42 type Token BS.ByteString = Word8
46 satisfy = AP.ByteString.satisfy
47 char = AP.ByteString.Char8.char
48 notInClass = AP.ByteString.notInClass
50 between :: Applicative f => f a -> f b -> f c -> f c
51 between o c p = o *> p <* c
53 match :: (Monad m, Eq a) => [a] -> m a -> (a -> m b) -> m b -> m b
54 match xs p f def = p >>= (\x -> if List.elem x xs then f x else def)
56 skipSome :: Alternative p => p a -> p ()
57 skipSome p = void (some p)
59 some :: Alternative p => p a -> p [a]
62 maybeP :: Alternative p => p a -> p (Maybe a)
63 maybeP p = option Nothing (Just <$> p)
65 fromMaybeP :: Monad m => m (Maybe a) -> m a -> m a
66 fromMaybeP mmx d = mmx >>= maybe d return
68 (<+>) :: Alternative p => p a -> p b -> p (Either a b)
69 p <+> q = Left <$> p <|> Right <$> q
71 (<:>) :: Applicative p => p a -> p [a] -> p [a]
74 (<~>) :: Applicative p => p a -> p b -> p (a, b)
77 pfoldl1 :: Alternative p => (b -> a -> b) -> b -> p a -> p b
78 pfoldl1 f k p = List.foldl' f k <$> some p
80 (>?>) :: MonadPlus m => m a -> (a -> Bool) -> m a
81 m >?> f = m >>= \x -> if f x then return x else Control.Applicative.empty
83 chainPre :: Alternative p => p (a -> a) -> p a -> p a
84 chainPre op p = flip (List.foldr ($)) <$> many op <*> p
86 chainPost :: Alternative p => p a -> p (a -> a) -> p a
87 chainPost p op = List.foldl' (flip ($)) <$> p <*> many op
89 chainl1 :: Alternative p => p a -> p (a -> a -> a) -> p a
90 chainl1 p op = chainPost p (flip <$> op <*> p)
92 chainr1 :: Alternative p => p a -> p (a -> a -> a) -> p a
93 chainr1 p op = let go = p <**> ((flip <$> op <*> go) <|> pure id) in go
96 = InfixL [p (a -> a -> a)]
97 | InfixR [p (a -> a -> a)]
99 | Postfix [p (a -> a)]
101 precedence :: Alternative p => [Level p s a] -> p a -> p a
102 precedence levels atom = List.foldl' convert atom levels
104 convert x (InfixL ops) = chainl1 x (choice ops)
105 convert x (InfixR ops) = chainr1 x (choice ops)
106 convert x (Prefix ops) = chainPre (choice ops) x
107 convert x (Postfix ops) = chainPost x (choice ops)