Skip to content

Commit 2a49674

Browse files
authored
Better errors for manyIndex (#211)
Return the parse error message of the phrase parser which failed instead of “Expected more phrases.” Also how many phrases were expected. #210
1 parent 4056d08 commit 2a49674

File tree

4 files changed

+22
-9
lines changed

4 files changed

+22
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ New features:
1515

1616
Other improvements:
1717

18+
- Better error messages for `manyIndex` (#211 by @jamesbrock)
19+
1820
## [v10.0.0](https://github.com/purescript-contrib/purescript-parsing/releases/tag/v9.1.0) - 2022-07-18
1921

2022
Bugfixes:

src/Parsing/Combinators.purs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ module Parsing.Combinators
8484
import Prelude
8585

8686
import Control.Lazy (defer)
87+
import Control.Monad.Error.Class (catchError, throwError)
8788
import Control.Monad.Rec.Class (Step(..), tailRecM)
8889
import Control.Plus (empty, (<|>), alt)
8990
import Data.Foldable (class Foldable, foldl, foldr)
@@ -98,7 +99,7 @@ import Data.Tuple (Tuple(..))
9899
import Data.Tuple.Nested (type (/\), (/\))
99100
import Data.Unfoldable (replicateA)
100101
import Data.Unfoldable1 (replicate1A)
101-
import Parsing (ParseError(..), ParseState(..), ParserT(..), Position(..), fail, position)
102+
import Parsing (ParseError(..), ParseState(..), ParserT(..), Position(..), fail, parseErrorMessage, parseErrorPosition, position)
102103

103104
-- | Provide an error message in the case of failure.
104105
withErrorMessage :: forall m s a. ParserT s m a -> String -> ParserT s m a
@@ -461,15 +462,17 @@ manyIndex from to p =
461462
go (Tuple i xs) =
462463
if i >= to then
463464
pure (Done (Tuple i (reverse xs)))
464-
else alt
465+
else catchError
465466
do
466467
x <- p i
467468
pure (Loop (Tuple (i + 1) (x : xs)))
468-
do
469+
\e -> do
469470
if i >= from then
470471
pure (Done (Tuple i (reverse xs)))
471472
else
472-
fail "Expected more phrases"
473+
throwError $ ParseError
474+
(parseErrorMessage e <> " (at least " <> show from <> ", but only parsed " <> show i <> ")")
475+
(parseErrorPosition e)
473476

474477
-- | If the parser succeeds without advancing the input stream position,
475478
-- | then force the parser to fail.

src/Parsing/Combinators/Array.purs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ module Parsing.Combinators.Array
1919
import Prelude
2020

2121
import Control.Alt (alt)
22+
import Control.Monad.Error.Class (catchError, throwError)
2223
import Control.Monad.Rec.Class (Step(..), tailRecM)
2324
import Data.Array as Array
2425
import Data.Array.NonEmpty (NonEmptyArray)
2526
import Data.Array.NonEmpty as Array.NonEmpty
2627
import Data.List (List(..), (:))
2728
import Data.Maybe (Maybe(..))
2829
import Data.Tuple (Tuple(..))
29-
import Parsing (ParserT, fail)
30+
import Parsing (ParseError(..), ParserT, fail, parseErrorMessage, parseErrorPosition)
3031
import Parsing.Combinators (try)
3132

3233
-- | Match the phrase `p` as many times as possible.
@@ -85,12 +86,14 @@ manyIndex from to p =
8586
go (Tuple i xs) =
8687
if i >= to then
8788
pure (Done (Tuple i xs))
88-
else alt
89+
else catchError
8990
do
9091
x <- p i
9192
pure (Loop (Tuple (i + 1) (x : xs)))
92-
do
93+
\e -> do
9394
if i >= from then
9495
pure (Done (Tuple i xs))
9596
else
96-
fail "Expected more phrases"
97+
throwError $ ParseError
98+
(parseErrorMessage e <> " (at least " <> show from <> ", but only parsed " <> show i <> ")")
99+
(parseErrorPosition e)

test/Main.purs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import Data.String.CodePoints as SCP
2727
import Data.String.CodeUnits (fromCharArray, singleton)
2828
import Data.String.CodeUnits as SCU
2929
import Data.String.Regex.Flags (RegexFlags, ignoreCase, noFlags)
30-
import Data.Tuple (Tuple(..), fst)
30+
import Data.Tuple (Tuple(..), fst, snd)
3131
import Data.Tuple.Nested (get2, (/\))
3232
import Effect (Effect)
3333
import Effect.Console (log, logShow)
@@ -1060,6 +1060,10 @@ main = do
10601060
{ actual: runParser "aaa" $ manyIndex (-2) (1) (\_ -> char 'a')
10611061
, expected: Right (Tuple 0 (Nil))
10621062
}
1063+
assertEqual' "manyIndex 6 errors"
1064+
{ actual: lmap parseErrorPosition $ runParser "aab" $ map snd $ manyIndex 3 3 (\_ -> char 'a')
1065+
, expected: lmap parseErrorPosition $ runParser "aab" $ (replicateA 3 (char 'a') :: Parser String (List Char))
1066+
}
10631067

10641068
log "\nTESTS advance\n"
10651069

@@ -1106,3 +1110,4 @@ main = do
11061110
$ string "aaaa\r\n" *> (replicateA 5 letter :: Parser String (List Char))
11071111
, expected: [ "Expected letter at position index:6 (line:2, column:1)", "", "🍷bbbb" ]
11081112
}
1113+

0 commit comments

Comments
 (0)