{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Text.Parsec.Indent (
IndentT, IndentParserT, IndentParser, runIndent,
runIndentParserT, runIndentParser,
withBlock, withBlock', block,
indented, same, sameOrIndented, checkIndent,
topLevel, notTopLevel,
withPos,
indentBrackets, indentAngles, indentBraces, indentParens,
(<+/>), (<-/>), (<*/>), (<?/>), Optional(..)
) where
import Control.Monad (ap, liftM2)
import Control.Monad.Identity (Identity, runIdentity)
import Control.Monad.Reader (ReaderT, ask, local, runReaderT)
import Text.Parsec
import qualified Text.Parsec.Indent.Explicit as Explicit
import Text.Parsec.Indent.Internal
import Text.Parsec.Token
referenceIndentation :: Monad m => IndentParserT s u m Indentation
referenceIndentation = ask
type IndentT m = ReaderT Indentation m
type IndentParserT s u m a = ParsecT s u (IndentT m) a
type IndentParser s u a = IndentParserT s u Identity a
withBlock
:: (Monad m, Stream s (IndentT m) z)
=> (a -> [b] -> c)
-> IndentParserT s u m a
-> IndentParserT s u m b
-> IndentParserT s u m c
withBlock f a p = withPos $ do
r1 <- a
r2 <- option [] (indented >> block p)
return (f r1 r2)
withBlock'
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m a
-> IndentParserT s u m b
-> IndentParserT s u m [b]
withBlock' = withBlock (flip const)
indented
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
indented = referenceIndentation >>= Explicit.indented
sameOrIndented
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
sameOrIndented = referenceIndentation >>= Explicit.sameOrIndented
same
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
same = referenceIndentation >>= Explicit.same
block
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m a
-> IndentParserT s u m [a]
block = Explicit.block
withPos
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m a
-> IndentParserT s u m a
withPos x = do
p <- Explicit.indentation
local (const p) x
checkIndent
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
checkIndent = referenceIndentation >>= Explicit.checkIndent
topLevel
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
topLevel = Explicit.topLevel
notTopLevel
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ()
notTopLevel = Explicit.notTopLevel
runIndentT :: Monad m => IndentT m a -> m a
runIndentT i = runReaderT i (Indentation 1 1)
runIndent :: IndentT Identity a -> a
runIndent = runIdentity . runIndentT
runIndentParserT
:: (Monad m, Stream s (IndentT m) t)
=> IndentParserT s u m a
-> u
-> SourceName
-> s
-> m (Either ParseError a)
runIndentParserT parser u source txt =
runIndentT (runParserT parser u source txt)
runIndentParser
:: Stream s (IndentT Identity) t
=> IndentParser s u a
-> u
-> SourceName
-> s
-> Either ParseError a
runIndentParser parser u source txt =
runIdentity (runIndentParserT parser u source txt)
(<+/>)
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m (a -> b)
-> IndentParserT s u m a
-> IndentParserT s u m b
a <+/> b = ap a (sameOrIndented >> b)
(<-/>)
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m a
-> IndentParserT s u m b
-> IndentParserT s u m a
a <-/> b = liftM2 const a (sameOrIndented >> b)
(<*/>)
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m ([a] -> b)
-> IndentParserT s u m a
-> IndentParserT s u m b
a <*/> b = ap a (many (sameOrIndented >> b))
data Optional s u m a = Opt a (IndentParserT s u m a)
(<?/>)
:: (Monad m, Stream s (IndentT m) z)
=> IndentParserT s u m (a -> b)
-> (Optional s u m a)
-> IndentParserT s u m b
(<?/>) a (Opt b c) = ap a (option b (sameOrIndented >> c))
indentBrackets
:: (Monad m, Stream s (IndentT m) z)
=> GenTokenParser s u (IndentT m)
-> IndentParserT s u m a
-> IndentParserT s u m a
indentBrackets lexer p = withPos $ return id <-/> symbol lexer "[" <+/> p <-/> symbol lexer "]"
indentAngles
:: (Monad m, Stream s (IndentT m) z)
=> GenTokenParser s u (IndentT m)
-> IndentParserT s u m a
-> IndentParserT s u m a
indentAngles lexer p = withPos $ return id <-/> symbol lexer "<" <+/> p <-/> symbol lexer ">"
indentBraces
:: (Monad m, Stream s (IndentT m) z)
=> GenTokenParser s u (IndentT m)
-> IndentParserT s u m a
-> IndentParserT s u m a
indentBraces lexer p = withPos $ return id <-/> symbol lexer "{" <+/> p <-/> symbol lexer "}"
indentParens
:: (Monad m, Stream s (IndentT m) z)
=> GenTokenParser s u (IndentT m)
-> IndentParserT s u m a
-> IndentParserT s u m a
indentParens lexer p = withPos $ return id <-/> symbol lexer "(" <+/> p <-/> symbol lexer ")"