-- 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. -- -- -- -- 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 -- --
    --
  1. All tokenisers should be indentation aware.
  2. --
  3. Whitespaces and comments should be skipped irrespective on which -- indentation mode one is in
  4. --
  5. The tokenisers should themselves be lexeme parsers and should skip -- trailing whitespace.
  6. --
-- -- 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: -- -- -- -- For indentation based grammars notice the following should be true -- --
    --
  1. Combinators for skipping whitespace/comments should skip spaces -- and comments no matter what the indentation is.
  2. --
  3. 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.
  4. --
  5. 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.
  6. --
-- -- 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