1- module Text.Parsing.Indent (
2- -- $doc
3- -- * Types
4- IndentParser , runIndent ,
5- -- * Blocks
6- withBlock , withBlock' , block , block1 ,
7- -- * Indentation Checking
8- indented , indented' , sameLine , sameOrIndented , checkIndent , withPos ,
9- -- * Paired characters
10- -- indentBrackets, indentAngles, indentBraces, indentParens,
11- -- * Line Fold Chaining
12- -- | Any chain using these combinators must used with 'withPos'
13- indentAp , (<+/>), indentNoAp , (<-/>), indentMany , (<*/>), indentOp , (<?/>), Optional (..)
14- ) where
15-
16- import Prelude (class Monad , Unit , id , ap , const , ($), flip , unit , pure , (==), bind , (<=))
17- import Data.List (List (..), many )
18- import Data.Maybe (Maybe (..))
19-
1+ -- | This is purescript-port of Text.Parsing.Indent
2+ -- | <https://hackage.haskell.org/package/indents-0.3.3/docs/Text-Parsec-Indent.html>, 05.07.2016.
3+ -- | A module to construct indentation aware parsers. Many programming
4+ -- | language have indentation based syntax rules e.g. python and Haskell.
5+ -- | This module exports combinators to create such parsers.
6+ -- |
7+ -- | The input source can be thought of as a list of tokens. Abstractly
8+ -- | each token occurs at a line and a column and has a width. The column
9+ -- | number of a token measures is indentation. If t1 and t2 are two tokens
10+ -- | then we say that indentation of t1 is more than t2 if the column
11+ -- | number of occurrence of t1 is greater than that of t2.
12+ -- |
13+ -- | Currently this module supports two kind of indentation based syntactic
14+ -- | structures which we now describe:
15+ -- |
16+ -- | - **Block**
17+ -- |
18+ -- | A block of indentation /c/ is a sequence of tokens with
19+ -- | indentation at least /c/. Examples for a block is a where clause of
20+ -- | Haskell with no explicit braces.
21+ -- |
22+ -- | - **Line fold**
23+ -- |
24+ -- | A line fold starting at line /l/ and indentation /c/ is a
25+ -- | sequence of tokens that start at line /l/ and possibly continue to
26+ -- | subsequent lines as long as the indentation is greater than /c/. Such
27+ -- | a sequence of lines need to be /folded/ to a single line. An example
28+ -- | is MIME headers. Line folding based binding separation is used in
29+ -- | Haskell as well.
30+ module Text.Parsing.Indent
31+ ( IndentParser
32+ , runIndent
33+ , withBlock
34+ , withBlock'
35+ , block
36+ , block1
37+ , indented
38+ , indented'
39+ , sameLine
40+ , sameOrIndented
41+ , checkIndent
42+ , withPos
43+ , indentAp
44+ , (<+/>)
45+ , indentNoAp
46+ , (<-/>)
47+ , indentMany
48+ , (<*/>)
49+ , indentOp
50+ , (<?/>)
51+ , Optional (..)
52+ ) where
53+
54+ import Prelude
2055import Control.Alt ((<|>))
21- import Control.Apply ((*>), lift2 )
22- import Control.Monad.Trans (lift )
23- import Control.Monad.State (State , evalState )
56+ import Control.Apply (lift2 )
57+ import Control.Monad.State (gets , State , evalState )
2458import Control.Monad.State.Trans (get , put )
25- import Data.Either (Either (..))
26-
27- import Text.Parsing.Parser (ParseError , ParserT (..), PState (..), fail )
28- import Text.Parsing.Parser.Combinators
59+ import Control.Monad.Trans.Class (lift )
60+ import Data.List (List (..), many )
61+ import Data.Maybe (Maybe (..))
62+ import Text.Parsing.Parser (ParserT , ParseState (ParseState), fail )
63+ import Text.Parsing.Parser.Combinators (option , optionMaybe )
2964import Text.Parsing.Parser.Pos (Position (..), initialPos )
3065import Text.Parsing.Parser.String (string , oneOf )
3166
32- -- $doc
33- -- This is purescript-port of Text.Parsing.Indent
34- -- https://hackage.haskell.org/package/indents-0.3.3/docs/Text-Parsec-Indent.html, 05.07.2016
35-
36- -- A module to construct indentation aware parsers. Many programming
37- -- language have indentation based syntax rules e.g. python and Haskell.
38- -- This module exports combinators to create such parsers.
39- --
40- -- The input source can be thought of as a list of tokens. Abstractly
41- -- each token occurs at a line and a column and has a width. The column
42- -- number of a token measures is indentation. If t1 and t2 are two tokens
43- -- then we say that indentation of t1 is more than t2 if the column
44- -- number of occurrence of t1 is greater than that of t2.
45- --
46- -- Currently this module supports two kind of indentation based syntactic
47- -- structures which we now describe:
48- --
49- -- [Block] --A block of indentation /c/ is a sequence of tokens with
50- -- indentation at least /c/. Examples for a block is a where clause of
51- -- Haskell with no explicit braces.
52- --
53- -- [Line fold] A line fold starting at line /l/ and indentation /c/ is a
54- -- sequence of tokens that start at line /l/ and possibly continue to
55- -- subsequent lines as long as the indentation is greater than /c/. Such
56- -- a sequence of lines need to be /folded/ to a single line. An example
57- -- is MIME headers. Line folding based binding separation is used in
58- -- Haskell as well.
59-
6067-- | Indentation sensitive parser type. Usually @ m @ will
61- -- be @ Identity @ as with any @ ParserT @
68+ -- | be @ Identity @ as with any @ ParserT @
6269type IndentParser s a = ParserT s (State Position ) a
6370
64-
6571-- | @ getPosition @ returns current position
66- -- should probably be added to Text.Parsing.Parser.Pos
72+ -- | should probably be added to Text.Parsing.Parser.Pos
6773getPosition :: forall m s . (Monad m ) => ParserT s m Position
68- getPosition = ParserT $ \( PState { input: (i :: s ), position: ( pos :: Position )}) -> pure {input: (i :: s ), result: ( Right ( pos :: Position )) :: Either ParseError Position , consumed : false , position : ( pos :: Position )}
74+ getPosition = gets \( ParseState _ pos _) -> pos
6975
7076-- | simple helper function to avoid typ-problems with MonadState instance
7177get' :: forall s . IndentParser s Position
72- get' = do
78+ get' = do
7379 g <- lift get
74- pure g
80+ pure g
7581
7682-- | simple helper function to avoid typ-problems with MonadState instance
7783put' :: forall s . Position -> IndentParser s Unit
@@ -80,7 +86,7 @@ put' p = lift (put p)
8086sourceColumn :: Position -> Int
8187sourceColumn (Position {line: _, column: c}) = c
8288
83- sourceLine :: Position -> Int
89+ sourceLine :: Position -> Int
8490sourceLine (Position {line: l, column: _}) = l
8591
8692setSourceLine :: Position -> Int -> Position
@@ -91,21 +97,19 @@ biAp f c v1 v2 = c (f v1) (f v2)
9197
9298-- | @ many1 @ should prabably be inside Text.Parsing.Parser.Combinators
9399many1 :: forall s m a . (Monad m ) => ParserT s m a -> ParserT s m (List a )
94- many1 p = lift2 Cons p (many p)
100+ many1 p = lift2 Cons p (many p)
95101
96102symbol :: forall m . (Monad m ) => String -> ParserT String m String
97103symbol name = (many $ oneOf [' ' ,' \t ' ]) *> (string name)
98104
99- -- --------------------------------------------------------------------
100-
101- -- | @ 'withBlock' f a p @ parses @ a @
102- -- followed by an indented block of @ p @
103- -- combining them with @ f @
105+ -- | `withBlock f a p` parses `a`
106+ -- | followed by an indented block of `p`
107+ -- | combining them with `f`.
104108withBlock :: forall a b c s . (a -> List b -> c ) -> IndentParser s a -> IndentParser s b -> IndentParser s c
105109withBlock f a p = withPos $ do
106110 r1 <- a
107111 r <- optionMaybe $ indented *> block p
108- case r of
112+ case r of
109113 Nothing -> pure (f r1 Nil )
110114 Just r2 -> pure (f r1 r2)
111115
@@ -122,7 +126,7 @@ indented = do
122126 put' $ setSourceLine s (sourceLine pos)
123127 pure unit
124128
125- -- | same as ' indented' , but does not change internal state
129+ -- | Same as ` indented` , but does not change internal state
126130indented' :: forall s . IndentParser s Unit
127131indented' = do
128132 pos <- getPosition
@@ -171,45 +175,45 @@ checkIndent = do
171175runIndent :: forall a . State Position a -> a
172176runIndent = flip evalState initialPos
173177
174- -- | ' <+/>' is to indentation sensitive parsers what 'ap' is to monads
178+ -- | ` <+/>` is to indentation sensitive parsers what `ap` is to monads
175179indentAp :: forall s a b . IndentParser s (a -> b ) -> IndentParser s a -> IndentParser s b
176180indentAp a b = ap a $ sameOrIndented *> b
177181
178182infixl 9 indentAp as <+/>
179183
180- -- | Like ' <+/>' but doesn't apply the function to the parsed value
184+ -- | Like ` <+/>` but doesn't apply the function to the parsed value
181185indentNoAp :: forall s a b . IndentParser s a -> IndentParser s b -> IndentParser s a
182186indentNoAp a b = lift2 const a $ sameOrIndented *> b
183187
184188infixl 10 indentNoAp as <-/>
185189
186- -- | Like ' <+/>' but applies the second parser many times
190+ -- | Like ` <+/>` but applies the second parser many times
187191indentMany :: forall s a b . IndentParser s (List a -> b ) -> IndentParser s a -> IndentParser s b
188192indentMany a b = ap a (many (sameOrIndented *> b))
189193
190194infixl 11 indentMany as <*/>
191195
192- -- | Datatype used to optional parsing
196+ -- | Data type used to optional parsing
193197data Optional s a = Opt a (IndentParser s a )
194198
195- -- | Like ' <+/>' but applies the second parser optionally using the ' Optional' datatype
196- indentOp :: forall s a b . IndentParser s (a -> b ) -> ( Optional s a ) -> IndentParser s b
199+ -- | Like ` <+/>` but applies the second parser optionally using the ` Optional` datatype
200+ indentOp :: forall s a b . IndentParser s (a -> b ) -> Optional s a -> IndentParser s b
197201indentOp a (Opt b c) = ap a (option b (sameOrIndented *> c))
198202
199203infixl 12 indentOp as <?/>
200204
201- -- | parses with surrounding brackets
205+ -- | Parses with surrounding brackets
202206indentBrackets :: forall a . IndentParser String a -> IndentParser String a
203207indentBrackets p = withPos $ pure id <- /> symbol " [" <+/> p <- /> symbol " ]"
204208
205- -- | parses with surrounding angle brackets
209+ -- | Parses with surrounding angle brackets
206210indentAngles :: forall a . IndentParser String a -> IndentParser String a
207211indentAngles p = withPos $ pure id <- /> symbol " <" <+/> p <- /> symbol " >"
208212
209- -- | parses with surrounding braces
213+ -- | Parses with surrounding braces
210214indentBraces :: forall a . IndentParser String a -> IndentParser String a
211215indentBraces p = withPos $ pure id <- /> symbol " {" <+/> p <- /> symbol " }"
212216
213- -- | parses with surrounding parentheses
217+ -- | Parses with surrounding parentheses
214218indentParens :: forall a . IndentParser String a -> IndentParser String a
215- indentParens p = withPos $ pure id <- /> symbol " (" <+/> p <- /> symbol " )"
219+ indentParens p = withPos $ pure id <- /> symbol " (" <+/> p <- /> symbol " )"
0 commit comments