Skip to content

Commit b1eb59f

Browse files
committed
Docs, and deprecate module Parsing.Pos
1 parent 52b9213 commit b1eb59f

File tree

7 files changed

+87
-63
lines changed

7 files changed

+87
-63
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,12 @@ runParser "aBabaB" (many ayebee)
9999

100100
will return `Right [true, false, true]`.
101101

102-
## Video tutorial
102+
### Stack-safety
103+
104+
Starting with v9.0.0, all parsers and combinators in this package are always
105+
stack-safe.
106+
107+
## Video introduction to monadic parser combinators
103108

104109
[*Monadic Parsers at the Input Boundary*](https://www.youtube.com/watch?v=LLkbzt4ms6M) by James Brock
105110

src/Parsing.purs

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1+
-- | Types and operations for monadic parsing.
2+
-- |
3+
-- | Combinators are in the `Parsing.Combinators` module.
4+
-- |
5+
-- | Primitive parsers for `String` input streams are in the `Parsing.String`
6+
-- | module.
17
module Parsing
2-
( ParseError(..)
3-
, parseErrorMessage
4-
, parseErrorPosition
5-
, ParseState(..)
6-
, ParserT(..)
7-
, Parser
8+
( Parser
89
, runParser
10+
, ParserT(..)
911
, runParserT
1012
, runParserT'
11-
, hoistParserT
12-
, mapParserT
13+
, ParseError(..)
14+
, parseErrorMessage
15+
, parseErrorPosition
16+
, Position(..)
17+
, initialPos
1318
, consume
1419
, position
1520
, fail
1621
, failWithPosition
1722
, region
23+
, ParseState(..)
24+
, hoistParserT
25+
, mapParserT
1826
) where
1927

2028
import Prelude
@@ -29,13 +37,15 @@ import Control.Monad.Trans.Class (class MonadTrans)
2937
import Control.MonadPlus (class Alternative, class MonadPlus, class Plus)
3038
import Data.Either (Either(..))
3139
import Data.Function.Uncurried (Fn2, Fn5, mkFn2, mkFn3, mkFn5, runFn2, runFn3, runFn5)
40+
import Data.Generic.Rep (class Generic)
3241
import Data.Identity (Identity)
3342
import Data.Lazy as Lazy
3443
import Data.Newtype (unwrap)
44+
import Data.Show.Generic (genericShow)
3545
import Data.Tuple (Tuple(..), fst)
36-
import Parsing.Pos (Position, initialPos)
3746

38-
-- | A parsing error, consisting of a message and position information.
47+
-- | A parsing error, consisting of an error message and
48+
-- | the position in the input stream at which the error occurred.
3949
data ParseError = ParseError String Position
4050

4151
parseErrorMessage :: ParseError -> String
@@ -51,7 +61,13 @@ instance showParseError :: Show ParseError where
5161
derive instance eqParseError :: Eq ParseError
5262
derive instance ordParseError :: Ord ParseError
5363

54-
-- | Contains the remaining input and current position.
64+
-- | The internal state of the `ParserT s m` monad.
65+
-- |
66+
-- | Contains the remaining input and current position and the consumed flag.
67+
-- |
68+
-- | The consumed flag is used to implement the rule for `alt` that
69+
-- | - If the left parser fails *without consuming any input*, then backtrack and try the right parser.
70+
-- | - If the left parser fails and consumes input, then fail immediately.
5571
data ParseState s = ParseState s Position Boolean
5672
-- ParseState constructor has three parameters,
5773
-- s: the remaining input
@@ -66,10 +82,7 @@ data ParseState s = ParseState s Position Boolean
6682
--
6783
-- http://blog.ezyang.com/2014/05/parsec-try-a-or-b-considered-harmful/
6884

69-
-- | The Parser monad transformer.
70-
-- |
71-
-- | The first type argument is the stream type. Typically, this is either `String`,
72-
-- | or some sort of token stream.
85+
-- | The `Parser s` monad with a monad transformer parameter `m`.
7386
newtype ParserT s m a = ParserT
7487
-- The parser is implemented using continuation-passing-style with uncurried
7588
-- functions. In addition to the usual error and success continuations, there
@@ -102,13 +115,15 @@ data RunParser s m a
102115
| Lift (m (Unit -> RunParser s m a))
103116
| Stop (ParseState s) (Either ParseError a)
104117

105-
-- | Apply a parser, keeping only the parsed result.
118+
-- | `runParser` with a monad transfomer parameter `m`.
106119
runParserT :: forall m s a. MonadRec m => s -> ParserT s m a -> m (Either ParseError a)
107120
runParserT s p = fst <$> runParserT' initialState p
108121
where
109122
initialState :: ParseState s
110123
initialState = ParseState s initialPos false
111124

125+
-- | Run a parser and produce either an error or the result of the parser
126+
-- | along with the internal state of the parser when it finishes.
112127
runParserT'
113128
:: forall m s a
114129
. MonadRec m
@@ -132,10 +147,14 @@ runParserT' state1 (ParserT k1) =
132147
Stop s res ->
133148
pure $ Done (Tuple res s)
134149

135-
-- | The `Parser` monad is a synonym for the parser monad transformer applied to the `Identity` monad.
150+
-- | The `Parser s` monad, where `s` is the type of the input stream.
151+
-- |
152+
-- | A synonym for the `ParserT` monad transformer applied
153+
-- | to the `Identity` monad.
136154
type Parser s = ParserT s Identity
137155

138-
-- | Apply a parser, keeping only the parsed result.
156+
-- | Run a parser on an input stream `s` and produce either an error or the
157+
-- | result `a` of the parser.
139158
runParser :: forall s a. s -> Parser s a -> Either ParseError a
140159
runParser s = unwrap <<< runParserT s
141160

@@ -145,7 +164,8 @@ hoistParserT f (ParserT k) = ParserT
145164
runFn5 k state1 more (lift <<< f) throw done
146165
)
147166

148-
-- | Change the underlying monad action and data type in a ParserT monad action.
167+
-- | Change the underlying monad action `m` and result data type `a` in
168+
-- | a `ParserT s m` monad action.
149169
mapParserT
150170
:: forall b n s a m
151171
. MonadRec m
@@ -366,3 +386,31 @@ failWithPosition message pos = throwError (ParseError message pos)
366386
-- | `region` as the parser backs out the call stack.
367387
region :: forall m s a. (ParseError -> ParseError) -> ParserT s m a -> ParserT s m a
368388
region context p = catchError p $ \err -> throwError $ context err
389+
390+
-- | `Position` represents the position of the parser in the input stream.
391+
-- |
392+
-- | - `index` is the position since the start of the input. Starts at 0.
393+
-- | - `line` is the current line in the input. Starts at 1.
394+
-- | - `column` is the column of the next character in the current line that
395+
-- | will be parsed. Starts at 1.
396+
newtype Position = Position
397+
{ index :: Int
398+
, line :: Int
399+
, column :: Int
400+
}
401+
402+
derive instance Generic Position _
403+
instance Show Position where
404+
show x = genericShow x
405+
406+
instance Eq Position where
407+
eq (Position l) (Position r) = l.index == r.index
408+
409+
instance Ord Position where
410+
compare (Position l) (Position r) = compare l.index r.index
411+
412+
-- | The `Position` before any input has been parsed.
413+
-- |
414+
-- | `{ index: 0, line: 1, column: 1 }`
415+
initialPos :: Position
416+
initialPos = Position { index: 0, line: 1, column: 1 }

src/Parsing/Combinators.purs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
-- | * [Data.List.Lazy.many](https://pursuit.purescript.org/packages/purescript-lists/docs/Data.List.Lazy#v:many)
3333
-- | * [Data.List.Lazy.some](https://pursuit.purescript.org/packages/purescript-lists/docs/Data.List.Lazy#v:some)
3434
-- |
35-
-- | ### Data.Unfoldable.replicateA Data.List.Lazy.replicateM
35+
-- | ## Combinators in this package
36+
-- |
37+
-- | ### replicateA replicateM
3638
-- |
3739
-- | The __replicateA__ and __replicateM__ combinators are re-exported from
3840
-- | this module. `replicateA n p` or `replicateM n p`
@@ -66,16 +68,16 @@ module Parsing.Combinators
6668
, chainl1
6769
, chainr
6870
, chainr1
69-
, module Control.Plus
70-
, module Data.Unfoldable
71-
, module Data.Unfoldable1
72-
, module Data.List.Lazy
7371
, withErrorMessage
7472
, (<?>)
7573
, withLazyErrorMessage
7674
, (<~?>)
7775
, asErrorMessage
7876
, (<??>)
77+
, module Control.Plus
78+
, module Data.Unfoldable
79+
, module Data.Unfoldable1
80+
, module Data.List.Lazy
7981
) where
8082

8183
import Prelude

src/Parsing/Indent.purs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,8 @@ import Control.Monad.State.Trans (get, put)
6666
import Control.Monad.Trans.Class (lift)
6767
import Data.List (List(..), many)
6868
import Data.Maybe (Maybe(..))
69-
import Parsing (ParserT, fail, position)
69+
import Parsing (ParserT, fail, position, Position(..), initialPos)
7070
import Parsing.Combinators (option, optionMaybe)
71-
import Parsing.Pos (Position(..), initialPos)
7271
import Parsing.String (string)
7372
import Parsing.String.Basic (oneOf)
7473

src/Parsing/Pos.purs

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,8 @@
1-
module Parsing.Pos where
1+
-- | This module is deprecated and will be removed in a future version.
2+
module Parsing.Pos
23

3-
import Prelude
4+
(module Parsing)
45

5-
import Data.Generic.Rep (class Generic)
6-
import Data.Show.Generic (genericShow)
6+
where
77

8-
-- | `Position` represents the position of the parser in the input.
9-
-- |
10-
-- | - `index` is the position since the start of the input. Starts at 0.
11-
-- | - `line` is the current line in the input. Starts at 1.
12-
-- | - `column` is the column of the next character in the current line that
13-
-- | will be parsed. Starts at 1.
14-
newtype Position = Position
15-
{ index :: Int
16-
, line :: Int
17-
, column :: Int
18-
}
19-
20-
derive instance Generic Position _
21-
instance Show Position where
22-
show x = genericShow x
23-
24-
instance Eq Position where
25-
eq (Position l) (Position r) = l.index == r.index
26-
27-
instance Ord Position where
28-
compare (Position l) (Position r) = compare l.index r.index
29-
30-
-- | The `Position` before any input has been parsed.
31-
initialPos :: Position
32-
initialPos = Position { index: 0, line: 1, column: 1 }
8+
import Parsing (Position(..), initialPos)

src/Parsing/String.purs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,8 @@ import Data.String.Regex as Regex
6363
import Data.String.Regex.Flags (RegexFlags)
6464
import Data.Tuple (Tuple(..))
6565
import Partial.Unsafe (unsafePartial)
66-
import Parsing (ParseError(..), ParseState(..), ParserT(..))
66+
import Parsing (ParseError(..), ParseState(..), ParserT(..), Position(..))
6767
import Parsing.Combinators ((<?>))
68-
import Parsing.Pos (Position(..))
6968

7069
-- | Match “end-of-file,” the end of the input stream.
7170
eof :: forall m. ParserT String m Unit

src/Parsing/String/Basic.purs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
-- | Basic `String` parsers derived from primitive `String` parsers.
2-
-- |
3-
-- | Note: In the future, the
4-
-- | __noneOf__, __noneOfCodePoints__, __oneOf__, __oneOfCodePoints__, __skipSpaces__, __whiteSpace__
5-
-- | should be moved into this module and removed from the
6-
-- | __Parsing.String__ module, because they are not primitive parsers.
72
module Parsing.String.Basic
83
( digit
94
, hexDigit

0 commit comments

Comments
 (0)