{- | Module : Data.Syntax.Combinator Description : Combinators that work with any sequence type. Copyright : (c) Daan Leijen 1999-2001, Bryan O'Sullivan 2007-2014, Paweł Nowak 2014 License : MIT Maintainer : Paweł Nowak Stability : experimental Combinators that work with any sequence type. -} module Data.Syntax.Combinator where import Control.Lens import Control.Lens.SemiIso import Data.SemiIsoFunctor -- | One or zero occurences of @f@. optional :: SemiIsoAlternative f => f a -> f (Maybe a) optional f = _Just /$/ f /|/ sipure _Nothing -- | Like 'optional', but specialized for @()@. opt :: SemiIsoAlternative f => f () -> f () opt f = f /|/ sipure id -- | Parser one or zero occurences of @f@, but prints nothing. opt_ :: SemiIsoAlternative f => f () -> f () opt_ f = semiIso (const (Left "opt_")) Right /$/ f /|/ sipure id -- | @manyTill p end@ applies action p zero or more times until action -- end succeeds, and returns the list of values returned by p. manyTill :: SemiIsoAlternative f => f a -> f () -> f [a] manyTill p end = _Empty /$/ end /|/ _Cons /$/ p /*/ manyTill p end -- | Zero or more occurences of @v@ separated by @s@. sepBy :: SemiIsoAlternative f => f a -> f () -> f [a] sepBy v s = sepBy1 v s /|/ sipure _Empty -- | One or more occurences of @v@ separated by @s@. sepBy1 :: SemiIsoAlternative f => f a -> f () -> f [a] sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /|/ sipure _Empty) -- | Tries to apply the actions in the list in order, until one of -- them succeeds. Returns the value of the succeeding action. choice :: SemiIsoAlternative f => [f a] -> f a choice = foldr (/|/) (sifail "choice: all alternatives failed") -- | Combine two alternatives. eitherOf :: SemiIsoAlternative f => f a -> f b -> f (Either a b) eitherOf a b = _Left /$/ a /|/ _Right /$/ b