git.iko.soy/typeable/pandoc
on master help sign in
Parsing: `many1Till`: Check for the end condition before parsing

By not checking for the end condition before the first parse, the parser was applied too often, consuming too much of the input. This fixes the behaviour of `testStringWith (many1Till (oneOf "ab") (string "aa")) "aaa"` which before incorrectly returned `Right "a"`. With this change, it instead correctly fails with `Left (PandocParsecError ...)` because it is not able to parse at least one occurence of `oneOf "ab"` that is not `"aa"`. Note that this only affects `many1Till p end` where `p` matches on a prefix of `end`.

commit5a71632d11f86cb6ed700fe3a4d717a56bad1b9e authorHerwig Stuetz <herwig@herwigstuetz.com> dateTue 23 May 2017, 23:21 (9 years ago) parentafb5514
4 files changed+8−7
src/Text/Pandoc/Parsing.hs+3−2 src/Text/Pandoc/Readers/Org/Inlines.hs+2−2 src/Text/Pandoc/Readers/TWiki.hs+2−2 src/Text/Pandoc/Readers/Textile.hs+1−1
src/Text/Pandoc/Parsing.hs+3−2
@@ -274,11 +274,12 @@ indentWith num = do
274274 , try (char '\t' >> indentWith (num - tabStop)) ]
275275
276276-- | Like @manyTill@, but reads at least one item.
277−many1Till :: Stream s m t
277+many1Till :: (Show end, Stream s m t)
278278 => ParserT s st m a
279279 -> ParserT s st m end
280280 -> ParserT s st m [a]
281281many1Till p end = do
282+ notFollowedBy' end
282283 first <- p
283284 rest <- manyTill p end
284285 return (first:rest)
@@ -343,7 +344,7 @@ blanklines :: Stream s m Char => ParserT s st m [Char]
343344blanklines = many1 blankline
344345
345346-- | Parses material enclosed between start and end parsers.
346−enclosed :: Stream s m Char => ParserT s st m t -- ^ start parser
347+enclosed :: (Show end, Stream s m Char) => ParserT s st m t -- ^ start parser
347348 -> ParserT s st m end -- ^ end parser
348349 -> ParserT s st m a -- ^ content parser (to be used repeatedly)
349350 -> ParserT s st m [a]
src/Text/Pandoc/Readers/Org/Inlines.hs+2−2
@@ -687,13 +687,13 @@ mathEnd c = try $ do
687687 return res
688688
689689
690−enclosedInlines :: PandocMonad m => OrgParser m a
690+enclosedInlines :: (PandocMonad m, Show b) => OrgParser m a
691691 -> OrgParser m b
692692 -> OrgParser m (F Inlines)
693693enclosedInlines start end = try $
694694 trimInlinesF . mconcat <$> enclosed start end inline
695695
696−enclosedRaw :: PandocMonad m => OrgParser m a
696+enclosedRaw :: (PandocMonad m, Show b) => OrgParser m a
697697 -> OrgParser m b
698698 -> OrgParser m String
699699enclosedRaw start end = try $
src/Text/Pandoc/Readers/TWiki.hs+2−2
@@ -349,13 +349,13 @@ linebreak = newline >> notFollowedBy newline >> (lastNewline <|> innerNewline)
349349 where lastNewline = eof >> return mempty
350350 innerNewline = return B.space
351351
352−between :: (Monoid c, PandocMonad m)
352+between :: (Monoid c, PandocMonad m, Show b)
353353 => TWParser m a -> TWParser m b -> (TWParser m b -> TWParser m c)
354354 -> TWParser m c
355355between start end p =
356356 mconcat <$> try (start >> notFollowedBy whitespace >> many1Till (p end) end)
357357
358−enclosed :: (Monoid b, PandocMonad m)
358+enclosed :: (Monoid b, PandocMonad m, Show a)
359359 => TWParser m a -> (TWParser m a -> TWParser m b) -> TWParser m b
360360enclosed sep p = between sep (try $ sep <* endMarker) p
361361 where
src/Text/Pandoc/Readers/Textile.hs+1−1
@@ -692,7 +692,7 @@ langAttr = do
692692 return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals)
693693
694694-- | Parses material surrounded by a parser.
695−surrounded :: PandocMonad m
695+surrounded :: (PandocMonad m, Show t)
696696 => ParserT [Char] st m t -- ^ surrounding parser
697697 -> ParserT [Char] st m a -- ^ content parser (to be used repeatedly)
698698 -> ParserT [Char] st m [a]