Skip to content

Commit e40ec4d

Browse files
committed
Bugfix: Delete the try in Combinators.Array.many
According to the semantics of “consume”: If the phrase parser fails without consuming then that is the end of the many. If the phrase parser fails after consuming then the whole parse has failed.
1 parent 5d54fb8 commit e40ec4d

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Notable changes to this project are documented in this file. The format is based
77
Bugfixes:
88
- `float` parser of `GenTokenParser` does not parse negative numbers (by @mstream)
99
- Fixes `consumed` semantics which could cause unexpected backtracking instead of a failure (by @natefaubion)
10+
- Fix `Combinators.Array.many` and `Combinators.Array.many1`. If the phrase fails after consuming
11+
then the combinator fails. (#240 by @jamesdbrock)
1012

1113
Breaking changes:
1214

src/Parsing/Combinators.purs

+6-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,12 @@ lookAhead (ParserT k1) = ParserT
207207

208208
-- | Match the phrase `p` as many times as possible.
209209
-- |
210-
-- | If `p` never consumes input when it
211-
-- | fails then `many p` will always succeed,
210+
-- | Will match until the phrase `p` fails *without consuming*.
211+
-- |
212+
-- | If the phrase `p` fails after consuming input then the `many` will fail.
213+
-- |
214+
-- | If the phrase `p` is wrapped in `try` then it will never consume.
215+
-- | If phrase `p` never consumes then `many p` will always succeed,
212216
-- | but may return an empty list.
213217
many :: forall s m a. ParserT s m a -> ParserT s m (List a)
214218
many = List.manyRec

src/Parsing/Combinators/Array.purs

+7-4
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,21 @@ import Data.List (List(..), (:))
2828
import Data.Maybe (Maybe(..))
2929
import Data.Tuple (Tuple(..))
3030
import Parsing (ParseError(..), ParserT, fail, parseErrorMessage, parseErrorPosition)
31-
import Parsing.Combinators (try)
3231

3332
-- | Match the phrase `p` as many times as possible.
3433
-- |
35-
-- | If `p` never consumes input when it
36-
-- | fails then `many p` will always succeed,
34+
-- | Will match until the phrase `p` fails *without consuming*.
35+
-- |
36+
-- | If the phrase `p` fails after consuming input then the `many` will fail.
37+
-- |
38+
-- | If the phrase `p` is wrapped in `try` then it will never consume.
39+
-- | If phrase `p` never consumes then `many p` will always succeed,
3740
-- | but may return an empty array.
3841
many :: forall s m a. ParserT s m a -> ParserT s m (Array a)
3942
many p = do
4043
rlist <- flip tailRecM Nil $ \xs -> alt
4144
do
42-
x <- try p
45+
x <- p
4346
pure (Loop (x : xs))
4447
do
4548
pure (Done xs)

0 commit comments

Comments
 (0)