indentparser-0.1: src/Text/Parsec/IndentParsec/Combinator.hs
{-# LANGUAGE FlexibleContexts #-}
{-|
Module containing combinators to parse some indentation based
structures.
-}
module Text.Parsec.IndentParsec.Combinator
( blockOf
, foldedLinesOf
, between
, betweenBlock
) where
import Text.Parsec.Prim
import Text.Parsec.IndentParsec.Prim
-- | run a given parser inside a block.
blockOf :: (Monad m, Show t, Stream s (IndentT HaskellLike m) t)
=> IndentParsecT s u m a
-> IndentParsecT s u m a
blockOf = nest Block
-- | run a given parser inside a line fold.
foldedLinesOf :: (Monad m, Show t, Stream s (IndentT HaskellLike m) t)
=> IndentParsecT s u m a
-> IndentParsecT s u m a
foldedLinesOf = nest LineFold
{-|
Similar to @`Text.Parsec.Combinator.between`@. However, the
@`Text.Parsec.Combinator.between`@ will not work as expected because
it will not turn off the indentation check of its input parser.
So something like
> whereClause = between lbrack rbrack bindings
> lbrack = do char '{'; spaces
> rbrack = do char '}'; spaces
will not be able to parse say
> where {
> a = 10
> }
Use the version exported by this module instead.
-}
between :: (Monad m, Indentation i, Show t, Show i, Stream s (IndentT i m) t)
=> GenIndentParsecT i s u m open -- ^ the opening delimiter
-> GenIndentParsecT i s u m close -- ^ the closing delimiter
-> GenIndentParsecT i s u m a -- ^ the contents
-> GenIndentParsecT i s u m a
between open close p = do _ <- try open
a <- neglectIndent p
_ <- neglectIndent close
return a
{-|
Similar to @`between`@ but if the opening and closing delimiters are
not given, uses a block to delimit the nesting. For example, a haskell
where clause will look like
> whereClause = betweenBlock lbrack rbrack bindings
> lbrack = do char '{'; spaces
> rbrack = do char '}'; spaces
-}
betweenBlock :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t)
=> IndentParsecT s u m open -- ^ opening delimitor
-> IndentParsecT s u m close -- ^ closing delimitor
-> IndentParsecT s u m a -- ^ the contents parser
-> IndentParsecT s u m a
betweenBlock open close p = between open close p <|> blockOf p