-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A combinator library for simultaneously defining parsers and pretty printers.
--   
--   Combinator library for defining both type safe parsers and pretty
--   printers simultaneously. This library performs well in practice
--   because parsers and printers are implemented in CPS and because
--   arguments are always curried, rather than packed into nested tuples.
@package cassette
@version 0.1.0

module Text.Cassette.Prim

-- | A cassette consists of two tracks, represented by functions. The
--   functions on each track are not necessarily inverses of each other,
--   and do not necessarily connect the same start and end types.
data K7 a b c d
K7 :: (a -> b) -> (d -> c) -> K7 a b c d
[sideA] :: K7 a b c d -> a -> b
[sideB] :: K7 a b c d -> d -> c

-- | Symmetric cassettes do have functions that are inverses of each other
--   on each track. Symmetric cassettes form a category under splicing (see
--   '(&lt;&gt;)').
newtype Sym a b
Sym :: K7 a b a b -> Sym a b
[unSym] :: Sym a b -> K7 a b a b

-- | The type of string transformers in CPS, <i>i.e.</i> functions from
--   strings to strings.
type C r = (String -> r) -> String -> r

-- | The type of cassettes with a string transformer on each side. The
--   A-side produces a value in addition to transforming the string,
--   <i>i.e.</i> it is a parser. The B-side consumes a value to transform
--   the string, <i>i.e.</i> it is a printer.
type PP a = forall r r'. K7 (C (a -> r)) (C r) (C (a -> r')) (C r')
type PP0 = forall r r'. K7 (C r) (C r) (C r') (C r')

-- | Tape splicing operator. Functions on each track are composed pairwise.
(<>) :: K7 b c b' c' -> K7 a b a' b' -> K7 a c a' c'
infixr 9 <>

-- | A synonym to '(&lt;&gt;)' with its arguments flipped and with lower
--   precedence.
(-->) :: () => K7 a b a' b' -> K7 b c b' c' -> K7 a c a' c'
infixr 8 -->

-- | Choice operator. If the first cassette fails, then try the second
--   parser. Note that this is an unrestricted backtracking operator: it
--   never commits to any particular choice.
(<|>) :: PP a -> PP a -> PP a
infixr 1 <|>

-- | Select the A-side.
play :: K7 a b c d -> a -> b

-- | Switch the A-side and B-side around.
flip :: K7 a b c d -> K7 d c b a

-- | Extract the parser from a cassette.
parse :: PP a -> String -> Maybe a

-- | Flip the cassette around to extract the pretty printer.
pretty :: PP a -> a -> Maybe String

-- | Always fail.
empty :: PP0

-- | Do nothing.
nothing :: PP0

-- | Turn the given pure transformer into a parsing/printing pair. That is,
--   return a cassette that produces and output on the one side, and
--   consumes an input on the other, in addition to the string
--   transformations of the given pure transformer. <tt>shift x p</tt>
--   produces <tt>x</tt> as the output of <tt>p</tt> on the parsing side,
--   and on the printing side accepts an input that is ignored.
shift :: a -> PP0 -> PP a

-- | Turn the given cassette into a pure string transformer. That is,
--   return a cassette that does not produce an output or consume an input.
--   <tt>unshift x p</tt> throws away the output of <tt>p</tt> on the
--   parsing side, and on the printing side sets the input to <tt>x</tt>.
unshift :: a -> PP a -> PP0

-- | Strip<i>add the given string from</i>to the output string.
string :: String -> PP0

-- | Successful only if predicate holds.
satisfy :: (Char -> Bool) -> PP Char

-- | Parse<i>print without consuming</i>producing any input.
lookAhead :: PP a -> PP a

-- | Succeeds if input string is empty.
eof :: PP0
instance Control.Category.Category Text.Cassette.Prim.Sym

module Text.Cassette.Lead

-- | The type of binary leads, parameterized by the type of the left
--   operand, the right operand, and the type of the result.
type UnL a b = forall r r'. K7 (C (b -> r)) (C (a -> r)) (C (b -> r')) (C (a -> r'))

-- | The type of binary leads, parameterized by the type of the left
--   operand, the right operand, and the type of the result.
type BinL a b c = forall r r'. K7 (C (c -> r)) (C (b -> a -> r)) (C (c -> r')) (C (b -> a -> r'))

-- | Lift a pair of symmetric functions to a lead.
liftL :: Sym a b -> UnL a b

-- | Iterates a one step construction function (resp. deconstruction)
--   function, i.e. a lead, thus obtaining a right fold (resp. unfold). The
--   resulting lead is a catamorphism on one side and an anamorpism on the
--   other, hence the name. The type of this function is the same as that
--   of <a>foldr</a>, lifted to cassettes.
catanar :: BinL a b b -> BinL b [a] b

-- | Iterates a one step construction function (resp. deconstruction)
--   function, i.e. a lead, thus obtaining a left fold (resp. unfold). The
--   resulting lead is a catamorphism on one side and an anamorpism on the
--   other, hence the name. The type of this function is the same as that
--   of <a>foldl</a>, lifted to cassettes.
catanal :: BinL a b a -> BinL a [b] a
consL :: BinL a [a] [a]
nilL :: PP [a]
justL :: UnL a (Maybe a)
nothingL :: PP (Maybe a)
pairL :: BinL a b (a, b)
tripleL :: K7 (C ((a, b, c) -> r)) (C (c -> b -> a -> r)) (C ((a, b, c) -> r')) (C (c -> b -> a -> r'))
quadrupleL :: K7 (C ((a, b, c, d) -> r)) (C (d -> c -> b -> a -> r)) (C ((a, b, c, d) -> r')) (C (d -> c -> b -> a -> r'))

module Text.Cassette.Combinator

-- | Applies each cassette in the supplied list in order, until one of them
--   succeeds.
choice :: [PP a] -> PP a

-- | <tt>count n p</tt> matches <tt>n</tt> occurrences of <tt>p</tt>.
count :: Int -> PP a -> PP [a]

-- | Tries to apply the given cassette. It returns the value of the
--   cassette on success, the first argument otherwise.
option :: a -> PP a -> PP a

-- | Tries to apply the given cassette. It returns a value of the form
--   <tt>Just x</tt> on success, <tt>Nothing</tt> otherwise.
optionMaybe :: PP a -> PP (Maybe a)

-- | Tries to match the given cassette and discards the result, otherwise
--   does nothing in case of failure.
optional :: PP a -> PP0

-- | Apply the given cassette zero or more times.
many :: PP a -> PP [a]

-- | Apply the given cassette one or more times.
many1 :: PP a -> PP [a]

-- | Apply the given cassette zero or more times, discarding the result.
skipMany :: PP a -> PP0

-- | Apply the given cassette one or more times, discarding the result.
skipMany1 :: PP a -> PP0

-- | Apply the first argument zero or more times, separated by the second
--   argument.
sepBy :: PP a -> PP0 -> PP [a]

-- | Apply the first argument one or more times, separated by the second
--   argument.
sepBy1 :: PP a -> PP0 -> PP [a]

-- | <tt>chainl p op x</tt> matches zero or more occurrences of <tt>p</tt>,
--   separated by <tt>op</tt>. Returns a value obtained by a <i>left
--   associative</i> application of all functions returned by <tt>op</tt>
--   to the values returned by <tt>p</tt>. If there are zero occurrences of
--   <tt>p</tt>, the value <tt>x</tt> is returned.
chainl :: PP0 -> BinL a a a -> PP a -> a -> PP a

-- | Match a a left-associative chain of infix operators.
chainl1 :: PP0 -> BinL a a a -> PP a -> PP a

-- | <tt>chainr p op x</tt> matches zero or more occurrences of <tt>p</tt>,
--   separated by <tt>op</tt>. Returns a value obtained by a <i>right
--   associative</i> application of all functions returned by <tt>op</tt>
--   to the values returned by <tt>p</tt>. If there are zero occurrences of
--   <tt>p</tt>, the value <tt>x</tt> is returned.
chainr :: PP0 -> BinL a a a -> PP a -> a -> PP a

-- | Match a a right-associative chain of infix operators.
chainr1 :: PP0 -> BinL a a a -> PP a -> PP a

-- | <tt>notFollowedBy p</tt> only succeeds when <tt>p</tt> fails. This
--   combinator does not consume/produce any input.
notFollowedBy :: PP0 -> PP0

-- | Applies first argument zero or more times until second argument
--   succeeds.
manyTill :: PP a -> PP0 -> PP [a]

module Text.Cassette.Char

-- | Succeeds if the current character is in the supplied list of
--   characters. See also <a>satisfy</a>.
--   
--   <pre>
--   vowel = oneOf "aeiou"
--   </pre>
oneOf :: [Char] -> PP Char

-- | Dual of <a>oneOf</a>.
noneOf :: [Char] -> PP Char

-- | The <a>satisfy</a> combinator, unshifted.
skip :: (Char -> Bool) -> Char -> PP0

-- | <a>skipSpace</a> marks a position where whitespace is allowed to
--   occur. It accepts arbitrary space while parsing, and produces no space
--   while printing.
skipSpace :: PP0

-- | <a>optSpace</a> marks a position where whitespace is desired to occur.
--   It accepts arbitrary space while parsing, and produces a single space
--   character while printing.
optSpace :: PP0

-- | <a>sepSpace</a> marks a position where whitespace is required to
--   occur. It requires one or more space characters while parsing, and
--   produces a single space character while printing.
sepSpace :: PP0

-- | Parses a newline character ('\n').
newline :: PP0

-- | Parses a tab character ('\t').
tab :: PP0
upper :: PP Char
lower :: PP Char
alphaNum :: PP Char
letter :: PP Char
digit :: PP Char
hexDigit :: PP Char
octDigit :: PP Char

-- | Any character.
anyChar :: PP Char

-- | A specific character.
char :: Char -> PP0


-- | This module exports combinators for parsing number literals.
module Text.Cassette.Number

-- | An integer literal, positive or negative.
int :: PP Int


-- | The combinators of this library are all pairs of functions going in
--   opposite directions. These pairs are called <i>cassettes</i>, sporting
--   two tracks (the two functions), one of which is read is one direction,
--   the other of which (accessed by flipping the cassette) is read in the
--   opossite direction.
--   
--   Here is an example specification for the lambda-calculus:
--   
--   <pre>
--   varL = K7 leadout leadin where
--     leadout k k' s x = k (\ s _ -&gt; k' s x) s (Var x)
--     leadin k k' s t@(Var x)  = k (\ s _ -&gt; k' s t) s x
--     leadin k k' s t          = k' s t
--   
--   absL = K7 leadout leadin where
--     leadout k k' s t' x = k (\ s _ -&gt; k' s t' x) s (Lam x t')
--     leadin k k' s t@(Lam x t)  = k (\ s _ _ -&gt; k' s t) s t x
--     leadin k k' s t            = k' s t
--   
--   appL = K7 leadout leadin where
--     leadout k s t2 t1 = k (\ s _ -&gt; k' s t2 t1) s (App t1 t2)
--     leadin k k' s t@(App t1 t2)  = k (\ s _ _ -&gt; k' s t) s t2 t1
--     leadin k k' s t            = k' s t
--   
--   parens p = char '(' &lt;&gt; p &lt;&gt; char ')'
--   
--   term :: PP Term
--   term  =   varL --&gt; ident
--         &lt;|&gt; absL --&gt; char '\' &lt;&gt; ident &lt;&gt; term
--         &lt;|&gt; appL --&gt; parens (term &lt;&gt; sepSpace &lt;&gt; term)
--   </pre>
--   
--   From this single specification, we can extract a parser,
--   
--   <pre>
--   parse term :: PP Term -&gt; String -&gt; Maybe Term
--   </pre>
--   
--   and also a pretty printer,
--   
--   <pre>
--   pretty term :: PP Term -&gt; Term -&gt; Maybe String
--   </pre>
--   
--   Specifications are built from primitive and derived combinators, which
--   affect the input string in some way. For each constructor of each
--   datatype, we need to write a <i>lead</i>, which is a pair of a
--   construction function and a destruction function. Leads are pure
--   combinators that do not affect the input string. By convention, we
--   suffix their name with <a>L</a>.
--   
--   Internally, the primitive combinators are written in CPS. Leads also
--   need to be written in this style, being primitive. They can, however,
--   be automatically generated for every datatype using some Template
--   Haskell hackery (in a separate package). A number of leads for
--   standard datatypes are defined in the <a>Lead</a> module.
module Text.Cassette
