@@ -41,6 +41,7 @@ module Text.Pandoc.Parsing ( takeWhileP,
4141 indentWith,
4242 many1Till,
4343 manyUntil,
44+ sepBy1',
4445 notFollowedBy',
4546 oneOfStrings,
4647 oneOfStringsCI,
@@ -340,6 +341,14 @@ manyUntil p end = scan
340341 (xs, e) <- scan
341342 return (x:xs, e))
342343
344+-- | Like @sepBy1@ from Parsec,
345+-- but does not fail if it @sep@ succeeds and @p@ fails.
346+sepBy1' :: (Stream s m t)
347+ => ParsecT s u m a
348+ -> ParsecT s u m sep
349+ -> ParsecT s u m [a]
350+sepBy1' p sep = (:) <$> p <*> many (try $ sep >> p)
351+
343352-- | A more general form of @notFollowedBy@. This one allows any
344353-- type of parser to be specified, and succeeds only if that parser fails.
345354-- It does not consume any input.
@@ -546,8 +555,8 @@ emailAddress :: Stream s m Char => ParserT s st m (String, String)
546555emailAddress = try $ toResult <$> mailbox <*> (char '@' *> domain)
547556 where toResult mbox dom = let full = fromEntities $ mbox ++ '@':dom
548557 in (full, escapeURI $ "mailto:" ++ full)
549− mailbox = intercalate "." <$> (emailWord `sepby1` dot)
550− domain = intercalate "." <$> (subdomain `sepby1` dot)
558+ mailbox = intercalate "." <$> (emailWord `sepBy1'` dot)
559+ domain = intercalate "." <$> (subdomain `sepBy1'` dot)
551560 dot = char '.'
552561 subdomain = many1 $ alphaNum <|> innerPunct
553562 -- this excludes some valid email addresses, since an
@@ -564,9 +573,6 @@ emailAddress = try $ toResult <$> mailbox <*> (char '@' *> domain)
564573 return (x:xs)
565574 isEmailChar c = isAlphaNum c || isEmailPunct c
566575 isEmailPunct c = c `elem` "!\"#$%&'*+-/=?^_{|}~;"
567− -- note: sepBy1 from parsec consumes input when sep
568− -- succeeds and p fails, so we use this variant here.
569− sepby1 p sep = (:) <$> p <*> many (try $ sep >> p)
570576
571577
572578uriScheme :: Stream s m Char => ParserT s st m String