Skip to content

Commit f5c80c2

Browse files
committed
consumeWith: propagate consumed flag when it was set
The Parsing design implies that if input was consumed, it must propagate further unless `try` is used to reset that. Fixes: #236
1 parent c38e6ea commit f5c80c2

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

Diff for: src/Parsing/String.purs

+2-2
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,12 @@ consumeWith
282282
. (String -> Either String { value :: a, consumed :: String, remainder :: String })
283283
-> ParserT String m a
284284
consumeWith f = ParserT
285-
( mkFn5 \state1@(ParseState input pos _) _ _ throw done ->
285+
( mkFn5 \state1@(ParseState input pos oldConsumed) _ _ throw done ->
286286
case f input of
287287
Left err ->
288288
runFn2 throw state1 (ParseError err pos)
289289
Right { value, consumed, remainder } ->
290-
runFn2 done (ParseState remainder (updatePosString pos consumed remainder) (not (String.null consumed))) value
290+
runFn2 done (ParseState remainder (updatePosString pos consumed remainder) (oldConsumed || not (String.null consumed))) value
291291
)
292292

293293
-- | Combinator which finds the first position in the input `String` where the

Diff for: test/Test/Main.purs

+12-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import Effect.Console (log, logShow)
3636
import Effect.Unsafe (unsafePerformEffect)
3737
import Node.Process (lookupEnv)
3838
import Parsing (ParseError(..), ParseState(..), Parser, ParserT, Position(..), consume, fail, getParserT, initialPos, parseErrorPosition, position, region, runParser)
39-
import Parsing.Combinators (advance, between, chainl, chainl1, chainr, chainr1, choice, empty, endBy, endBy1, lookAhead, many, many1, many1Till, many1Till_, manyIndex, manyTill, manyTill_, notFollowedBy, optionMaybe, replicateA, sepBy, sepBy1, sepEndBy, sepEndBy1, skipMany, skipMany1, try, tryRethrow, (<?>), (<??>), (<~?>))
39+
import Parsing.Combinators (advance, between, chainl, chainl1, chainr, chainr1, choice, empty, endBy, endBy1, lookAhead, many, many1, many1Till, many1Till_, manyIndex, manyTill, manyTill_, notFollowedBy, optional, optionMaybe, replicateA, sepBy, sepBy1, sepEndBy, sepEndBy1, skipMany, skipMany1, try, tryRethrow, (<?>), (<??>), (<~?>))
4040
import Parsing.Combinators.Array as Combinators.Array
4141
import Parsing.Expr (Assoc(..), Operator(..), buildExprParser)
4242
import Parsing.Language (haskellDef, haskellStyle, javaStyle)
@@ -572,6 +572,15 @@ javaStyleTest = do
572572
"hello {- comment\n -} foo"
573573
(mkPos 7)
574574

575+
takeWhilePropagateFail :: TestM
576+
takeWhilePropagateFail = do
577+
-- `takeWhile` always succeeds, but if input was consumed prior and failure happens
578+
-- later, then the failure with consumption should propagate past `optional` #236
579+
parseErrorTestPosition
580+
(optional (char 'f' <* takeWhile (const false) <* fail "failure"))
581+
"f"
582+
(Position { index: 1, line: 1, column: 2 })
583+
575584
main :: Effect Unit
576585
main = do
577586

@@ -734,6 +743,8 @@ main = do
734743
, expected: Left $ ParseError "Expected letter" (Position { index: 0, line: 1, column: 1 })
735744
}
736745

746+
takeWhilePropagateFail
747+
737748
log "\nTESTS number\n"
738749

739750
-- assert' "Number.fromString" $ Just infinity == Data.Number.fromString "Infinity"

0 commit comments

Comments
 (0)