-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A parser for indentation based structures
--
-- This is a complete rewrite of the Indentparser package. Using the
-- monad transformer structer of parsec 3, the code has been greatly
-- simplified. Besides these changes the code is now in public domain.
@package indentparser
@version 0.1
-- | In general, an indentation structure is a predicate on the position
-- which tells us whether the token is acceptable or not. Besides the
-- predicate to check if a token at a given position is acceptable, we
-- also need to specify how indentations can be nested. This is captured
-- by the type class Indentation.
module Text.Parsec.IndentParsec.Prim
-- | Type class that captures generic indentation rule. It should follow
-- the condition that acceptable never = const
-- False.
class Indentation i
never :: Indentation i => i
always :: Indentation i => i
acceptable :: Indentation i => i -> SourcePos -> Bool
nestableIn :: Indentation i => i -> i -> Bool
-- | The indentation parser.
type GenIndentParsecT i s u m a = ParsecT s u (IndentT i m) a
-- | Build indentation awareness into the parser
tokeniser :: (Indentation i, Monad m) => GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Any nested indentation starts at a position. Given an indentor
-- function, i.e. a function to compute the indentation state from the
-- current position, and a parser to parse the body of the indentation,
-- runs the parser inside the nested indentation context given by the
-- indentor.
nest :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t) => (SourcePos -> i) -> GenIndentParsecT i s u m body -> GenIndentParsecT i s u m body
-- | run a given parser neglecting indentation.
neglectIndent :: (Monad m, Show t, Show i, Indentation i, Stream s (IndentT i m) t) => GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Type to capture Haskell like indentation. Besides always and
-- never the important indentations are blocks and line folds. A
-- block starting at position p consists of all tokens that have
-- indentation at least as much as p. A folded like starting at
-- position p is
data HaskellLike
Never :: HaskellLike
Neglect :: HaskellLike
Block :: SourcePos -> HaskellLike
LineFold :: SourcePos -> HaskellLike
-- | Run a given indentation aware parser with a starting indentation.
runGIPT' :: (Monad m, Stream s (IndentT i m) t) => i -> GenIndentParsecT i s u m a -> u -> SourceName -> s -> m (Either ParseError a)
-- | Same as runGIPT' always.
runGIPT :: (Monad m, Indentation i, Stream s (IndentT i m) t) => GenIndentParsecT i s u m a -> u -> SourceName -> s -> m (Either ParseError a)
-- | The inner monad for indent parsers.
type IndentT i m = StateT i m
type GenIndentParsec i s u a = GenIndentParsecT i s u Identity a
type IndentParsecT s u m a = GenIndentParsecT HaskellLike s u m a
type IndentParsec s u a = IndentParsecT s u Identity a
instance Show HaskellLike
instance Indentation HaskellLike
-- | Module containing combinators to parse some indentation based
-- structures.
module Text.Parsec.IndentParsec.Combinator
-- | 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
-- | 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
-- | 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 -> GenIndentParsecT i s u m close -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m 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 -> IndentParsecT s u m close -> IndentParsecT s u m a -> IndentParsecT s u m a
-- | Module to create indentation aware tokenisers. Despite the simplicity
-- of parser combinators, getting tokenisers for common language
-- contructs right is tricky. The parsec way of handling this involves
-- the following steps.
--
--
-- - Define the description of the language via the
-- Text.Parsec.Language.LanguageDef record.
-- - Apply the Text.Parsec.Token.makeTokenParser combinator
-- get hold of Text.Parsec.Token.TokenParser. The
-- actual tokenisers are the fields of this record.
--
--
-- This module provides a similar interfaces for generating indentation
-- aware tokenisers. There are few specific things that an indentation
-- aware tokeniser should be careful aboute
--
--
-- - All tokenisers should be indentation aware.
-- - Whitespaces and comments should be skipped irrespective on which
-- indentation mode one is in
-- - The tokenisers should themselves be lexeme parsers and should skip
-- trailing whitespace.
--
--
-- Getting all this working can often be tricky.
module Text.Parsec.IndentParsec.Token
type GenIndentTokenParser i s u m = GenTokenParser s u (IndentT i m)
type IndentTokenParser s u m = GenIndentTokenParser HaskellLike s u m
-- | Indentation aware tokeniser to match a valid identifier.
identifier :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Indentation aware tokeniser matches an operator.
operator :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Indentation aware tokeniser to match a reserved word.
reserved :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> String -> GenIndentParsecT i s u m ()
-- | Indentation aware parser to match a reserved operator of the language.
reservedOp :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> String -> GenIndentParsecT i s u m ()
-- | Indentation aware parser to match a character literal (the syntax is
-- assumend to be that of Hasekell which matches that of most programming
-- language
charLiteral :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Char
-- | Indentation aware parser to match a string literal (the syntax is
-- assumend to be that of Hasekell which matches that of most programming
-- language).
stringLiteral :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Indentation aware parser to match a natural number.
natural :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Integer
-- | Indentation aware parser to match an integer.
integer :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Integer
-- | Indentation aware tokeniser to match a floating point number.
float :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Double
-- | Indentation aware tokensier to match either a natural number or
-- Floating point number.
naturalOrFloat :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m (Either Integer Double)
-- | Indentation aware tokensier to match an integer in decimal.
decimal :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Integer
-- | Indentation aware tokeniser to match an integer in hexadecimal.
hexadecimal :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Integer
-- | Indentation aware tokeniser to match an integer in ocatal.
octal :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m Integer
-- | Indentation aware tokeniser that is equvalent to
-- string.
symbol :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> String -> GenIndentParsecT i s u m String
-- | Creates a lexeme tokeniser. The resultant tokeniser indentation aware
-- and skips trailing white spaces/comments.
lexeme :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | The parser whiteSpace skips spaces and comments. This does not care
-- about indentation as skipping spaces should be done irrespective of
-- the indentation
whiteSpace :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m ()
-- | Matches a semicolon and returns ';'.
semi :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Matches a comma and returns ,.
comma :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Matches a colon and returns :.
colon :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Matches a dot and returns ..
dot :: (Indentation i, Monad m) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m String
-- | Match the input parser p within a pair of paranthesis.
parens :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Same as parens but if no explicit paranthesis are given,
-- matches p inside an indented block.
parensBlock :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m a
-- | Match the input parser p within a pair of braces
braces :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Same as braces but if no explicit braces are given, matches
-- p inside an indented block.
bracesBlock :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m a
-- | Match the input parser p within a pair of angular brackets,
-- i.e. < and >.
angles :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Same as angles but if no explicit anglular brackets are given,
-- matches p inside and indented block.
anglesBlock :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m a
-- | Match p within a angular brackets i.e. '[' and ']'.
brackets :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m a
-- | Same as brackets but if no explicit brackets are given, matches
-- p inside and indented block.
bracketsBlock :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m a
-- | Parse zero or more p seperated by by a semicolon
semiSep :: (Indentation i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m [a]
-- | Parse zero or more p seperated by semicolon or new line. Long
-- lines are continued using line folding.
semiSepOrFoldedLines :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m [a]
-- | Parse one or more p seperated by a semicolon
semiSep1 :: (Indentation i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m [a]
-- | Parse one or more p seperated by semicolon or new line. Long
-- lines are continued using line folding.
semiSepOrFoldedLines1 :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m [a]
-- | Parse zero or more p seperated by by a comma.
commaSep :: (Indentation i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m [a]
-- | Parse zero or more p seperated by comma or new line. Long
-- lines are continued using line folding.
commaSepOrFoldedLines :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m [a]
-- | Parse one or more p seperated by a comma.
commaSep1 :: (Indentation i, Monad m, Stream s (IndentT i m) t, Show t) => GenIndentTokenParser i s u m -> GenIndentParsecT i s u m a -> GenIndentParsecT i s u m [a]
-- | Parse one or more p seperated by comma or new line. Long
-- lines are continued using line folding.
commaSepOrFoldedLines1 :: (Monad m, Stream s (IndentT HaskellLike m) t, Show t) => GenIndentTokenParser HaskellLike s u m -> GenIndentParsecT HaskellLike s u m a -> GenIndentParsecT HaskellLike s u m [a]
-- | A module to construct indentation aware parsers. Many programming
-- language have indentation based syntax rules e.g. python and Haskell.
-- This module exports combinators to create such parsers. This is a
-- rewrite of the IndentParser package. There are a few changes in the
-- names of functions besides the underlying code is simplified.
--
-- The input source can be thought of as a list of tokens. Abstractly
-- each token occurs at a line and a column and has a width. The column
-- number of a token measures is indentation. If t1 and t2 are two tokens
-- then we say that indentation of t1 is more than t2 if the column
-- number of occurrence of t1 is greater than that of t2.
--
-- Currently this module supports two kind of indentation based syntactic
-- structures which we now describe:
--
--
-- - Block A block of indentation c is a sequence of
-- tokens with indentation at least c. Examples for a block is a
-- where clause of Haskell with no explicit braces.
-- - Line fold A line fold starting at line l and
-- indentation c is a sequence of tokens that start at line
-- l and possibly continue to subsequent lines as long as the
-- indentation is greater than c. Such a sequence of lines need to
-- be folded to a single line. An example is MIME headers. Line
-- folding based binding separation is used in Haskell as well.
--
--
-- For indentation based grammars notice the following should be true
--
--
-- - Combinators for skipping whitespace/comments should skip spaces
-- and comments no matter what the indentation is.
-- - All tokenisers of the language should check for indentation. The
-- combinator tokeniser makes its input parser indentation aware.
-- Use it on all tokenisers of the language.
-- - All tokenisers themselves should skip trailing whitespaces and
-- comments, i.e. they should be lexeme parsers. Otherwise, the will be
-- problem matching the next token.
--
--
-- A block can then be parsed using the combinator blockOf and a
-- line fold using foldedLinesOf.
--
-- Generating indentation aware tokenisers could be tricky. One can use
-- the module Text.Parsec.IndentParsec.Token for this.
module Text.Parsec.IndentParsec