syntax-0.3.0.0: Data/Syntax.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{- |
Module : Data.Syntax
Description : Abstract syntax description.
Copyright : (c) Paweł Nowak
License : MIT
Maintainer : Paweł Nowak <pawel834@gmail.com>
Stability : experimental
Abstract syntax descriptions based on semi-isomorphisms.
-}
module Data.Syntax (
-- * Syntax.
Syntax(..),
-- * Common isomorphisms.
packed
) where
import Prelude hiding (take, takeWhile)
import Control.Lens.Iso
import Control.Lens.SemiIso
import Data.MonoTraversable
import Data.SemiIsoFunctor
import Data.Sequences hiding (take, takeWhile)
-- | An isomorphism between a sequence and a list of its elements.
packed :: IsSequence seq => Iso' seq [Element seq]
packed = iso otoList fromList
-- | An abstract syntax description based on semi-isomorphisms.
--
-- This class can be implemented by both parsers and printers (and maybe more?).
--
-- The usual use is to write a polymorphic syntax description and instantiate it
-- both as a parser and a printer. An example is available in the 'syntax-example'
-- package.
--
-- Methods of this class try to mimic "Data.Attoparsec.Text" interface.
class ( SemiIsoAlternative syn
, SemiIsoMonad syn
, IsSequence seq
, Eq seq
, Eq (Element seq))
=> Syntax syn seq | syn -> seq
where
-- | Any character.
anyChar :: syn (Element seq)
-- | A specific character.
char :: Element seq -> syn ()
char c = rev (exact c) /$/ anyChar
-- | Any character except the given one.
notChar :: Element seq -> syn (Element seq)
notChar c = bifiltered (/= c) /$/ anyChar
-- | Any character satisfying a predicate.
satisfy :: (Element seq -> Bool) -> syn (Element seq)
satisfy p = bifiltered p /$/ anyChar
-- | Transforms a character using a SemiIso and filters out values
-- not satisfying the predicate.
satisfyWith :: ASemiIso' a (Element seq) -> (a -> Bool) -> syn a
satisfyWith ai p = bifiltered p . ai /$/ anyChar
-- | A specific string.
string :: seq -> syn ()
string s = rev (exact s) /$/ take (olength s)
-- | A string of length @n@.
take :: Int -> syn seq
take n = packed /$/ sireplicate n anyChar
-- | Maximal string which elements satisfy a predicate.
takeWhile :: (Element seq -> Bool) -> syn seq
takeWhile p = packed /$/ simany (satisfy p)
-- | Maximal non-empty string which elements satisfy a predicate.
takeWhile1 :: (Element seq -> Bool) -> syn seq
takeWhile1 p = packed /$/ sisome (satisfy p)
-- | Maximal string which elements do not satisfy a predicate.
takeTill :: (Element seq -> Bool) -> syn seq
takeTill p = takeWhile (not . p)
-- | Maximal non-empty string which elements do not satisfy a predicate.
takeTill1 :: (Element seq -> Bool) -> syn seq
takeTill1 p = takeWhile1 (not . p)
{-# MINIMAL anyChar #-}