packages feed

indentparser (empty) → 0.1

raw patch · 8 files changed

+941/−0 lines, 8 filesdep +basedep +mtldep +parsecsetup-changed

Dependencies added: base, mtl, parsec

Files

+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ UNLICENSE view
@@ -0,0 +1,24 @@+This is free and unencumbered software released into the public domain.++Anyone is free to copy, modify, publish, use, compile, sell, or+distribute this software, either in source code form or as a compiled+binary, for any purpose, commercial or non-commercial, and by any+means.++In jurisdictions that recognize copyright laws, the author or authors+of this software dedicate any and all copyright interest in the+software to the public domain. We make this dedication for the benefit+of the public at large and to the detriment of our heirs and+successors. We intend this dedication to be an overt act of+relinquishment in perpetuity of all present and future rights to this+software under copyright law.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.++For more information, please refer to <http://unlicense.org/>
+ examples/simple-expression.hs view
@@ -0,0 +1,69 @@+import Text.Parsec+import Text.Parsec.Prim+import Text.Parsec.IndentParsec(runGIPT)++import Control.Monad.Identity+import Text.Parsec.Token (makeTokenParser, GenLanguageDef(..))+import qualified Text.Parsec.IndentParsec.Token as IT+import Text.Parsec.IndentParsec.Prim++data Expr = Const Integer+          | Var String+          | WhereClause Expr [Binding] deriving Show++type Binding = (String, Expr)++langDef = LanguageDef { commentStart = "{-"+                      , commentEnd   = "-}"+                      , commentLine  = "--"+                      , identStart = letter   <|> char '_'+                      , identLetter = alphaNum <|> char '_'+                      , opStart = oneOf "-+/*=<>"+                      , opLetter = oneOf "-+/*=<>"+                      , reservedNames = [ "where" ]+                      , reservedOpNames = [ "=" , "+" , "-", "*", "/"]+                      , caseSensitive = False+                      , nestedComments = True+                      }++tokP :: IT.IndentTokenParser String () Identity+tokP = makeTokenParser langDef++identifier = IT.identifier tokP+integer = IT.integer tokP+semiSep = IT.semiSepOrFoldedLines tokP+kwWhere = IT.reserved tokP "where"+assigns = IT.reservedOp tokP "="+++main = do inp <- getContents+          let x = runGIPT prog () "<stdin>" inp+              in case runIdentity x of+                      Right bs -> sequence_ $ map print bs+                      Left e -> do putStr "parse error: "+                                   print e++prog :: IndentParsecT String () Identity [Binding]+prog = do IT.whiteSpace tokP+          semiSep binding++expression = fmap Const integer+             <|> fmap Var identifier+             <|> do e <- expression+                    kwWhere+                    bs <- IT.bracesBlock tokP bindings+                    return $ WhereClause e bs++compoundExpression = do e <- expression+                        whereBlock e++whereBlock e = do try kwWhere+                  bs <- IT.bracesBlock tokP bindings+                  return $ WhereClause e bs+               <|> return e++bindings = semiSep binding+binding = do x <- identifier+             assigns+             e <- compoundExpression+             return (x,e)
+ indentparser.cabal view
@@ -0,0 +1,53 @@+Name: indentparser+Version: 0.1+Synopsis: A parser for indentation based structures+Homepage: http://www.cse.iitk.ac.in/users/ppk/code/HASKELL/indentparser++Description: 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.++License: PublicDomain+License-file: UNLICENSE+Author: Piyush P Kurur+Maintainer: ppk@cse.iitk.ac.in+Copyright: I, Piyush P Kurur, hereby release the software to the public domain+   I, however, do not give any warrenties what so ever. Please refer to the+   accompanying file UNLICENSE for more details.++   Also see http://cr.yp.to/publicdomain.html for an explanation of+   what it means to release under public domain in the United States+   of America.++Category: Text+Build-type: Simple+Cabal-version: >=1.6++Flag examples+  Description: Build the example code.+  Default: False++Library+  Hs-source-dirs: src+  GHC-options: -Wall+  Exposed-modules: Text.Parsec.IndentParsec+                 , Text.Parsec.IndentParsec.Prim+                 , Text.Parsec.IndentParsec.Combinator+                 , Text.Parsec.IndentParsec.Token+  Build-depends: base >= 4.0 && < 5+               , mtl  >= 2.0 && < 3+               , parsec >= 3.0 && < 4++Executable simple-expression+  Hs-source-dirs:examples, src+  Main-is:simple-expression.hs+  if !flag(examples)+    Buildable:False+  else+    Build-depends: parsec >= 3.0++Source-repository this+  type: darcs+  location: http://patch-tag.com/r/ppk/indentparser+  tag: 0.1-RELEASE
+ src/Text/Parsec/IndentParsec.hs view
@@ -0,0 +1,58 @@+{-|++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++1. Combinators for skipping whitespace/comments should skip spaces and+comments no matter what the indentation is.++2. 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.++3. 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+       ( module Text.Parsec.IndentParsec.Prim+       , module Text.Parsec.IndentParsec.Combinator+       , module Text.Parsec.IndentParsec.Token+       ) where++import Text.Parsec.IndentParsec.Prim+import Text.Parsec.IndentParsec.Combinator+import Text.Parsec.IndentParsec.Token
+ src/Text/Parsec/IndentParsec/Combinator.hs view
@@ -0,0 +1,82 @@+{-# 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
+ src/Text/Parsec/IndentParsec/Prim.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE FlexibleContexts #-}+{-|++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+       ( Indentation(..)+       , GenIndentParsecT+       , tokeniser+       , nest+       , neglectIndent+       , HaskellLike(..)+       -- * Running parsers+       , runGIPT', runGIPT+       -- * Some convenient type aliases.+       , IndentT+       , GenIndentParsec+       , IndentParsecT+       , IndentParsec+       ) where++import Control.Monad.State+import Control.Monad.Identity++import Text.Parsec.Prim+import Text.Parsec.Error+import Text.Parsec.Pos+import Text.Parsec.Combinator++{-|++Type class that captures generic indentation rule. It should follow+the condition that @`acceptable` `never` = `const` `False`@.++-}++class Indentation i where+      never      :: i  -- ^ an indentation state where no tokens are+                       -- accepted.+      always     :: i  -- ^ an indentation that will always accept+                       -- tokens.+      acceptable :: i -> SourcePos -> Bool -- ^ Check if the current+                                           -- position is acceptable.+      nestableIn :: i -- ^ Inner indentation.+                 -> i -- ^ Outer indentation.+                 -> Bool -- ^ True if the inner indentation can nest+                         -- inside the outer indentations.++-- | The inner monad for indent parsers.+type IndentT i m = StateT i m++-- | 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+tokeniser p = do pos <- getPosition+                 i   <- lift get+                 if acceptable i pos then p+                    else fail $ "unexpected token at " ++ show pos++{-|++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) -- ^ indentor function.+     -> GenIndentParsecT i s u m body -- ^ The nested parser to run+     -> GenIndentParsecT i s u m body+nest indentor p = do outerI <- lift get+                     curPos <- getPosition+                     let innerI = indentor curPos+                         in if innerI `nestableIn` outerI+                            then nestP innerI outerI p+                            else nestP never  outerI p++nestP :: (Indentation i, Show i, Monad m, Stream s (IndentT i m) t, Show t)+      => i -- ^ Inner indentation+      -> i -- ^ Outer indentation+      -> GenIndentParsecT i s u m body -- ^ body parser+      -> GenIndentParsecT i s u m body++nestP i o p = do lift $ put i+                 x <- p+                 notFollowedBy (tokeniser anyToken)+                               <?> "unterminated " ++ show i+                 lift $ put o+                 return x++-- | 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++neglectIndent p = do o <- get+                     lift $ put always+                     x <- p+                     lift $ put o+                     return x++-- | Run a given indentation aware parser with a starting indentation.+runGIPT' :: (Monad m, Stream s (IndentT i m) t)+         => i                          -- ^ The starting indentation,+         -> GenIndentParsecT i s u m a -- ^ The parser to run,+         -> u                          -- ^ The user state,+         -> SourceName                 -- ^ Name of the input source,+         -> s                          -- ^ The actual stream,+         -> m (Either ParseError a)    -- ^ The result++runGIPT' i p u sname s = evalStateT (runPT p u sname s) i++-- | Same as @`runGIPT'` always@.+runGIPT :: (Monad m, Indentation i, Stream s (IndentT i m) t)+        => GenIndentParsecT i s u m a -- ^ The parser to run,+        -> u                          -- ^ The user state,+        -> SourceName                 -- ^ Name of the input source,+        -> s                          -- ^ The actual stream,+        -> m (Either ParseError a)    -- ^ The result.++runGIPT  = runGIPT' always++{-|++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+                   | Neglect+                   | Block SourcePos+                   | LineFold SourcePos++instance Indentation HaskellLike where+         never  = Never+         always = Neglect++         acceptable Never          _ = False+         acceptable Neglect        _ = True+         acceptable (Block bp)     p = sourceColumn bp <= sourceColumn p+         acceptable (LineFold lp)  p = sourceColumn lp < sourceColumn p ||+                                            lp == p+         nestableIn (Block i)    (Block o)    = sourceColumn o < sourceColumn i+         nestableIn (Block i)    (LineFold o) = sourceColumn o < sourceColumn i+         nestableIn (LineFold i) (LineFold o) = sourceColumn o < sourceColumn i+         nestableIn (LineFold i) (Block o)    = sourceColumn o <= sourceColumn i+         nestableIn _            _            = True++instance Show HaskellLike where+         show Never   = "empty block"+         show Neglect = "unindented chunk"+         show (Block pos)    = "block started at " ++ show pos+         show (LineFold pos) = "line fold started at " ++ show pos++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
+ src/Text/Parsec/IndentParsec/Token.hs view
@@ -0,0 +1,479 @@+{-# LANGUAGE FlexibleContexts #-}+{-|++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++   1. All tokenisers should be indentation aware.++   2. Whitespaces and comments should be skipped irrespective on which+      indentation mode one is in++   3. 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+       (+       -- * Usage.+       -- $usage+         GenIndentTokenParser+       , IndentTokenParser+       , identifier+       , operator+       , reserved+       , reservedOp+       , charLiteral+       , stringLiteral+       , natural+       , integer+       , float+       , naturalOrFloat+       , decimal+       , hexadecimal+       , octal+       , symbol+       , lexeme+       , whiteSpace+       , semi+       , comma+       , colon+       , dot+       , parens, parensBlock+       , braces, bracesBlock+       , angles, anglesBlock+       , brackets, bracketsBlock+       , semiSep, semiSepOrFoldedLines+       , semiSep1, semiSepOrFoldedLines1+       , commaSep, commaSepOrFoldedLines+       , commaSep1, commaSepOrFoldedLines1+       ) where+++import Text.Parsec.IndentParsec.Prim+import Text.Parsec.IndentParsec.Combinator+import Text.Parsec(many)++import qualified Text.Parsec.Token as T+import Text.Parsec(Stream)+import Text.Parsec.Combinator hiding (between)+++{- $usage++For each combinator @foo@ for every field @foo@ of the+'Text.Parsec.Token.TokenParser' with essentially the same semantics+but for the returned parser being indentation aware. There are certain+new combinators that are defined specifically for parsing indentation+based syntactic constructs:++[Grouping Parsers] A grouping parser takes an input parser @p@ and+returns a parser that parses @p@ between two /grouping delimiters/.+There are three flavours of grouping parsers: @foo@, @fooBlock@ where+@foo@ can be one of @angles@, @braces@, @parens@, @brackets@. For+example, consider the parser @'braces' tokP p@ parses @p@ delimited by+'{' and '}'. In this case @p@ does not care about indentation. The+parser @'bracesBlock' tokP p@ is like @braces tokP p@ but if no+explicit delimiting braces are given parses @p@ within an indented+block.++> bracesBlock tokP p    = braces tokP p <|> blockOf p++[Seperator Parsers] A seperator parser takes as input a parser say @p@+and returns a parser that parses a list of @p@ seperated by a+seperator. The module exports the combinators @fooSep@, @fooSep1@,+@fooSepOrFoldedLines@ and @fooSepOrFoldedLines1@, where @foo@ is+either @semi@ (in which case the seperator is a semicolon) or @comma@+(in which case the seperator is a comma).++To illustrate the use of this module we now give, as an incomplete+example, a parser that parses a where clause in Haskell which+illustrates the use of this module.++>   import qualified Text.Parsec.Language as L+>   import qualified Text.Parsec.Toke as T+>   import qualified Text.Parsec.IndentToken as IT+>   tokP = T.makeTokenParser L.haskellDef+>   mySemiSep = IT.semiSepOrFoldedLines tokP+>   myBraces = IT.bracesBlock tokP+>   identifier = IT.identifier tokP+>   ....+>   symbol = IT.symbol tokP+>+>   binding = mySemiSep bind+>   bind    = do id <- identifier+>                symbol (char '=')+>                e <- expr+>                return (id,e)+>+>  whereClause = do reserved "where"; braceBlock binding++-}++type GenIndentTokenParser i s u m = T.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+identifier = tokeniser . T.identifier++-- | Indentation aware tokeniser matches an operator.+operator  :: (Indentation i, Monad m)+          => GenIndentTokenParser i s u m+          -> GenIndentParsecT i s u m String+operator = tokeniser . T.operator++-- | Indentation aware tokeniser to match a reserved word.+reserved :: (Indentation i, Monad m)+         => GenIndentTokenParser i s u m+         -> String -- ^ The reserved word.+         -> GenIndentParsecT i s u m ()+reserved tokP = tokeniser . T.reserved tokP++-- | Indentation aware parser to match a reserved operator of the+-- language.+reservedOp :: (Indentation i, Monad m)+           => GenIndentTokenParser i s u m+           -> String -- ^ The reserved operator to be matched.+           -> GenIndentParsecT i s u m ()+reservedOp tokP = tokeniser . T.reservedOp tokP++-- | 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+charLiteral = tokeniser . T.charLiteral++-- | 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+stringLiteral = tokeniser . T.stringLiteral++-- | Indentation aware parser to match a natural number.+natural :: (Indentation i, Monad m)+        => GenIndentTokenParser i s u m+        -> GenIndentParsecT i s u m Integer+natural = tokeniser . T.natural++-- | Indentation aware parser to match an integer.+integer :: (Indentation i, Monad m)+        => GenIndentTokenParser i s u m+        -> GenIndentParsecT i s u m Integer+integer = tokeniser . T.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+float = tokeniser . T.float++-- | 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)+naturalOrFloat = tokeniser . T.naturalOrFloat++-- | 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+decimal = tokeniser . T.decimal++-- | 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+hexadecimal = tokeniser . T.hexadecimal++-- | 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+octal = tokeniser . T.octal++-- | 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+symbol tokP = tokeniser . T.symbol tokP++-- | 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+lexeme tokP = tokeniser . T.lexeme tokP++-- | 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 ()+whiteSpace = T.whiteSpace++-- | Matches a semicolon and returns ';'.+semi :: (Indentation i, Monad m)+     => GenIndentTokenParser i s u m+     -> GenIndentParsecT i s u m String+semi = tokeniser . T.semi++-- | Matches a comma and returns ",".+comma :: (Indentation i, Monad m)+      => GenIndentTokenParser i s u m+      -> GenIndentParsecT i s u m String+comma = tokeniser . T.comma++-- | Matches a colon and returns ":".+colon :: (Indentation i, Monad m)+      => GenIndentTokenParser i s u m+      -> GenIndentParsecT i s u m String+colon = tokeniser . T.colon++-- | Matches a dot and returns ".".+dot :: (Indentation i, Monad m)+    => GenIndentTokenParser i s u m+    -> GenIndentParsecT i s u m String+dot = tokeniser . T.dot++lparen   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+rparen   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+lbrace   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+rbrace   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+langle   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+rangle   :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+lbracket :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String+rbracket :: (Monad m, Indentation i)+         => GenIndentTokenParser i s u m+         -> GenIndentParsecT i s u m String++lparen tokP = symbol tokP "("+rparen tokP = symbol tokP ")"++lbrace tokP = symbol tokP "{"+rbrace tokP = symbol tokP "}"++langle tokP = symbol tokP "<"+rangle tokP = symbol tokP ">"++lbracket tokP = symbol tokP "["+rbracket tokP = symbol tokP "]"++-- | 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+parens tokP = lparen tokP  `between` rparen tokP++{-|++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+parensBlock tokP = lparen tokP `betweenBlock` rparen tokP++-- | 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+braces tokP = lbrace tokP  `between` rbrace tokP++{-|++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+bracesBlock tokP = lbrace tokP  `betweenBlock` rbrace tokP++{-|++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+angles tokP = langle tokP  `between` rangle tokP++{-|++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+anglesBlock tokP = langle tokP  `betweenBlock` rangle tokP++-- | 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+brackets tokP = lbracket tokP  `between` rbracket tokP++{-|++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+bracketsBlock tokP = lbracket tokP  `betweenBlock` rbracket tokP++-- | 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]+semiSep tokP p =  sepBy p $ semi tokP++-- |  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]+semiSep1 tokP p =  sepBy1 p $ semi tokP++{-|++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]+semiSepOrFoldedLines tokP p = fmap concat .  many+                                          . foldedLinesOf+                                          . sepEndBy1 p+                                          $ semi tokP++{-|++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]+semiSepOrFoldedLines1 tokP p = do first <- foldedLinesOf . sepEndBy1 p+                                                         $ semi tokP+                                  rest <- semiSepOrFoldedLines tokP p+                                  return (first ++ rest)+++-- | 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]+commaSep tokP p =  sepBy p $ comma tokP++-- |  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]+commaSep1 tokP p =  sepBy1 p $ comma tokP++{-|++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]+commaSepOrFoldedLines tokP p = fmap concat .  many+                                           . foldedLinesOf+                                           . sepEndBy1 p+                                           $ comma tokP++{-|++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]+commaSepOrFoldedLines1 tokP p = do first <- foldedLinesOf . sepEndBy1 p+                                                         $ comma tokP+                                   rest <- commaSepOrFoldedLines tokP p+                                   return (first ++ rest)