{-# LANGUAGE RankNTypes, GADTs, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, UndecidableInstances, NoMonomorphismRestriction, ImpredicativeTypes #-} module Text.ParserCombinators.UU.Derived where import Text.ParserCombinators.UU.Core pReturn = pure pFail = empty infixl 4 infixl 2 `opt` -- | Optionally recognize parser 'p'. -- -- If 'p' can be recognized, the return value of 'p' is used. Otherwise, -- the value 'v' is used. Note that opt is greedy, if you do not want -- this use @... <|> pure v@ instead. Furthermore, 'p' should not -- recognise the empty string, since this would make your parser ambiguous!! opt :: P st a -> a -> P st a p `opt` v = p <<|> pure v pMaybe :: P st a -> P st (Maybe a) pMaybe p = Just <$> p `opt` Nothing pEither p q = Left <$> p <|> Right <$> q (<$$>) :: (a -> b -> c) -> P st b -> P st (a -> c) f <$$> p = flip f <$> p () :: P st a -> P st (a -> a) -> P st a p q = p <**> (q `opt` id) -- | This can be used to parse 'x' surrounded by 'l' and 'r'. -- -- Example: -- -- > pParens = pPacked pOParen pCParen pPacked :: P st b1 -> P st b2 -> P st a -> P st a pPacked l r x = l *> x <* r -- ======================================================================================= -- ===== Iterating ps =============================================================== -- ======================================================================================= pFoldr :: (a -> a1 -> a1, a1) -> P st a -> P st a1 pFoldr_ng :: (a -> a1 -> a1, a1) -> P st a -> P st a1 pFoldr alg@(op,e) p = pfm where pfm = (op <$> p <*> pfm) `opt` e pFoldr_ng alg@(op,e) p = pfm where pfm = (op <$> p <*> pfm) <|> pure e pFoldr1 :: (v -> b -> b, b) -> P st v -> P st b pFoldr1_ng :: (v -> b -> b, b) -> P st v -> P st b pFoldr1 alg@(op,e) p = op <$> p <*> pFoldr alg p pFoldr1_ng alg@(op,e) p = op <$> p <*> pFoldr_ng alg p pFoldrSep :: (v -> b -> b, b) -> P st a -> P st v -> P st b pFoldrSep_ng :: (v -> b -> b, b) -> P st a -> P st v -> P st b pFoldrSep alg@(op,e) sep p = op <$> p <*> pFoldr alg sepp `opt` e where sepp = sep *> p pFoldrSep_ng alg@(op,e) sep p = op <$> p <*> pFoldr_ng alg sepp <|> pure e where sepp = sep *> p pFoldr1Sep :: (a -> b -> b, b) -> P st a1 ->P st a -> P st b pFoldr1Sep_ng :: (a -> b -> b, b) -> P st a1 ->P st a -> P st b pFoldr1Sep alg@(op,e) sep p = pfm where pfm = op <$> p <*> pFoldr alg (sep *> p) pFoldr1Sep_ng alg@(op,e) sep p = pfm where pfm = op <$> p <*> pFoldr_ng alg (sep *> p) list_alg :: (a -> [a] -> [a], [a1]) list_alg = ((:), []) pList :: P st a -> P st [a] pList_ng :: P st a -> P st [a] pList p = pFoldr list_alg p pList_ng p = pFoldr_ng list_alg p pList1 :: P st a -> P st [a] pList1_ng :: P st a -> P st [a] pList1 p = pFoldr1 list_alg p pList1_ng p = pFoldr1_ng list_alg p pListSep :: P st a1 -> P st a -> P st [a] pListSep_ng :: P st a1 -> P st a -> P st [a] pListSep sep p = pFoldrSep list_alg sep p pListSep_ng sep p = pFoldrSep_ng list_alg sep p pList1Sep :: P st a1 -> P st a -> P st [a] pList1Sep_ng :: P st a1 -> P st a -> P st [a] pList1Sep s p = pFoldr1Sep list_alg s p pList1Sep_ng s p = pFoldr1Sep_ng list_alg s p pChainr :: P st (c -> c -> c) -> P st c -> P st c pChainr_ng :: P st (c -> c -> c) -> P st c -> P st c pChainr op x = r where r = x (flip <$> op <*> r) pChainr_ng op x = r where r = x <**> ((flip <$> op <*> r) <|> pure id) pChainl :: P st (c -> c -> c) -> P st c -> P st c pChainl_ng :: P st (c -> c -> c) -> P st c -> P st c pChainl op x = f <$> x <*> pList (flip <$> op <*> x) where f x [] = x f x (func:rest) = f (func x) rest pChainl_ng op x = f <$> x <*> pList_ng (flip <$> op <*> x) where f x [] = x f x (func:rest) = f (func x) rest -- | Parses using any of the parsers in the list 'l'. pAny :: (a -> P st a1) -> [a] -> P st a1 pAny f l = foldr (<|>) pFail (map f l) -- | Parses any of the symbols in 'l'. pAnySym :: Provides st s s => [s] -> P st s pAnySym = pAny pSym pToken :: Provides st s s => [s] -> P st [s] pToken [] = pure [] pToken (a:as) = (:) <$> pSym a <*> pToken as pAnyToken :: Provides st s s => [[s]] -> P st [s] pAnyToken = pAny pToken