packages feed

IndentParser 0.1 → 0.2

raw patch · 7 files changed

+991/−807 lines, 7 filesdep ~basedep ~parsecPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, parsec

API changes (from Hackage documentation)

- Text.ParserCombinators.Parsec.IndentParser: data IndentState st
- Text.ParserCombinators.Parsec.IndentParser: getIndentMode :: IndentParser tok st IndentMode
- Text.ParserCombinators.Parsec.IndentParser: indentMode :: IndentState st -> IndentMode
- Text.ParserCombinators.Parsec.IndentParser: instance Eq IndentMode
- Text.ParserCombinators.Parsec.IndentParser: instance Show IndentMode
- Text.ParserCombinators.Parsec.IndentParser: saveIndentMode :: IndentParser tok st a -> IndentParser tok st a
- Text.ParserCombinators.Parsec.IndentParser: setIndentMode :: IndentMode -> IndentParser tok st ()
- Text.ParserCombinators.Parsec.IndentParser: state :: IndentState st -> st
- Text.ParserCombinators.Parsec.IndentToken: angles :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: anglesOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: anglesOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: braces :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: bracesOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: bracesOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: brackets :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: bracketsOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: bracketsOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: charLiteral :: TokenParser st -> IndentCharParser st Char
- Text.ParserCombinators.Parsec.IndentToken: colon :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: commaOrNewLineSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: commaOrNewLineSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: commaSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: commaSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: decimal :: TokenParser st -> IndentCharParser st Integer
- Text.ParserCombinators.Parsec.IndentToken: dot :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: float :: TokenParser st -> IndentCharParser st Double
- Text.ParserCombinators.Parsec.IndentToken: hexadecimal :: TokenParser st -> IndentCharParser st Integer
- Text.ParserCombinators.Parsec.IndentToken: identifier :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: integer :: TokenParser st -> IndentCharParser st Integer
- Text.ParserCombinators.Parsec.IndentToken: lexeme :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: natural :: TokenParser st -> IndentCharParser st Integer
- Text.ParserCombinators.Parsec.IndentToken: naturalOrFloat :: TokenParser st -> IndentCharParser st (Either Integer Double)
- Text.ParserCombinators.Parsec.IndentToken: octal :: TokenParser st -> IndentCharParser st Integer
- Text.ParserCombinators.Parsec.IndentToken: operator :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: parens :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: parensOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: parensOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
- Text.ParserCombinators.Parsec.IndentToken: reserved :: TokenParser st -> String -> IndentCharParser st ()
- Text.ParserCombinators.Parsec.IndentToken: reservedOp :: TokenParser st -> String -> IndentCharParser st ()
- Text.ParserCombinators.Parsec.IndentToken: semi :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: semiOrNewLineSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: semiOrNewLineSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: semiSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: semiSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
- Text.ParserCombinators.Parsec.IndentToken: stringLiteral :: TokenParser st -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: symbol :: TokenParser st -> String -> IndentCharParser st String
- Text.ParserCombinators.Parsec.IndentToken: type IndentCharParser st a = IndentParser Char st a
- Text.ParserCombinators.Parsec.IndentToken: type LanguageDef st = LanguageDef (IndentState st)
- Text.ParserCombinators.Parsec.IndentToken: type TokenParser st = TokenParser (IndentState st)
- Text.ParserCombinators.Parsec.IndentToken: whiteSpace :: TokenParser st -> IndentCharParser st ()
+ Text.ParserCombinators.Parsec.IndentParser: type IndentCharParser st a = IndentParser Char st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: angles :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: anglesOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: anglesOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: braces :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: bracesOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: bracesOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: brackets :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: bracketsOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: bracketsOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: charLiteral :: TokenParser st -> IndentCharParser st Char
+ Text.ParserCombinators.Parsec.IndentParser.Token: colon :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: comma :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: commaOrNewLineSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: commaOrNewLineSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: commaSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: commaSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: decimal :: TokenParser st -> IndentCharParser st Integer
+ Text.ParserCombinators.Parsec.IndentParser.Token: dot :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: float :: TokenParser st -> IndentCharParser st Double
+ Text.ParserCombinators.Parsec.IndentParser.Token: hexadecimal :: TokenParser st -> IndentCharParser st Integer
+ Text.ParserCombinators.Parsec.IndentParser.Token: identifier :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: integer :: TokenParser st -> IndentCharParser st Integer
+ Text.ParserCombinators.Parsec.IndentParser.Token: lexeme :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: natural :: TokenParser st -> IndentCharParser st Integer
+ Text.ParserCombinators.Parsec.IndentParser.Token: naturalOrFloat :: TokenParser st -> IndentCharParser st (Either Integer Double)
+ Text.ParserCombinators.Parsec.IndentParser.Token: octal :: TokenParser st -> IndentCharParser st Integer
+ Text.ParserCombinators.Parsec.IndentParser.Token: operator :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: parens :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: parensOrBlock :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: parensOrLineFold :: TokenParser st -> IndentCharParser st a -> IndentCharParser st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: reserved :: TokenParser st -> String -> IndentCharParser st ()
+ Text.ParserCombinators.Parsec.IndentParser.Token: reservedOp :: TokenParser st -> String -> IndentCharParser st ()
+ Text.ParserCombinators.Parsec.IndentParser.Token: semi :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: semiOrNewLineSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: semiOrNewLineSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: semiSep :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: semiSep1 :: TokenParser st -> IndentCharParser st a -> IndentCharParser st [a]
+ Text.ParserCombinators.Parsec.IndentParser.Token: stringLiteral :: TokenParser st -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: symbol :: TokenParser st -> String -> IndentCharParser st String
+ Text.ParserCombinators.Parsec.IndentParser.Token: type IndentCharParser st a = IndentParser Char st a
+ Text.ParserCombinators.Parsec.IndentParser.Token: type TokenParser st = TokenParser (st, IndentState)
+ Text.ParserCombinators.Parsec.IndentParser.Token: whiteSpace :: TokenParser st -> IndentCharParser st ()
- Text.ParserCombinators.Parsec.IndentParser: Block :: Column -> IndentMode
+ Text.ParserCombinators.Parsec.IndentParser: Block :: IndentMode
- Text.ParserCombinators.Parsec.IndentParser: LineFold :: Line -> Column -> IndentMode
+ Text.ParserCombinators.Parsec.IndentParser: LineFold :: IndentMode
- Text.ParserCombinators.Parsec.IndentParser: type IndentParser tok st a = GenParser tok (IndentState st) a
+ Text.ParserCombinators.Parsec.IndentParser: type IndentParser tok st a = GenParser tok (st, IndentState) a

Files

+ ACK view
@@ -0,0 +1,3 @@+Martin Grabmueller <login:magr at the host cs dot tu-berlin dot de>+had send valuable bug reports after IndentParser-0.1 was uploaded to+HackageDB.
+ CHANGES view
@@ -0,0 +1,23 @@+Mon Oct 15 20:05:18 IST 2007  ppk@cse.iitk.ac.in+  * Reorganised and Nested indent Fix+  +  Bugs Fix+  	* Serious trouble when indentation structures are+  	nested. Hopefully fixed.+  Reorganisation+  	* All state manipulation parsers are moved into the+  	module IndentParser.Prim which is hidden.+  	* IndentToken renamed to IndentParser.Token+  	* Redefined parser state of indent parser.+  	++Mon Oct  8 10:22:13 IST 2007  ppk@cse.iitk.ac.in+  tagged IndentParser-0.1++Mon Oct  8 10:19:27 IST 2007  ppk@cse.iitk.ac.in+  * Initial Version+  +  Haskell modules to construct Indentation based syntactic structures.+  How to Install: via Cabal. Suggestion and bug reports are welcome+  (have a glance at TODO).+  
IndentParser.cabal view
@@ -1,8 +1,8 @@ Name:	IndentParser-Version: 0.1+Version: 0.2 License: GPL License-File: gplv3-Maintainer:login id is ppk and host is cse dot iitk dot ac dot in+Maintainer:login:ppk host:cse dot iitk dot ac dot in Author: Piyush P Kurur Homepage: http://www.cse.iitk.ac.in/~ppk Category: Parsing@@ -18,5 +18,6 @@ 	for programming languages. Exposed-modules:  	Text.ParserCombinators.Parsec.IndentParser-	Text.ParserCombinators.Parsec.IndentToken-Extra-Source-Files: TODO+	Text.ParserCombinators.Parsec.IndentParser.Token+Other-modules:	Text.ParserCombinators.Parsec.IndentParser.Prim+Extra-Source-Files: TODO ACK CHANGES
Text/ParserCombinators/Parsec/IndentParser.hs view
@@ -47,6 +47,18 @@ Haskell as well.  +The module exports three combinators are @'indentParser'@, @'block'@+and @'lineFold'@.  To construct parsers for indentation based grammars+one typically applies the @'indentParser'@.  A block can then be+parsed using the combinator @'block'@ and a line fold using+@'lineFold'@. Generating indentation aware tokenisers could be tricky.+Given a language description via the+'Text.ParserCombinators.Parsec.Language.LanguageDef' record use module+@'Text.ParserCombinators.Parsec.IndentParser.Token'@ to generate its+tokeiser (this will apply @'indentParser'@ on all tokenisers and then+the user can forget about @'indentParser'@ combinator).++ Warning:  Internally indentations are implemented using Parser states. If one@@ -61,34 +73,19 @@  module Text.ParserCombinators.Parsec.IndentParser     (-                    -- * Parser type-+                    -- * Parser type.                     IndentParser,-                    -- * Parser Combinators.-                    -- $combinators+                    IndentCharParser,+                    IndentMode(..),                     indentParser,                     noIndent, block, lineFold,                     betweenOrBlock, betweenOrLineFold,-                    -- * Primitive Parsers-                    -- $prim-                    IndentMode(..),-                    IndentState, state, indentMode,-                    saveIndentMode,-                    getIndentMode, setIndentMode,                     -- * User state manipulation.-                    -- $state                     getState, setState,-                    -- * Testing and Running.-                    -- $run-                    runParser, parseTest,-                    ---) where---+                    -- * Running and testing.+                    runParser, parseTest --- The functions @getState@ @setState@ and parseTest for indentation--- Parsers are exported by this module. Hence they are hidden.+) where   import Text.ParserCombinators.Parsec hiding (@@ -98,69 +95,49 @@                                              runParser                                             ) + import Text.ParserCombinators.Parsec.Pos-import qualified Text.ParserCombinators.Parsec.Prim as PP-import Control.Monad(fmap)+import Text.ParserCombinators.Parsec.IndentParser.Prim -getStatePrim = PP.getState-setStatePrim = PP.setState-runParserPrim = PP.runParser +-- Some comparisons of indentations. -{-|  -  An indentation aware parser. The parser should be of this type to-  make it possible to parse indentation based grammatical structure.+indentGT :: SourcePos -> SourcePos -> Bool+indentGT pos1 pos2 = sourceColumn pos1 > sourceColumn pos2+indentGE pos1 pos2 = sourceColumn pos1 >= sourceColumn pos2+indentEq pos1 pos2 = sourceColumn pos1 == sourceColumn pos2 --} +                -type IndentParser tok st a = GenParser tok (IndentState st) a --{- $combinators--The module exports three combinators are @'indentParser'@, @'block'@-and @'lineFold'@.  To construct parsers for indentation based grammars-one typically applies the @'indentParser'@ to all tokenisers. In-conjunction with @'Text.ParserCombinators.Parsec.Token'@ module, one-would want to apply indentParser to all the fields of the-'Text.ParserCombinators.Parsec.Token.TokenParser' record except-@'Text.ParserCombinators.Parsec.Token.whiteSpace'@. A block can then-be parsed using the combinator @'block'@ and a line fold using-@'lineFold'@. To generate indentation aware tokeniser from the-corresponding 'Text.ParserCombinators.Parsec.Language.LanguageDef'-record see the module @'Text.ParserCombinators.Parsec.IndentToken'@.-+{-|  +  The combinator indentParser makes its input parser indentation+  aware. Usually one would want to make all the tokenisers indentation+  aware.   -}    -{-|  -  The combinator indentParser makes its input parser indentation-  aware. Usually one would want to make all the tokenisers indentation-  aware. ---} indentParser :: IndentParser tok st a -> IndentParser tok st a indentParser p = do indMode <- getIndentMode                     case indMode of-                      NoIndent -> p   -- -                      Block c  -> blockP c p-                      LineFold l c -> lineP l c p-    where blockP c p   = do col <- column-                            if col >= c then p else pzero -          lineP l c p = do col <- column-                           if col > c then p else -                               do ln <- line-                                  if ln == l then p else pzero--               +                      NoIndent -> p+                      Block    -> inBlockMode p+                      LineFold -> inLineFoldMode p+    where inBlockMode    p = do curCol <- column+                                indCol <- indentColumn+                                if curCol >= indCol then p else pzero +          inLineFoldMode p = do curPos <- getPosition+                                oldPos <- getIndentPos+                                if curPos `indentGT` oldPos +                                       || curPos == oldPos then p else pzero   {-|@@ -174,220 +151,229 @@ -}  noIndent :: IndentParser tok st a -> IndentParser tok st a-noIndent p = saveIndentMode $ do {setIndentMode NoIndent; p}-                                ---{-|+noIndent p = saveIndent (p `withIndentMode` NoIndent) -The parser @'block' p@ parses a /block/ of @p@ with the block-indentation being the current column number.+   --}  -+{-|+The parser @'block' p@ parses a /block/ of @p@.+-}  block :: IndentParser tok st a -> IndentParser tok st a-block p = saveIndentMode $ do col <- column-                              setIndentMode $ Block col-                              p-                + {-|  -The parser @lineFold p@ parses a folded line of @p@. The current line-is the starting line. The indentation of the line depends on where in-the source we are. If we are in a block then the indentation is the-indentation of the block. Otherwise the current column is the-indentation.+The parser @lineFold p@ parses a folded line of @p@.  -}- lineFold :: IndentParser tok st a -> IndentParser tok st a-lineFold p = saveIndentMode $ do ln <- line-                                 indMode <- getIndentMode-                                 case indMode of-                                   NoIndent -> do col <- column-                                                  setIndentMode $ LineFold ln col-                                   Block c  -> setIndentMode $ LineFold ln c-                                 p  --{-|--  The parser @betweenOrBlock open close p@ parses @p@ between @open@-and @close@. If open is matched @p@ is parsed in 'NoIndent' mode otherwise-a block @p@ is parsed in 'Block' mode. For eg. the parser for parsing-haskell where clause would look like--> whereClause = do reserved where; betweenOrBlock bindings+{- --}-betweenOrBlock :: IndentParser tok st open -> -                  IndentParser tok st close ->-                  IndentParser tok st a -> -                  IndentParser tok st a+The complication in the definition of block and lineFold is in the+handling of nested indentation. We now describe the rules for nesting+of blocks and lineFolds. -betweenOrBlock left right p = do left; x <- noIndent p; right; return x-                              <|> block p+(1) A block or a lineFold can start any where in a NoIndent chunk+(2) A block inside a lineFold or block has to be indented +    more than the previous indentation, otherwise it is an empty block. -{-|+(3) A lineFold inside a lineFold has to be indented more than+    the previous indentation otherwise it is an empty lineFold+(4) A lineFold inside a block should be indented at least as much+    as the previous indentation otherwise it is an empty lineFold. -Similar to betweenOrBlock but uses lineFold instead of block.+Based on these rules we define the parsers isEmptyBlock and+isEmptyLineFold.  -}-betweenOrLineFold :: IndentParser tok st open -> -                     IndentParser tok st close -> -                     IndentParser tok st a ->-                     IndentParser tok st a-betweenOrLineFold left right p = do left; x <- noIndent p; right; return x-                                 <|> lineFold p  --- | This returns the current line number+isEmptyBlock = do indm <- getIndentMode+                  case indm of+                    NoIndent -> return False+                    _        -> do curCol <- column+                                   indCol <- indentColumn+                                   return (curCol <= indCol) -line :: GenParser tok st Line-line   = fmap sourceLine   getPosition+isEmptyLineFold = do indm <- getIndentMode+                     case indm of+                       NoIndent -> return False+                       Block     -> do curCol <- column+                                       indCol <- indentColumn+                                       return (curCol < indCol)+                       LineFold  -> do curCol <- column+                                       indCol <- indentColumn+                                       return (curCol <= indCol) --- | This returns the current column number -column :: GenParser tok st Column-column = fmap sourceColumn getPosition+{-  +  If the current block (or line fold) is empty we cannot outright+  reject because the argument parser @p@ could be some parser that+  accepts an empty string.  So the stratgy we use is that in this case+  we set the indentation position to be one more than the current+  position. So this will gurantee that @p@, if it is a valid+  indentation parser will see empty input. +-} -{- $prim  -We now describe the primitives that are used to build the combinators-@block@, @noIndent@ and @lineFold@. An indentation parser can be in-one of the following modes: -[@NoIndent@] In this mode the parser ignores all indentation-constraints. All tokens regardless of their indentation are accepted.+setPosBlock = do test <- isEmptyBlock+                 pos <- if test then nextPos else getPosition+                 setIndentPos pos+                   -[@Block c@] In this mode a parser accepts only tokens which have-indentation at least @c@. A parser parsing a block that is indented-more than @c@ columns will be this mode. +setPosLineFold = do test <- isEmptyLineFold+                    pos <- if test then nextPos else getPosition+                    setIndentPos pos -[@LineFold l c@] In this mode a parser accepts tokens as long as it is-in the current line or is indented more than @c@. When parsing a-folded line starting at @l@ and indentation more than @c@ the parser-will be in this mode. +{- +   Also a block p (lineFold p) should contain p and nothing else. So+   when we are done with it we need to ensure that there is no more+   input. This is done using the parser eobReached (eolfReached)  -} -data IndentMode  = NoIndent   -                 | Block Column-                 | LineFold Line Column deriving (Show, Eq)-                --- | This parser returns the current indentation mode. --getIndentMode :: IndentParser tok st IndentMode-getIndentMode = fmap indentMode getStatePrim+eobReached :: IndentParser tok st ()+eobReached = do indCol <- indentColumn+                col    <- column+                if indCol <= col then (endOfInput <|> prematureEnd)+                   else return ()+    where prematureEnd = do indPos <- getIndentPos+                            pos <- getPosition+                            fail ("premature block termination " +++                                     "started at " ++ show indPos +++                                     " and ended at " ++ show pos)+              +                  --- | This parser sets the current indentation mode--setIndentMode :: IndentMode -> IndentParser tok st ()-setIndentMode ind  = do indState <- getStatePrim-                        PP.setState $ indState {indentMode = ind}+eolfReached = do indCol <- indentColumn+                 col  <- column+                 if indCol < col  then (endOfInput <|> prematureEnd)+                    else return ()+    where prematureEnd = do indPos <- getIndentPos+                            pos <- getPosition+                            fail ("premature block termination " +++                                     "started at " ++ show indPos +++                                     " and ended at " ++ show pos)+                -{-| --The parser @saveIndentMode p@ saves the current indentation mode and-returns the result of running @p@. It restores back the old-indentation once @p@ has finished executing.-+{-+  Having defined these parsers we can now define the parser block and+  lineFold. -}-saveIndentMode :: IndentParser tok st a -> IndentParser tok st a-saveIndentMode p = do indMode <- getIndentMode-                      x <- p-                      setIndentMode indMode-                      return x+block p = saveIndent $ do setPosBlock+                          x <- p `withIndentMode` Block+                          eobReached+                          return x  +lineFold p = saveIndent $ do setPosLineFold+                             x <- p `withIndentMode` LineFold+                             eolfReached+                             return x -{- $state  -Indentation awareness is built into indentation parser by using these-parser states.  To distinguish it from the actual user defined state we-call the former the indentation state and the later the user state.-+                   +{-| +  The parser @betweenOrBlock open close p@ parses @p@ between @open@+and @close@. If open is matched @p@ is parsed in 'NoIndent' mode otherwise+a block @p@ is parsed in 'Block' mode. For eg. the parser for parsing+haskell where clause would look like +> whereClause = do reserved where; betweenOrBlock bindings  -} --- | The parser state used by Indentation Parsers.--data IndentState st = IndentState {-                                   state :: st, -- the actual state-                                   indentMode :: IndentMode -- the indentation mode-                                  } ------ | Gets the current user state. Use this instead of the one exported--- from Parsec module--getState  :: IndentParser tok st st-getState  = fmap state getStatePrim+betweenOrBlock :: IndentParser tok st open -> +                  IndentParser tok st close ->+                  IndentParser tok st a -> +                  IndentParser tok st a +betweenOrBlock left right p = do left; x <- noIndent p; right; return x+                              <|> block p -{-| +{-| -This parser sets the current state of the parser to the given input-state.  Use this function instead of the one exported by the parsec-library.+Similar to betweenOrBlock but uses lineFold instead of block.  -}+betweenOrLineFold :: IndentParser tok st open -> +                     IndentParser tok st close -> +                     IndentParser tok st a ->+                     IndentParser tok st a+betweenOrLineFold left right p = do left; x <- noIndent p; right; return x+                                 <|> lineFold p -setState :: st -> IndentParser tok st ()-setState st = do indState <- getStatePrim-                 PP.setState indState {state = st}   +-- Some position parsers.  +-- | This returns the current line number -{- $run+line :: GenParser tok st Line+line   = fmap sourceLine   getPosition -  -The most generic way to run an IndentParser. Use @parseTest@ for-testing your parser instead.+-- | This returns the current column number --}-runParser :: IndentParser tok st a  -- ^ the parser to be run-             -> st  -- ^ the initial state -             -> IndentMode -- ^ the indentation mode-             -> SourceName -- ^ the source file name-             -> [tok]  -- ^ the list of tokens-             -> Either ParseError a -- ^ the result of parsing+column :: GenParser tok st Column+column = fmap sourceColumn getPosition -runParser p st imode = runParserPrim p (IndentState st imode)+indentColumn :: IndentParser tok st Column+indentColumn = fmap sourceColumn getIndentPos  +nextPos :: GenParser tok st SourcePos+nextPos = do pos <- getPosition+             return (pos `incSourceColumn` 1)   {-|  -This is the function analogues to parseTest of the Parsec module.-Given an indent parser @p :: IndentParser tok () a@ and a list of-tokens it runs the parser and prints the result.+The parser @saveIndent p@, saves the current indentation, runs @p@,+and restores the indentation back.  -} +saveIndent :: IndentParser tok st a -> IndentParser tok st a+saveIndent p = do indMode <- getIndentMode+                  indPos  <- getIndentPos+                  x <- p+                  setIndentMode indMode+                  setIndentPos  indPos+                  return x+    +withIndentMode :: IndentParser tok st a -> IndentMode -> IndentParser tok st a+withIndentMode p indm = do setIndentMode indm+                           p+                -parseTest :: Show a => IndentParser tok () a -> [tok] -> IO ()-parseTest p input = case result of-                      Left err  -> do putStr "Error"; print err-                      Right a   -> do print a-    where result = runParser p () NoIndent "" input+{-  +When an block or a lineFold is to be entered care must be taken to set+the indentation position. If the current indentation mode is NoIndent+then just set the current position. In case we are already inside+a line fold or a block then the indentation should be the max of+current position and previous indentation position + 1. The reason+we do not outright reject is because block p could be  +-}+++endOfInput = do ins <- getInput+                case ins of+                  [] -> return ()+                  _  -> pzero
+ Text/ParserCombinators/Parsec/IndentParser/Prim.hs view
@@ -0,0 +1,159 @@+{-|+++This module contains the primitve indentation parsers. In most of+the case one would not want to use the functions of this module.+++-}++++module Text.ParserCombinators.Parsec.IndentParser.Prim+    (+     -- * Types+     IndentParser,+     IndentCharParser,+     IndentMode(..),+     IndentState,+     -- * Geting indentation modes and position.+     getIndentMode, setIndentMode,+     getIndentPos, setIndentPos,+     -- * User state manipulation.+     getState, setState,+     -- * Runing and testing+     runParser, parseTest+    +     ) where                 ++import  Text.ParserCombinators.Parsec hiding+    (getState, setState, parseTest, runParser)+import qualified Text.ParserCombinators.Parsec.Prim as PP+import Control.Monad(fmap)+import Text.ParserCombinators.Parsec.Pos(initialPos)++-- | The mode of the indentation parser.++data IndentMode  = NoIndent   -- ^ Ignore indentation+                 | Block      -- ^ In block mode+                 | LineFold   -- ^ In line fold mode+                   deriving Eq+              +++{-|++Indentation awareness is built into indentation parser by using these+parser states.  To distinguish it from the actual user defined state we+call the former the indentation state and the later the user state.+++-}++++data IndentState  = IndentState {+                                   indentMode  :: IndentMode,+                                   -- the indentation mode.+                                   indentPos :: SourcePos+                                   -- The position where the current +                                   -- indentation started.+                                  }++++{-| +  An indentation aware parser.+-} +++type IndentParser tok st a = GenParser tok (st, IndentState) a+type IndentCharParser st a = IndentParser Char st a++-- | Gets the current user state.+getState  :: IndentParser tok st st+-- | Gets the current indentation state.+getIndentState :: IndentParser tok st IndentState+-- | Gets the current identation mode.+getIndentMode :: IndentParser tok st IndentMode+-- | Gets the position where the last indentation started.+getIndentPos :: IndentParser tok st SourcePos+++getState        = fmap fst getStatePrim+getIndentState  = fmap snd getStatePrim+getIndentMode   = fmap indentMode getIndentState+getIndentPos     = fmap indentPos  getIndentState+++++-- | Sets the user state.+setState :: st -> IndentParser tok st ()+-- | Sets the current indentation.+setIndentPos :: SourcePos -> IndentParser tok st ()+-- | Sets the current indentation mode.+setIndentMode :: IndentMode -> IndentParser tok st ()+-- | Sets the indentation state of the parser.+setIndentState :: IndentState -> IndentParser tok st ()++setState       st   = do indst    <- getIndentState+                         setStatePrim (st,indst)+setIndentState indst = do st  <- getState+                          setStatePrim (st, indst)++setIndentPos   sp   = do indst <- getIndentState+                         setIndentState $ indst {indentPos = sp}+setIndentMode indm  = do indst <- getIndentState+                         setIndentState $ indst {indentMode = indm}+++++{- $run++  +The most generic way to run an IndentParser. Use @parseTest@ for+testing your parser instead.++-}++runParser :: IndentParser tok st a  -- ^ the parser to be run+             -> st  -- ^ the initial state +             -> IndentMode -- ^ the indentation mode+             -> SourceName -- ^ the source file name+             -> [tok]  -- ^ the list of tokens+             -> Either ParseError a -- ^ the result of parsing++runParser p st imode sname = runParserPrim p (st, istate) sname+    where istate = IndentState { indentPos = initialPos sname,+                                 indentMode = imode+                               }+++++{-| ++This is the function analogues to parseTest of the Parsec module.+Given an indent parser @p :: IndentParser tok () a@ and a list of+tokens it runs the parser and prints the result.++-}+++parseTest :: Show a => IndentParser tok () a -> [tok] -> IO ()+parseTest p input = case result of+                      Left err  -> do putStr "Error"; print err+                      Right a   -> do print a+    where result = runParser p () NoIndent "" input++++++++getStatePrim = PP.getState+setStatePrim = PP.setState+runParserPrim = PP.runParser
+ Text/ParserCombinators/Parsec/IndentParser/Token.hs view
@@ -0,0 +1,613 @@+{-# OPTIONS_GHC -fglasgow-exts #-}++{-++Haskell module for constructing indentation aware parser combinators.+Copyright (C) 2007  Piyush P Kurur, <http://www.cse.iitk.ac.in/~ppk>++This program is free software: you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation, either version 3 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program.  If not, see <http://www.gnu.org/licenses/>.+  ++-}++{-|++A module for constructing indentation aware tokeniser that can be used+in conjuction with @'Text.ParserCombinators.Parsec.Token'@. All the+combinator takes a @'Text.ParserCombinators.Parsec.Token.TokenParser'@+as its first argument. For every field @foo@ of+@'Text.ParserCombinators.Parsec.Token.TokenParser'@ this module+exports a combinator @foo@. To define a tokeniser for an indentation+based language a user first defines the appropriate+@'Text.ParserCombinators.Parsec.Language.LanguageDef'@ record, applies+the combinator @'Text.ParserCombinators.Parsec.Token.makeTokenParser'@+to get a @'Text.ParserCombinators.Parsec.Token.TokenParser'@ record+say @tokP@ and then, instead of selecting the field @foo@ of @tokP@,+applies the combinator @foo@ exported from this module to @tokP@. The+semantics of the combinator @foo@ is essentially same as that of the+field @foo@ of @'Text.ParserCombinators.Parsec.Token.TokenParser'@ but+the returned parsers are indentation aware. Apart from these there are+certain new combinators that are defined specifically for parsing+certain indentation based syntactic constructs. (We have not defined+squares use brackets instead)+++There are two important classes of parser combinator exported by this+module:++[Grouping Parser Combinator] A grouping parser combinator takes as+input a parser say @p@ and returns a parser that parses @p@ between+two /grouping delimiters/.  There are three flavours of grouping+parsers: @foo@, @fooOrBlock@ and @fooOrLineFold@ where @foo@ can be+one of @angles@, @braces@, @parens@, @brackets@. To illustrate we take+@foo@ to be @braces@. The parser @'braces' tokP p@ parses @p@+delimited by '{' and '}'. In this case @p@ does not care about+indentation (i.e. the parser @p@ is run in+@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode). The+parser @'bracesOrBlock' tokP p@ is like @braces tokP p@ but if no+explicit delimiting braces are given parses @p@ within an indented+block. Similarly @'bracesOrLineFold' tokP p@ parses @p@ between '{'+and '}' and uses line fold when no explicit braces are given. These+can be two varients can be defined as follows++> bracesOrBlock tokP p    = braces tokP p <|> block p+> bracesOrLineFold tokP p = braces tokP p <|> lineFold p+++[Seperator Parser Combinator] A seperator parser combinator 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@, @fooOrNewLineSep@ and @fooOrNewLineSep1@, 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.ParserCombinators.Parsec.Language as L+>   import qualified Text.ParserCombinators.Parsec.Toke as T+>   import qualified Text.ParserCombinator.Parsec.IndentToken as IT+++>   tokP = T.makeTokenParser L.haskellDef+>   semiOrNewLineSep = IT.semiOrNewLineSep tokP+>   bracesOrBlock = IT.bracesOrBlock tokP+>   identifier = IT.identifier tokP+>   ....+>   symbol = IT.symbol tokP++>   binding = semiOrNewLineSep bind+>   bind    = do id <- identifier+>                symbol (char '=')+>                e <- expr+>                return (id,e)+>  whereClause = do reserved "where"; braceOrBlock binding+++-}+++module Text.ParserCombinators.Parsec.IndentParser.Token+    ( +     -- * Types+     IndentCharParser,+     TokenParser,+     -- * Combinators+     identifier, reserved,+     operator, reservedOp,+     charLiteral, stringLiteral,+     natural, integer, float, naturalOrFloat,+     decimal, hexadecimal, octal,+     semi, colon, dot, comma,+     lexeme, symbol, whiteSpace,+     -- * Separator parser combinators+     semiSep, semiSep1, commaSep, commaSep1,+     semiOrNewLineSep, semiOrNewLineSep1,+     commaOrNewLineSep, commaOrNewLineSep1,+     -- * Grouping parser combinator+     parens,parensOrBlock, parensOrLineFold,+     braces, bracesOrBlock, bracesOrLineFold,+     angles, anglesOrBlock, anglesOrLineFold,+     brackets, bracketsOrBlock, bracketsOrLineFold+    ) where++import Text.ParserCombinators.Parsec hiding (+                                             getState,+                                             setState,+                                             parseTest,+                                             runParser+                                            )++import qualified Text.ParserCombinators.Parsec.Token as T+import qualified Text.ParserCombinators.Parsec.Language as L+import Text.ParserCombinators.Parsec.IndentParser+import Text.ParserCombinators.Parsec.IndentParser.Prim (IndentState)+++type TokenParser st = T.TokenParser (st,IndentState)++++++{-| Indentation aware parser to match a valid identifier of the+language.  -}++identifier :: TokenParser st -> IndentCharParser st String+identifier = indentParser . T.identifier+++{-| Indentation aware parser to match a reserved word of the language.+-}++reserved :: TokenParser st ->+            String  -- ^ The reserved word to be matched.+         -> IndentCharParser st ()+reserved tokP = indentParser . T.reserved tokP+++{-| The parser @reserved tokP keyword@ parses  the reserved word keyword.+ The string keyword should have been declared as a reserved word in the + @'Text.ParserCombinator.Parserc.Language.LanguageDef'@+                    -record.  -}++operator :: TokenParser st -> IndentCharParser st String+operator = indentParser . T.operator++{-|+  Indentation aware parser to match a reserved operator of the language.+-}++reservedOp :: TokenParser st ->+              String+              -- ^ The reserved operator to be matched. Should have+              -- been declared as a reserved operator in the +              -- @'Text.ParserCombinator.Parserc.Language.LanguageDef'@+              -- record.+              -> IndentCharParser st ()++reservedOp tokP = indentParser . 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 :: TokenParser st -> IndentCharParser st Char+charLiteral = indentParser . 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 :: TokenParser st -> IndentCharParser st String+stringLiteral = indentParser . T.stringLiteral+++{-| Indentation aware parser to match a natural number.  -}++natural :: TokenParser st -> IndentCharParser st Integer+natural = indentParser . T.natural++{-|+  Indentation aware parser to match an integer.+-}++integer :: TokenParser st -> IndentCharParser st Integer+integer = indentParser . T.integer++{-| Indentation aware parser to match a floating point number.  -}++float :: TokenParser st -> IndentCharParser st Double +float = indentParser . T.float++{-| Indentation aware parser to match either a natural number or+Floating point number.  -}++naturalOrFloat :: TokenParser st+               -> IndentCharParser st (Either Integer Double)+naturalOrFloat = indentParser . T.naturalOrFloat++-- | Indentation aware parser to match an integer in decimal.+++decimal  :: TokenParser st -> IndentCharParser st Integer+decimal = indentParser . T.decimal++{-| Indentation aware parser to match an integer in hexadecimal.-}++hexadecimal :: TokenParser st -> IndentCharParser st Integer+hexadecimal = indentParser . T.hexadecimal ++{-| ++Indentation aware parser to match an integer in ocatal.++-}++octal  :: TokenParser st -> IndentCharParser st Integer+octal = indentParser . T.octal+++{-| Matches a semicolon and returns ';'.  -}+++semi :: TokenParser st -> IndentCharParser st String+semi = indentParser . T.semi++{-| Matches a comma and returns ",".  -}++comma :: TokenParser st -> IndentCharParser st String+comma = indentParser . T.comma++{-| Matches a colon and returns ":". -}+colon :: TokenParser st -> IndentCharParser st String+colon = indentParser . T.colon++{-| Matches a dot and returns "." -}+dot   :: TokenParser st -> IndentCharParser st String+dot = indentParser . T.dot+++{-| Given an indentation aware parser @p@ as argument @semiSep tokP@+  returns a parser that parses zero or more occurances of @p@+  seperated by semicolon (';') -}++semiSep :: TokenParser st +        -> IndentCharParser st a +        -> IndentCharParser st [a]++semiSep tokP p = p `sepBy` semicolon+    where semicolon = semi tokP+++{-| Given an indentation aware parser @p@ as argument @semiSep1 tokP@+  returns a parser that parses one or more occurances of @p@ seperated+  by semicolon (';') -}+++semiSep1 :: TokenParser st +         -> IndentCharParser st a -- ^ The input Parser+         -> IndentCharParser st [a]++semiSep1 tokP p = p `sepBy1` semicolon+    where semicolon = semi tokP++++{-| Given an indentation aware parser @p@ as argument @commaSep tokP@+  returns a parser that parses zero or more occurances of @p@+  seperated by comma (',') -}++commaSep :: TokenParser st+         -> IndentCharParser st a -- ^ The input Parser+         -> IndentCharParser st [a]++commaSep tokP p = p `sepBy` virgule+    where virgule = comma tokP+++++{-| Given an indentation aware parser @p@ as argument @commaSep1 tokP@+  returns a parser that parses one or more occurances of @p@ seperated+  by comma (',') -}+++commaSep1 :: TokenParser st+         -> IndentCharParser st a -- ^ The input Parser+         -> IndentCharParser st [a]++commaSep1 tokP p = p `sepBy1` virgule+    where virgule = comma tokP+++++{-| ++Given an indentation aware parser @p@ as argument @semiOrNewLineSep1+tokP@ returns a parser that parses one or more occurances of @p@+seperated by either semicolons (';') or newline. To seperate multiple+occurance of @p@ in the same line use an explicit semicolon (';').++-}++semiOrNewLineSep1 :: TokenParser st+                  -> IndentCharParser st a -- ^ The input Parser+                  -> IndentCharParser st [a]++semiOrNewLineSep1 tokP p = do xs <- lineFold $ semiSep1 tokP p+                              rest <- semiOrNewLineSep tokP p+                              return (xs++rest)++++{-| ++Given an indentation aware parser @p@ as argument @semiOrNewLineSep+tokP@ returns a parser that parses zero or more occurances of @p@+seperated by either semicolons (';') or newlines. To seperate multiple+occurance of @p@ in the same line use an explicit semicolon (';').++-}++semiOrNewLineSep :: TokenParser st+                 -> IndentCharParser st a -- ^ The input Parser+                 -> IndentCharParser st [a]++semiOrNewLineSep tokP p =  do xs <- lineFold $ semiSep tokP p+                              case xs of+                                [] -> return []+                                _  -> do rest <- semiOrNewLineSep tokP p+                                         return (xs++rest)++++++++{-| ++Given an indentation aware parser @p@ as argument @commaOrNewLineSep1+tokP@ returns a parser that parses one or more occurances of @p@+seperated by either comma (',') or newline. To seperate multiple+occurance of @p@ in the same line use an explicit comma (',').++-}++commaOrNewLineSep1 :: TokenParser st+                  -> IndentCharParser st a -- ^ The input Parser+                  -> IndentCharParser st [a]++commaOrNewLineSep1 tokP p = do xs <- lineFold $ commaSep1 tokP p+                               rest <- commaOrNewLineSep tokP p+                               return (xs++rest)++++{-| ++Given an indentation aware parser @p@ as argument @commaOrNewLineSep+tokP@ returns a parser that parses zero or more occurances of @p@+seperated by either comma (',') or newlines. To seperate multiple+occurance of @p@ in the same line use an explicit comma (',').++-}++commaOrNewLineSep :: TokenParser st+                 -> IndentCharParser st a -- ^ The input Parser+                 -> IndentCharParser st [a]++commaOrNewLineSep tokP p = do xs <- lineFold $ commaSep tokP p+                              case xs of+                                [] -> return []+                                _  -> do rest <- commaOrNewLineSep tokP p+                                         return (xs++rest)++++++{-|++The parser @parens tokP p@ parses @p@ between '(' and ')'. The parser+@p@ does not care about indentation i.e. @p@ is run in+@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.++-}++parens     :: TokenParser st ->+              IndentCharParser st a -- ^ The input Parser+           -> IndentCharParser st a++parens tokP p = between (symbol tokP "(") (symbol tokP ")") (noIndent p)++{-| ++Similar to @'parens'@ but when no explicit '(' and ')' are given,+groups @p@ by block indentation.++-}++parensOrBlock :: TokenParser st -> +                 IndentCharParser st a -- ^ The input parser+              -> IndentCharParser st a++parensOrBlock tokP p = parens tokP p <|> block p++++{-| ++Similar to @'parens'@ but when no explicit '(' and ')' are given,+groups @p@ by a line fold.++-}+parensOrLineFold :: TokenParser st -> +                    IndentCharParser st a -- ^ The input parser+                 -> IndentCharParser st a++parensOrLineFold tokP p = parens tokP p <|> lineFold p+++{-|++The parser @braces tokP p@ parses @p@ between '{' and '}'. The parser+@p@ does not care about indentation i.e. @p@ is run in+@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.++-}++braces     :: TokenParser st ->+              IndentCharParser st a -- ^ The input Parser+           -> IndentCharParser st a++braces tokP p = between (symbol tokP "{") (symbol tokP "}") (noIndent p)++++{-| ++Similar to @'braces'@ but when no explicit '{' and '}' are given,+groups @p@ by block indentation.++-}+bracesOrBlock :: TokenParser st -> +                 IndentCharParser st a -- ^ The input parser+              -> IndentCharParser st a++bracesOrBlock tokP p = braces tokP p <|> block p+++{-| ++Similar to @'braces'@ but when no explicit '{' and '}' are given,+groups @p@ by a line fold.++-}++bracesOrLineFold :: TokenParser st -> +                    IndentCharParser st a -- ^ The input parser+                 -> IndentCharParser st a++bracesOrLineFold tokP p = braces tokP p <|> lineFold p+++{-|++The parser @angles tokP p@ parses @p@ between angles. The parser @p@+does not care about indentation i.e. @p@ is run in+@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.++-}++angles     :: TokenParser st ->+              IndentCharParser st a -- ^ The input Parser+           -> IndentCharParser st a++angles tokP p = between (symbol tokP "<") (symbol tokP ">") (noIndent p)++++{-| ++Similar to @'angles'@ but when no explicit angles are given, groups+@p@ by block indentation.++-}++anglesOrBlock :: TokenParser st -> +                 IndentCharParser st a -- ^ The input parser+              -> IndentCharParser st a++anglesOrBlock tokP p = angles tokP p <|> block p+++{-| ++Similar to @'angles'@ but when no explicit angles are given, groups+@p@ by a line fold.++-}++anglesOrLineFold :: TokenParser st -> +                    IndentCharParser st a -- ^ The input parser+                 -> IndentCharParser st a++anglesOrLineFold tokP p = angles tokP p <|> lineFold p++++{-|++The parser @brackets tokP p@ parses @p@ between '[' and ']'. The+parser @p@ does not care about indentation i.e. @p@ is run in+@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.++-}++brackets     :: TokenParser st ->+                IndentCharParser st a -- ^ The input Parser+             -> IndentCharParser st a++brackets tokP p = between (symbol tokP "[") (symbol tokP "]") (noIndent p)++++{-| ++Similar to @'brackets'@ but when no explicit '[' and ']' are given,+groups @p@ by block indentation.++-}+bracketsOrBlock :: TokenParser st -> +                   IndentCharParser st a -- ^ The input parser+                -> IndentCharParser st a++bracketsOrBlock tokP p = brackets tokP p <|> block p+++{-| ++Similar to @'brackets'@ but when no explicit '[' and ']' are given,+groups @p@ by a line fold.++-}++bracketsOrLineFold :: TokenParser st -> +                    IndentCharParser st a -- ^ The input parser+                 -> IndentCharParser st a++bracketsOrLineFold tokP p = brackets tokP p <|> lineFold p+++{-|++Indentation aware parser that is equvalent to string str.++-}++symbol     :: TokenParser st +           -> String +           -> IndentCharParser st String+symbol tokP = indentParser . T.symbol tokP+++{-| Creates a lexeme parser. The resultant parser skips trailing+spaces and is indentation aware.  -}++lexeme     :: TokenParser st +           -> IndentCharParser st a  -- ^ The input parser.+           -> IndentCharParser st a++lexeme tokP = indentParser . 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 :: TokenParser st -> IndentCharParser st ()+whiteSpace = T.whiteSpace 
− Text/ParserCombinators/Parsec/IndentToken.hs
@@ -1,601 +0,0 @@-{-# OPTIONS_GHC -fglasgow-exts #-}--{---Haskell module for constructing indentation aware parser combinators.-Copyright (C) 2007  Piyush P Kurur, <http://www.cse.iitk.ac.in/~ppk>--This program is free software: you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation, either version 3 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program.  If not, see <http://www.gnu.org/licenses/>.-  ---}--{-|--A module for constructing indentation aware tokeniser that can be used-in conjuction with @'Text.ParserCombinators.Parsec.Token'@.  All the-combinator takes a @'Text.ParserCombinators.Parsec.Token.TokenParser'@-as its first argument. For every field @foo@ of-@'Text.ParserCombinators.Parsec.Token.TokenParser'@ this module-exports a combinator @foo@. To define a tokeniser for an indentation-based language a user first defines the appropriate-@'Text.ParserCombinators.Parsec.Language.LanguageDef'@ record, applies-the combinator @'Text.ParserCombinators.Parsec.Token.makeTokenParser'@-to get a @'Text.ParserCombinators.Parsec.Token.TokenParser'@ record-say @tokP@ and then, instead of selecting the field @foo@ of @tokP@,-applies the combinator @foo@ exported from this module to @tokP@. The-semantics of the combinator @foo@ is essentially same as that of the-field @foo@ of @'Text.ParserCombinators.Parsec.Token.TokenParser'@ but-the returned parsers are indentation aware. Apart from these there are-certain new combinators that are defined specifically for parsing-certain indentation based syntactic constructs. (We have not defined-squares use brackets instead)---There are two important classes of parser combinator exported by this-module:--[Grouping Parser Combinator] A grouping parser combinator takes as-input a parser say @p@ and returns a parser that parses @p@ between-two /grouping delimiters/.  There are three flavours of grouping-parsers: @foo@, @fooOrBlock@ and @fooOrLineFold@ where @foo@ can be-one of @'angles'@, @'braces'@, @'parens'@, @'brackets'@ or To-illustrate we take @foo@ to be braces. The parser @braces tokP p@-parses @p@ delimited by '{' and '}'. In this case @p@ does not care-about indentation (i.e. the parser @p@ is run in-@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode). The-parser @'bracesOrBlock' tokP p@ is like @braces tokP p@ but if no-explicit delimiting braces are given parses @p@ within an indented-block. Similarly @'bracesOrLineFold' tokP p@ parses @p@ between '{'-and '}' and uses line fold when no explicit braces are given. These-can be two varients can be defined as follows--> bracesOrBlock tokP p =  braces tokP $ noIndent p <|> block p-> bracesOrLineFold tokP p = braces tokP $ noIndent p <|> lineFold p---[Seperator Parser Combinator] A seperator parser combinator 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@, @fooOrNewLineSep@ and @fooOrNewLineSep1@, 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.ParserCombinators.Parsec.Language as L->   import qualified Text.ParserCombinators.Parsec.Toke as T->   import qualified Text.ParserCombinator.Parsec.IndentToken as IT--->   tokP = T.makeTokenParser L.haskellDef->   semiOrNewLineSep = IT.semiOrNewLineSep tokP->   bracesOrBlock = IT.bracesOrBlock tokP->   identifier = IT.identifier tokP->   ....->   symbol = IT.symbol tokP-->   binding = semiOrNewLineSep bind->   bind    = do id <- identifier->                symbol (char '=')->                e <- expr->                return (id,e)->  whereClause = do reserved "where"; braceOrBlock binding----}---module Text.ParserCombinators.Parsec.IndentToken-    ( -     -- * Types-     IndentCharParser,-     LanguageDef,-     TokenParser,-     -- * Combinators-     identifier, reserved,-     operator, reservedOp,-     charLiteral, stringLiteral,-     natural, integer, float, naturalOrFloat,-     decimal, hexadecimal, octal,-     semi, colon, dot,-     lexeme, symbol, whiteSpace,-     -- * Separator parser combinators-     semiSep, semiSep1, commaSep, commaSep1,-     semiOrNewLineSep, semiOrNewLineSep1,-     commaOrNewLineSep, commaOrNewLineSep1,-     -- * Grouping parser combinator-     parens,parensOrBlock, parensOrLineFold,-     braces, bracesOrBlock, bracesOrLineFold,-     angles, anglesOrBlock, anglesOrLineFold,-     brackets, bracketsOrBlock, bracketsOrLineFold-    ) where--import Text.ParserCombinators.Parsec hiding (-                                             getState,-                                             setState,-                                             parseTest,-                                             runParser-                                            )--import qualified Text.ParserCombinators.Parsec.Token as T-import qualified Text.ParserCombinators.Parsec.Language as L-import Text.ParserCombinators.Parsec.IndentParser--type IndentCharParser st a = IndentParser Char st a-type LanguageDef st = L.LanguageDef (IndentState st)-type TokenParser st = T.TokenParser (IndentState st)-----{-| Indentation aware parser to match a valid identifier of the-language.  -}--identifier :: TokenParser st -> IndentCharParser st String-identifier = indentParser . T.identifier---{-| Indentation aware parser to match a reserved word of the language.--}--reserved :: TokenParser st ->-            String  -- ^ The reserved word to be matched.-         -> IndentCharParser st ()-reserved tokP = indentParser . T.reserved tokP---{-| The parser @reserved tokP keyword@ parses  the reserved word keyword.- The string keyword should have been declared as a reserved word in the - @'Text.ParserCombinator.Parserc.Language.LanguageDef'@-                    -record.  -}--operator :: TokenParser st -> IndentCharParser st String-operator = indentParser . T.operator--{-|-  Indentation aware parser to match a reserved operator of the language.--}--reservedOp :: TokenParser st ->-              String-              -- ^ The reserved operator to be matched. Should have-              -- been declared as a reserved operator in the -              -- @'Text.ParserCombinator.Parserc.Language.LanguageDef'@-              -- record.-              -> IndentCharParser st ()--reservedOp tokP = indentParser . 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 :: TokenParser st -> IndentCharParser st Char-charLiteral = indentParser . 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 :: TokenParser st -> IndentCharParser st String-stringLiteral = indentParser . T.stringLiteral---{-| Indentation aware parser to match a natural number.  -}--natural :: TokenParser st -> IndentCharParser st Integer-natural = indentParser . T.natural--{-|-  Indentation aware parser to match an integer.--}--integer :: TokenParser st -> IndentCharParser st Integer-integer = indentParser . T.integer--{-| Indentation aware parser to match a floating point number.  -}--float :: TokenParser st -> IndentCharParser st Double -float = indentParser . T.float--{-| Indentation aware parser to match either a natural number or-Floating point number.  -}--naturalOrFloat :: TokenParser st-               -> IndentCharParser st (Either Integer Double)-naturalOrFloat = indentParser . T.naturalOrFloat---- | Indentation aware parser to match an integer in decimal.---decimal  :: TokenParser st -> IndentCharParser st Integer-decimal = indentParser . T.decimal--{-| Indentation aware parser to match an integer in hexadecimal.-}--hexadecimal :: TokenParser st -> IndentCharParser st Integer-hexadecimal = indentParser . T.hexadecimal --{-| --Indentation aware parser to match an integer in ocatal.---}--octal  :: TokenParser st -> IndentCharParser st Integer-octal = indentParser . T.octal---{-| Matches a semicolon and returns ';'.  -}---semi :: TokenParser st -> IndentCharParser st String-semi = indentParser . T.semi--{-| Matches a comma and returns ",".  -}--comma :: TokenParser st -> IndentCharParser st String-comma = indentParser . T.comma--{-| Matches a colon and returns ":". -}-colon :: TokenParser st -> IndentCharParser st String-colon = indentParser . T.colon--{-| Matches a dot and returns "." -}-dot   :: TokenParser st -> IndentCharParser st String-dot = indentParser . T.dot---{-| Given an indentation aware parser @p@ as argument @semiSep tokP@-  returns a parser that parses zero or more occurances of @p@-  seperated by semicolon (';') -}--semiSep :: TokenParser st -        -> IndentCharParser st a -        -> IndentCharParser st [a]--semiSep tokP p = p `sepBy` semicolon-    where semicolon = semi tokP---{-| Given an indentation aware parser @p@ as argument @semiSep1 tokP@-  returns a parser that parses one or more occurances of @p@ seperated-  by semicolon (';') -}---semiSep1 :: TokenParser st -         -> IndentCharParser st a -- ^ The input Parser-         -> IndentCharParser st [a]--semiSep1 tokP p = p `sepBy1` semicolon-    where semicolon = semi tokP----{-| Given an indentation aware parser @p@ as argument @commaSep tokP@-  returns a parser that parses zero or more occurances of @p@-  seperated by comma (',') -}--commaSep :: TokenParser st-         -> IndentCharParser st a -- ^ The input Parser-         -> IndentCharParser st [a]--commaSep tokP p = p `sepBy` virgule-    where virgule = comma tokP-----{-| Given an indentation aware parser @p@ as argument @commaSep1 tokP@-  returns a parser that parses one or more occurances of @p@ seperated-  by comma (',') -}---commaSep1 :: TokenParser st-         -> IndentCharParser st a -- ^ The input Parser-         -> IndentCharParser st [a]--commaSep1 tokP p = p `sepBy1` virgule-    where virgule = comma tokP-----{-| --Given an indentation aware parser @p@ as argument @semiOrNewLineSep1-tokP@ returns a parser that parses one or more occurances of @p@-seperated by either semicolons (';') or newline. To seperate multiple-occurance of @p@ in the same line use an explicit semicolon (';').---}--semiOrNewLineSep1 :: TokenParser st-                  -> IndentCharParser st a -- ^ The input Parser-                  -> IndentCharParser st [a]--semiOrNewLineSep1 tokP p = do xs <- lineFold $ semiSep1 tokP p-                              rest <- semiOrNewLineSep tokP p-                              return (xs++rest)----{-| --Given an indentation aware parser @p@ as argument @semiOrNewLineSep-tokP@ returns a parser that parses zero or more occurances of @p@-seperated by either semicolons (';') or newlines. To seperate multiple-occurance of @p@ in the same line use an explicit semicolon (';').---}--semiOrNewLineSep :: TokenParser st-                 -> IndentCharParser st a -- ^ The input Parser-                 -> IndentCharParser st [a]--semiOrNewLineSep tokP p = semiOrNewLineSep1 tokP p <|> return []------{-| --Given an indentation aware parser @p@ as argument @commaOrNewLineSep1-tokP@ returns a parser that parses one or more occurances of @p@-seperated by either comma (',') or newline. To seperate multiple-occurance of @p@ in the same line use an explicit comma (',').---}--commaOrNewLineSep1 :: TokenParser st-                  -> IndentCharParser st a -- ^ The input Parser-                  -> IndentCharParser st [a]--commaOrNewLineSep1 tokP p = do xs <- lineFold $ semiSep1 tokP p-                               rest <- semiOrNewLineSep tokP p-                               return (xs++rest)----{-| --Given an indentation aware parser @p@ as argument @commaOrNewLineSep-tokP@ returns a parser that parses zero or more occurances of @p@-seperated by either comma (',') or newlines. To seperate multiple-occurance of @p@ in the same line use an explicit comma (',').---}--commaOrNewLineSep :: TokenParser st-                 -> IndentCharParser st a -- ^ The input Parser-                 -> IndentCharParser st [a]--commaOrNewLineSep tokP p = commaOrNewLineSep1 tokP p <|> return []----{-|--The parser @parens tokP p@ parses @p@ between '(' and ')'. The parser-@p@ does not care about indentation i.e. @p@ is run in-@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.---}--parens     :: TokenParser st ->-              IndentCharParser st a -- ^ The input Parser-           -> IndentCharParser st a--parens tokP p = between (symbol tokP "(") (symbol tokP ")") (noIndent p)--{-| --Similar to @'parens'@ but when no explicit '(' and ')' are given,-groups @p@ by block indentation.---}--parensOrBlock :: TokenParser st -> -                 IndentCharParser st a -- ^ The input parser-              -> IndentCharParser st a--parensOrBlock tokP p = parens tokP p <|> block p----{-| --Similar to @'parens'@ but when no explicit '(' and ')' are given,-groups @p@ by a line fold.---}-parensOrLineFold :: TokenParser st -> -                    IndentCharParser st a -- ^ The input parser-                 -> IndentCharParser st a--parensOrLineFold tokP p = parens tokP p <|> lineFold p---{-|--The parser @braces tokP p@ parses @p@ between '{' and '}'. The parser-@p@ does not care about indentation i.e. @p@ is run in-@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.---}--braces     :: TokenParser st ->-              IndentCharParser st a -- ^ The input Parser-           -> IndentCharParser st a--braces tokP p = between (symbol tokP "{") (symbol tokP "}") (noIndent p)----{-| --Similar to @'braces'@ but when no explicit '{' and '}' are given,-groups @p@ by block indentation.---}-bracesOrBlock :: TokenParser st -> -                 IndentCharParser st a -- ^ The input parser-              -> IndentCharParser st a--bracesOrBlock tokP p = braces tokP p <|> block p---{-| --Similar to @'braces'@ but when no explicit '{' and '}' are given,-groups @p@ by a line fold.---}--bracesOrLineFold :: TokenParser st -> -                    IndentCharParser st a -- ^ The input parser-                 -> IndentCharParser st a--bracesOrLineFold tokP p = braces tokP p <|> lineFold p---{-|--The parser @angles tokP p@ parses @p@ between angles. The parser @p@-does not care about indentation i.e. @p@ is run in-@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.---}--angles     :: TokenParser st ->-              IndentCharParser st a -- ^ The input Parser-           -> IndentCharParser st a--angles tokP p = between (symbol tokP "<") (symbol tokP ">") (noIndent p)----{-| --Similar to @'angles'@ but when no explicit angles are given, groups-@p@ by block indentation.---}--anglesOrBlock :: TokenParser st -> -                 IndentCharParser st a -- ^ The input parser-              -> IndentCharParser st a--anglesOrBlock tokP p = angles tokP p <|> block p---{-| --Similar to @'angles'@ but when no explicit angles are given, groups-@p@ by a line fold.---}--anglesOrLineFold :: TokenParser st -> -                    IndentCharParser st a -- ^ The input parser-                 -> IndentCharParser st a--anglesOrLineFold tokP p = angles tokP p <|> lineFold p----{-|--The parser @brackets tokP p@ parses @p@ between '[' and ']'. The-parser @p@ does not care about indentation i.e. @p@ is run in-@'Text.ParserCombinators.Parsec.IndentParser.NoIndent'@ mode.---}--brackets     :: TokenParser st ->-                IndentCharParser st a -- ^ The input Parser-             -> IndentCharParser st a--brackets tokP p = between (symbol tokP "[") (symbol tokP "]") (noIndent p)----{-| --Similar to @'brackets'@ but when no explicit '[' and ']' are given,-groups @p@ by block indentation.---}-bracketsOrBlock :: TokenParser st -> -                   IndentCharParser st a -- ^ The input parser-                -> IndentCharParser st a--bracketsOrBlock tokP p = brackets tokP p <|> block p---{-| --Similar to @'brackets'@ but when no explicit '[' and ']' are given,-groups @p@ by a line fold.---}--bracketsOrLineFold :: TokenParser st -> -                    IndentCharParser st a -- ^ The input parser-                 -> IndentCharParser st a--bracketsOrLineFold tokP p = brackets tokP p <|> lineFold p---{-|--Indentation aware parser that is equvalent to string str.---}--symbol     :: TokenParser st -           -> String -           -> IndentCharParser st String-symbol tokP = indentParser . T.symbol tokP---{-| Creates a lexeme parser. The resultant parser skips trailing-spaces and is indentation aware.  -}--lexeme     :: TokenParser st -           -> IndentCharParser st a  -- ^ The input parser.-           -> IndentCharParser st a--lexeme tokP = indentParser . 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 :: TokenParser st -> IndentCharParser st ()-whiteSpace = T.whiteSpace