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
20
55
import 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 )
24
58
import 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 )
29
64
import Text.Parsing.Parser.Pos (Position (..), initialPos )
30
65
import Text.Parsing.Parser.String (string , oneOf )
31
66
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
-
60
67
-- | Indentation sensitive parser type. Usually @ m @ will
61
- -- be @ Identity @ as with any @ ParserT @
68
+ -- | be @ Identity @ as with any @ ParserT @
62
69
type IndentParser s a = ParserT s (State Position ) a
63
70
64
-
65
71
-- | @ getPosition @ returns current position
66
- -- should probably be added to Text.Parsing.Parser.Pos
72
+ -- | should probably be added to Text.Parsing.Parser.Pos
67
73
getPosition :: 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
69
75
70
76
-- | simple helper function to avoid typ-problems with MonadState instance
71
77
get' :: forall s . IndentParser s Position
72
- get' = do
78
+ get' = do
73
79
g <- lift get
74
- pure g
80
+ pure g
75
81
76
82
-- | simple helper function to avoid typ-problems with MonadState instance
77
83
put' :: forall s . Position -> IndentParser s Unit
@@ -80,7 +86,7 @@ put' p = lift (put p)
80
86
sourceColumn :: Position -> Int
81
87
sourceColumn (Position {line: _, column: c}) = c
82
88
83
- sourceLine :: Position -> Int
89
+ sourceLine :: Position -> Int
84
90
sourceLine (Position {line: l, column: _}) = l
85
91
86
92
setSourceLine :: Position -> Int -> Position
@@ -91,21 +97,19 @@ biAp f c v1 v2 = c (f v1) (f v2)
91
97
92
98
-- | @ many1 @ should prabably be inside Text.Parsing.Parser.Combinators
93
99
many1 :: 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)
95
101
96
102
symbol :: forall m . (Monad m ) => String -> ParserT String m String
97
103
symbol name = (many $ oneOf [' ' ,' \t ' ]) *> (string name)
98
104
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`.
104
108
withBlock :: forall a b c s . (a -> List b -> c ) -> IndentParser s a -> IndentParser s b -> IndentParser s c
105
109
withBlock f a p = withPos $ do
106
110
r1 <- a
107
111
r <- optionMaybe $ indented *> block p
108
- case r of
112
+ case r of
109
113
Nothing -> pure (f r1 Nil )
110
114
Just r2 -> pure (f r1 r2)
111
115
@@ -122,7 +126,7 @@ indented = do
122
126
put' $ setSourceLine s (sourceLine pos)
123
127
pure unit
124
128
125
- -- | same as ' indented' , but does not change internal state
129
+ -- | Same as ` indented` , but does not change internal state
126
130
indented' :: forall s . IndentParser s Unit
127
131
indented' = do
128
132
pos <- getPosition
@@ -171,45 +175,45 @@ checkIndent = do
171
175
runIndent :: forall a . State Position a -> a
172
176
runIndent = flip evalState initialPos
173
177
174
- -- | ' <+/>' is to indentation sensitive parsers what 'ap' is to monads
178
+ -- | ` <+/>` is to indentation sensitive parsers what `ap` is to monads
175
179
indentAp :: forall s a b . IndentParser s (a -> b ) -> IndentParser s a -> IndentParser s b
176
180
indentAp a b = ap a $ sameOrIndented *> b
177
181
178
182
infixl 9 indentAp as <+/>
179
183
180
- -- | Like ' <+/>' but doesn't apply the function to the parsed value
184
+ -- | Like ` <+/>` but doesn't apply the function to the parsed value
181
185
indentNoAp :: forall s a b . IndentParser s a -> IndentParser s b -> IndentParser s a
182
186
indentNoAp a b = lift2 const a $ sameOrIndented *> b
183
187
184
188
infixl 10 indentNoAp as <-/>
185
189
186
- -- | Like ' <+/>' but applies the second parser many times
190
+ -- | Like ` <+/>` but applies the second parser many times
187
191
indentMany :: forall s a b . IndentParser s (List a -> b ) -> IndentParser s a -> IndentParser s b
188
192
indentMany a b = ap a (many (sameOrIndented *> b))
189
193
190
194
infixl 11 indentMany as <*/>
191
195
192
- -- | Datatype used to optional parsing
196
+ -- | Data type used to optional parsing
193
197
data Optional s a = Opt a (IndentParser s a )
194
198
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
197
201
indentOp a (Opt b c) = ap a (option b (sameOrIndented *> c))
198
202
199
203
infixl 12 indentOp as <?/>
200
204
201
- -- | parses with surrounding brackets
205
+ -- | Parses with surrounding brackets
202
206
indentBrackets :: forall a . IndentParser String a -> IndentParser String a
203
207
indentBrackets p = withPos $ pure id <- /> symbol " [" <+/> p <- /> symbol " ]"
204
208
205
- -- | parses with surrounding angle brackets
209
+ -- | Parses with surrounding angle brackets
206
210
indentAngles :: forall a . IndentParser String a -> IndentParser String a
207
211
indentAngles p = withPos $ pure id <- /> symbol " <" <+/> p <- /> symbol " >"
208
212
209
- -- | parses with surrounding braces
213
+ -- | Parses with surrounding braces
210
214
indentBraces :: forall a . IndentParser String a -> IndentParser String a
211
215
indentBraces p = withPos $ pure id <- /> symbol " {" <+/> p <- /> symbol " }"
212
216
213
- -- | parses with surrounding parentheses
217
+ -- | Parses with surrounding parentheses
214
218
indentParens :: 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