Closed
Description
The issue discussed in purescript-contrib/purescript-parsing#120 also applies to this project.
Paraphrasing the conclusion from the other issue:
- many p will get stuck in a loop if p possibly doesn't consume any input but still succeeds.
- We could change the semantics of many-like combinators (or add a safe variant) that doesn't hang in the situation where no input was consumed.
@jamesdbrock pointed out that
Because ParserT is a monad transformer, it's possible to imagine a ParserT s State a which consumes no input of the first parse but does consume input on the second parse, due to some mechanics of the internal state.
However, I don't think that problem applies in this project, since Parser
is not a monad transformer here.
I would propose something like the following. But perhaps these safe variants could even replace the original functions.
-- Fails with parse error if parser did not consume any input
assertConsume :: forall a. Parser a -> Parser a
assertConsume p = Parser $ \posStrBefore ->
case unParser p posStrBefore of
Right result ->
if posStrBefore.pos < result.suffix.pos
then Right result
else Left { pos: result.suffix.pos, error: "Consumed no input." }
x -> x
safeMany :: forall a. Parser a -> Parser (List a)
safeMany = many <<< assertConsume
safeMany1 :: forall a. Parser a -> Parser (NonEmptyList a)
safeMany1 = many1 <<< assertConsume
safeManyTill :: forall a end. Parser a -> Parser end -> Parser (List a)
safeManyTill p = manyTill (assertConsume p)
safeMany1Till :: forall a end. Parser a -> Parser end -> Parser (NonEmptyList a)
safeMany1Till p = many1Till (assertConsume p)
Any thoughts?
Metadata
Metadata
Assignees
Labels
No labels