packages feed

parsley-1.0.0.1: benchmarks/Shared/Attoparsec/Extended.hs

module Shared.Attoparsec.Extended (
    module Data.Functor,
    module Control.Applicative,
    module Data.Attoparsec.Text,
    module Control.Monad,
    module Shared.Attoparsec.Extended
  ) where

import Data.Attoparsec.Text hiding (match, string)
import Data.Functor (void, ($>))
import Control.Monad (MonadPlus)
import Control.Applicative (liftA2, liftA3, empty, Alternative, (<**>), (<|>), many)
import Data.List (foldl')

string = traverse char

token :: String -> Parser String
token = try . string

between o c p = o *> p <* c

oneOf = satisfy . inClass
noneOf = satisfy . notInClass

match :: (Monad m, Eq a) => [a] -> m a -> (a -> m b) -> m b -> m b
match xs p f def = p >>= (\x -> if elem x xs then f x else def)

skipSome :: Parser a -> Parser ()
skipSome p = void (some p)

some = many1

maybeP :: Parser a -> Parser (Maybe a)
maybeP p = option Nothing (Just <$> p)

fromMaybeP :: Monad m => m (Maybe a) -> m a -> m a
fromMaybeP mmx d = mmx >>= maybe d return

(<+>) :: Parser a -> Parser b -> Parser (Either a b)
p <+> q = Left <$> p <|> Right <$> q

(<:>) :: Parser a -> Parser [a] -> Parser [a]
(<:>) = liftA2 (:)

(<~>) :: Parser a -> Parser b -> Parser (a, b)
(<~>) = liftA2 (,)

pfoldl1 :: (b -> a -> b) -> b -> Parser a -> Parser b
pfoldl1 f k p = foldl' f k <$> some p

(>?>) :: MonadPlus m => m a -> (a -> Bool) -> m a
m >?> f = m >>= \x -> if f x then return x else empty

chainPre :: Parser (a -> a) -> Parser a -> Parser a
chainPre op p = flip (foldr ($)) <$> many op <*> p

chainPost :: Parser a -> Parser (a -> a) -> Parser a
chainPost p op = foldl' (flip ($)) <$> p <*> many op

chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a
chainl1 p op = chainPost p (flip <$> op <*> p)

chainr1 :: Parser a -> Parser (a -> a -> a) -> Parser a
chainr1 p op = let go = p <**> ((flip <$> op <*> go) <|> pure id) in go

data Level s a = InfixL  [Parser (a -> a -> a)]
               | InfixR  [Parser (a -> a -> a)]
               | Prefix  [Parser (a -> a)]
               | Postfix [Parser (a -> a)]

precedence :: [Level s a] -> Parser a -> Parser a
precedence levels atom = foldl' convert atom levels
  where
    convert x (InfixL ops)  = chainl1 x (choice ops)
    convert x (InfixR ops)  = chainr1 x (choice ops)
    convert x (Prefix ops)  = chainPre (choice ops) x
    convert x (Postfix ops) = chainPost x (choice ops)