Skip to content

Commit 9467576

Browse files
authored
Fix choice error behavior (#168)
1 parent 9664e94 commit 9467576

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/Text/Parsing/Parser/Combinators.purs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ import Data.Function.Uncurried (mkFn2, mkFn5, runFn2, runFn5)
105105
import Data.List (List(..), many, manyRec, reverse, (:))
106106
import Data.List.NonEmpty (NonEmptyList, cons')
107107
import Data.List.NonEmpty as NEL
108-
import Data.Maybe (Maybe(..))
108+
import Data.Maybe (Maybe(..), fromMaybe)
109109
import Data.Tuple (Tuple(..))
110110
import Data.Tuple.Nested (type (/\), (/\))
111111
import Data.Unfoldable (replicateA)
@@ -442,7 +442,11 @@ chainr1Rec p f = do
442442

443443
-- | Parse one of a set of alternatives.
444444
choice :: forall f m s a. Foldable f => f (ParserT s m a) -> ParserT s m a
445-
choice = foldr (<|>) empty
445+
choice = fromMaybe empty <<< foldr go Nothing
446+
where
447+
go p1 = case _ of
448+
Nothing -> Just p1
449+
Just p2 -> Just (p1 <|> p2)
446450

447451
-- | Skip many instances of a phrase.
448452
skipMany :: forall s a m. ParserT s m a -> ParserT s m Unit

test/Main.purs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import Effect.Console (logShow)
2222
import Partial.Unsafe (unsafePartial)
2323
import Test.Assert (assert')
2424
import Text.Parsing.Parser (ParseError(..), Parser, ParserT, fail, parseErrorMessage, parseErrorPosition, position, region, runParser)
25-
import Text.Parsing.Parser.Combinators (between, chainl, chainl1Rec, chainlRec, chainr1Rec, chainrRec, endBy1, endBy1Rec, endByRec, many1Rec, many1TillRec, many1TillRec_, many1Till_, manyTillRec, manyTillRec_, manyTill_, notFollowedBy, optionMaybe, sepBy1, sepBy1Rec, sepByRec, sepEndBy1Rec, sepEndByRec, skipMany1Rec, skipManyRec, try, (<?>), (<~?>), (<??>))
25+
import Text.Parsing.Parser.Combinators (between, chainl, chainl1Rec, chainlRec, chainr1Rec, chainrRec, choice, endBy1, endBy1Rec, endByRec, many1Rec, many1TillRec, many1TillRec_, many1Till_, manyTillRec, manyTillRec_, manyTill_, notFollowedBy, optionMaybe, sepBy1, sepBy1Rec, sepByRec, sepEndBy1Rec, sepEndByRec, skipMany1Rec, skipManyRec, try, (<?>), (<??>), (<~?>))
2626
import Text.Parsing.Parser.Expr (Assoc(..), Operator(..), buildExprParser)
2727
import Text.Parsing.Parser.Language (haskellDef, haskellStyle, javaStyle)
2828
import Text.Parsing.Parser.Pos (Position(..), initialPos)
@@ -727,6 +727,16 @@ main = do
727727
"no"
728728
"No alternative"
729729

730+
-- Choice shouldn't always yield "No alternative", that's what `oneOf` is for.
731+
parseErrorTestMessage
732+
( choice
733+
[ string "a"
734+
, string "b"
735+
]
736+
)
737+
"c"
738+
"Expected \"b\""
739+
730740
-- we can't test "NaN" with `parseTest` because nan doesn't compare equal
731741
case runParser "NaN" number of
732742
Right actual -> do

0 commit comments

Comments
 (0)