git.iko.soy/typeable/pandoc
on master help sign in
Generalised all functions in Parsing.hs

Before it wasn't possible to use these general combinators with the ParsecT transformer but with the more general types this is now possible.

commitf201bdcb58743d10cc9dc357da6779fd29b531b5 authorMatthew Pickering <matthewtpickering@gmail.com> dateFri 11 Jul 2014, 12:45 (12 years ago) parent05a5b4e
1 file changed+168−128
src/Text/Pandoc/Parsing.hs+168−128
src/Text/Pandoc/Parsing.hs+168−128
@@ -1,5 +1,8 @@
1−{-# LANGUAGE GeneralizedNewtypeDeriving, TypeSynonymInstances,
2− FlexibleInstances#-}
1+{-# LANGUAGE
2+ FlexibleContexts
3+, GeneralizedNewtypeDeriving
4+, TypeSynonymInstances
5+, FlexibleInstances #-}
36{-
47Copyright (C) 2006-2014 John MacFarlane <jgm@berkeley.edu>
58
@@ -177,12 +180,15 @@ import Text.Pandoc.Asciify (toAsciiChar)
177180import Data.Default
178181import qualified Data.Set as Set
179182import Control.Monad.Reader
180−import Control.Applicative ((*>), (<*), (<$), liftA2, Applicative)
183+import Control.Monad.Identity
184+import Control.Applicative ((<$>), (<*>), (*>), (<*), (<$), Applicative)
181185import Data.Monoid
182186import Data.Maybe (catMaybes)
183187
184188type Parser t s = Parsec t s
185189
190+type ParserT = ParsecT
191+
186192newtype F a = F { unF :: Reader ParserState a } deriving (Monad, Applicative, Functor)
187193
188194runF :: F a -> ParserState -> a
@@ -201,11 +207,11 @@ instance Monoid a => Monoid (F a) where
201207
202208-- | Like >>, but returns the operation on the left.
203209-- (Suggested by Tillmann Rendel on Haskell-cafe list.)
204−(>>~) :: (Monad m) => m a -> m b -> m a
205−a >>~ b = a >>= \x -> b >> return x
210+(>>~) :: (Applicative m) => m a -> m b -> m a
211+a >>~ b = a <* b
206212
207213-- | Parse any line of text
208−anyLine :: Parser [Char] st [Char]
214+anyLine :: Stream [Char] m Char => ParserT [Char] st m [Char]
209215anyLine = do
210216 -- This is much faster than:
211217 -- manyTill anyChar newline
@@ -221,9 +227,10 @@ anyLine = do
221227 _ -> mzero
222228
223229-- | Like @manyTill@, but reads at least one item.
224−many1Till :: Parser [tok] st a
225− -> Parser [tok] st end
226− -> Parser [tok] st [a]
230+many1Till :: Stream s m t
231+ => ParserT s st m a
232+ -> ParserT s st m end
233+ -> ParserT s st m [a]
227234many1Till p end = do
228235 first <- p
229236 rest <- manyTill p end
@@ -232,14 +239,14 @@ many1Till p end = do
232239-- | A more general form of @notFollowedBy@. This one allows any
233240-- type of parser to be specified, and succeeds only if that parser fails.
234241-- It does not consume any input.
235−notFollowedBy' :: Show b => Parser [a] st b -> Parser [a] st ()
242+notFollowedBy' :: (Show b, Stream s m a) => ParserT s st m b -> ParserT s st m ()
236243notFollowedBy' p = try $ join $ do a <- try p
237244 return (unexpected (show a))
238245 <|>
239246 return (return ())
240247-- (This version due to Andrew Pimlott on the Haskell mailing list.)
241248
242−oneOfStrings' :: (Char -> Char -> Bool) -> [String] -> Parser [Char] st String
249+oneOfStrings' :: Stream s m Char => (Char -> Char -> Bool) -> [String] -> ParserT s st m String
243250oneOfStrings' _ [] = fail "no strings"
244251oneOfStrings' matches strs = try $ do
245252 c <- anyChar
@@ -254,11 +261,11 @@ oneOfStrings' matches strs = try $ do
254261-- | Parses one of a list of strings. If the list contains
255262-- two strings one of which is a prefix of the other, the longer
256263-- string will be matched if possible.
257−oneOfStrings :: [String] -> Parser [Char] st String
264+oneOfStrings :: Stream s m Char => [String] -> ParserT s st m String
258265oneOfStrings = oneOfStrings' (==)
259266
260267-- | Parses one of a list of strings (tried in order), case insensitive.
261−oneOfStringsCI :: [String] -> Parser [Char] st String
268+oneOfStringsCI :: Stream s m Char => [String] -> ParserT s st m String
262269oneOfStringsCI = oneOfStrings' ciMatch
263270 where ciMatch x y = toLower' x == toLower' y
264271 -- this optimizes toLower by checking common ASCII case
@@ -269,35 +276,35 @@ oneOfStringsCI = oneOfStrings' ciMatch
269276 | otherwise = toLower c
270277
271278-- | Parses a space or tab.
272−spaceChar :: Parser [Char] st Char
279+spaceChar :: Stream s m Char => ParserT s st m Char
273280spaceChar = satisfy $ \c -> c == ' ' || c == '\t'
274281
275282-- | Parses a nonspace, nonnewline character.
276−nonspaceChar :: Parser [Char] st Char
283+nonspaceChar :: Stream s m Char => ParserT s st m Char
277284nonspaceChar = satisfy $ flip notElem ['\t', '\n', ' ', '\r']
278285
279286-- | Skips zero or more spaces or tabs.
280−skipSpaces :: Parser [Char] st ()
287+skipSpaces :: Stream s m Char => ParserT s st m ()
281288skipSpaces = skipMany spaceChar
282289
283290-- | Skips zero or more spaces or tabs, then reads a newline.
284−blankline :: Parser [Char] st Char
291+blankline :: Stream s m Char => ParserT s st m Char
285292blankline = try $ skipSpaces >> newline
286293
287294-- | Parses one or more blank lines and returns a string of newlines.
288−blanklines :: Parser [Char] st [Char]
295+blanklines :: Stream s m Char => ParserT s st m [Char]
289296blanklines = many1 blankline
290297
291298-- | Parses material enclosed between start and end parsers.
292−enclosed :: Parser [Char] st t -- ^ start parser
293− -> Parser [Char] st end -- ^ end parser
294− -> Parser [Char] st a -- ^ content parser (to be used repeatedly)
295− -> Parser [Char] st [a]
299+enclosed :: Stream s m Char => ParserT s st m t -- ^ start parser
300+ -> ParserT s st m end -- ^ end parser
301+ -> ParserT s st m a -- ^ content parser (to be used repeatedly)
302+ -> ParserT s st m [a]
296303enclosed start end parser = try $
297304 start >> notFollowedBy space >> many1Till parser end
298305
299306-- | Parse string, case insensitive.
300−stringAnyCase :: [Char] -> Parser [Char] st String
307+stringAnyCase :: Stream s m Char => [Char] -> ParserT s st m String
301308stringAnyCase [] = string ""
302309stringAnyCase (x:xs) = do
303310 firstChar <- char (toUpper x) <|> char (toLower x)
@@ -305,7 +312,7 @@ stringAnyCase (x:xs) = do
305312 return (firstChar:rest)
306313
307314-- | Parse contents of 'str' using 'parser' and return result.
308−parseFromString :: Parser [tok] st a -> [tok] -> Parser [tok] st a
315+parseFromString :: Stream s m t => ParserT s st m a -> s -> ParserT s st m a
309316parseFromString parser str = do
310317 oldPos <- getPosition
311318 oldInput <- getInput
@@ -316,7 +323,7 @@ parseFromString parser str = do
316323 return result
317324
318325-- | Parse raw line block up to and including blank lines.
319−lineClump :: Parser [Char] st String
326+lineClump :: Stream [Char] m Char => ParserT [Char] st m String
320327lineClump = blanklines
321328 <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)
322329
@@ -325,8 +332,8 @@ lineClump = blanklines
325332-- pairs of open and close, which must be different. For example,
326333-- @charsInBalanced '(' ')' anyChar@ will parse "(hello (there))"
327334-- and return "hello (there)".
328−charsInBalanced :: Char -> Char -> Parser [Char] st Char
329− -> Parser [Char] st String
335+charsInBalanced :: Stream s m Char => Char -> Char -> ParserT s st m Char
336+ -> ParserT s st m String
330337charsInBalanced open close parser = try $ do
331338 char open
332339 let isDelim c = c == open || c == close
@@ -350,8 +357,8 @@ uppercaseRomanDigits :: [Char]
350357uppercaseRomanDigits = map toUpper lowercaseRomanDigits
351358
352359-- | Parses a roman numeral (uppercase or lowercase), returns number.
353−romanNumeral :: Bool -- ^ Uppercase if true
354− -> Parser [Char] st Int
360+romanNumeral :: Stream s m Char => Bool -- ^ Uppercase if true
361+ -> ParserT s st m Int
355362romanNumeral upperCase = do
356363 let romanDigits = if upperCase
357364 then uppercaseRomanDigits
@@ -383,8 +390,8 @@ romanNumeral upperCase = do
383390
384391-- | Parses an email address; returns original and corresponding
385392-- escaped mailto: URI.
386−emailAddress :: Parser [Char] st (String, String)
387−emailAddress = try $ liftA2 toResult mailbox (char '@' *> domain)
393+emailAddress :: Stream s m Char => ParserT s st m (String, String)
394+emailAddress = try $ toResult <$> mailbox <*> (char '@' *> domain)
388395 where toResult mbox dom = let full = fromEntities $ mbox ++ '@':dom
389396 in (full, escapeURI $ "mailto:" ++ full)
390397 mailbox = intercalate "." `fmap` (emailWord `sepby1` dot)
@@ -398,7 +405,7 @@ emailAddress = try $ liftA2 toResult mailbox (char '@' *> domain)
398405 isEmailPunct c = c `elem` "!\"#$%&'*+-/=?^_{|}~;"
399406 -- note: sepBy1 from parsec consumes input when sep
400407 -- succeeds and p fails, so we use this variant here.
401− sepby1 p sep = liftA2 (:) p (many (try $ sep >> p))
408+ sepby1 p sep = (:) <$> p <*> (many (try $ sep >> p))
402409
403410
404411-- Schemes from http://www.iana.org/assignments/uri-schemes.html plus
@@ -426,11 +433,11 @@ schemes = ["coap","doi","javascript","aaa","aaas","about","acap","cap","cid",
426433 "ventrilo","view-source","webcal","wtai","wyciwyg","xfire","xri",
427434 "ymsgr"]
428435
429−uriScheme :: Parser [Char] st String
436+uriScheme :: Stream s m Char => ParserT s st m String
430437uriScheme = oneOfStringsCI schemes
431438
432439-- | Parses a URI. Returns pair of original and URI-escaped version.
433−uri :: Parser [Char] st (String, String)
440+uri :: Stream [Char] m Char => ParserT [Char] st m (String, String)
434441uri = try $ do
435442 scheme <- uriScheme
436443 char ':'
@@ -460,7 +467,7 @@ uri = try $ do
460467 let uri' = scheme ++ ":" ++ fromEntities str'
461468 return (uri', escapeURI uri')
462469
463−mathInlineWith :: String -> String -> Parser [Char] st String
470+mathInlineWith :: Stream s m Char => String -> String -> ParserT s st m String
464471mathInlineWith op cl = try $ do
465472 string op
466473 notFollowedBy space
@@ -474,12 +481,12 @@ mathInlineWith op cl = try $ do
474481 notFollowedBy digit -- to prevent capture of $5
475482 return $ concat words'
476483
477−mathDisplayWith :: String -> String -> Parser [Char] st String
484+mathDisplayWith :: Stream s m Char => String -> String -> ParserT s st m String
478485mathDisplayWith op cl = try $ do
479486 string op
480487 many1Till (noneOf "\n" <|> (newline >>~ notFollowedBy' blankline)) (try $ string cl)
481488
482−mathDisplay :: Parser [Char] ParserState String
489+mathDisplay :: Stream s m Char => ParserT s ParserState m String
483490mathDisplay =
484491 (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
485492 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -487,7 +494,7 @@ mathDisplay =
487494 <|> (guardEnabled Ext_tex_math_double_backslash >>
488495 mathDisplayWith "\\\\[" "\\\\]")
489496
490−mathInline :: Parser [Char] ParserState String
497+mathInline :: Stream s m Char => ParserT s ParserState m String
491498mathInline =
492499 (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
493500 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -499,8 +506,9 @@ mathInline =
499506-- displacement (the difference between the source column at the end
500507-- and the source column at the beginning). Vertical displacement
501508-- (source row) is ignored.
502−withHorizDisplacement :: Parser [Char] st a -- ^ Parser to apply
503− -> Parser [Char] st (a, Int) -- ^ (result, displacement)
509+withHorizDisplacement :: Stream s m Char
510+ => ParserT s st m a -- ^ Parser to apply
511+ -> ParserT s st m (a, Int) -- ^ (result, displacement)
504512withHorizDisplacement parser = do
505513 pos1 <- getPosition
506514 result <- parser
@@ -509,7 +517,7 @@ withHorizDisplacement parser = do
509517
510518-- | Applies a parser and returns the raw string that was parsed,
511519-- along with the value produced by the parser.
512−withRaw :: Monad m => ParsecT [Char] st m a -> ParsecT [Char] st m (a, [Char])
520+withRaw :: Stream [Char] m Char => ParsecT [Char] st m a -> ParsecT [Char] st m (a, [Char])
513521withRaw parser = do
514522 pos1 <- getPosition
515523 inp <- getInput
@@ -525,12 +533,13 @@ withRaw parser = do
525533 return (result, raw)
526534
527535-- | Parses backslash, then applies character parser.
528−escaped :: Parser [Char] st Char -- ^ Parser for character to escape
529− -> Parser [Char] st Char
536+escaped :: Stream s m Char
537+ => ParserT s st m Char -- ^ Parser for character to escape
538+ -> ParserT s st m Char
530539escaped parser = try $ char '\\' >> parser
531540
532541-- | Parse character entity.
533−characterReference :: Parser [Char] st Char
542+characterReference :: Stream s m Char => ParserT s st m Char
534543characterReference = try $ do
535544 char '&'
536545 ent <- many1Till nonspaceChar (char ';')
@@ -539,19 +548,19 @@ characterReference = try $ do
539548 Nothing -> fail "entity not found"
540549
541550-- | Parses an uppercase roman numeral and returns (UpperRoman, number).
542−upperRoman :: Parser [Char] st (ListNumberStyle, Int)
551+upperRoman :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
543552upperRoman = do
544553 num <- romanNumeral True
545554 return (UpperRoman, num)
546555
547556-- | Parses a lowercase roman numeral and returns (LowerRoman, number).
548−lowerRoman :: Parser [Char] st (ListNumberStyle, Int)
557+lowerRoman :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
549558lowerRoman = do
550559 num <- romanNumeral False
551560 return (LowerRoman, num)
552561
553562-- | Parses a decimal numeral and returns (Decimal, number).
554−decimal :: Parser [Char] st (ListNumberStyle, Int)
563+decimal :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
555564decimal = do
556565 num <- many1 digit
557566 return (Decimal, read num)
@@ -560,7 +569,8 @@ decimal = do
560569-- returns (DefaultStyle, [next example number]). The next
561570-- example number is incremented in parser state, and the label
562571-- (if present) is added to the label table.
563−exampleNum :: Parser [Char] ParserState (ListNumberStyle, Int)
572+exampleNum :: Stream s m Char
573+ => ParserT s ParserState m (ListNumberStyle, Int)
564574exampleNum = do
565575 char '@'
566576 lab <- many (alphaNum <|> satisfy (\c -> c == '_' || c == '-'))
@@ -574,38 +584,39 @@ exampleNum = do
574584 return (Example, num)
575585
576586-- | Parses a '#' returns (DefaultStyle, 1).
577−defaultNum :: Parser [Char] st (ListNumberStyle, Int)
587+defaultNum :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
578588defaultNum = do
579589 char '#'
580590 return (DefaultStyle, 1)
581591
582592-- | Parses a lowercase letter and returns (LowerAlpha, number).
583−lowerAlpha :: Parser [Char] st (ListNumberStyle, Int)
593+lowerAlpha :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
584594lowerAlpha = do
585595 ch <- oneOf ['a'..'z']
586596 return (LowerAlpha, ord ch - ord 'a' + 1)
587597
588598-- | Parses an uppercase letter and returns (UpperAlpha, number).
589−upperAlpha :: Parser [Char] st (ListNumberStyle, Int)
599+upperAlpha :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
590600upperAlpha = do
591601 ch <- oneOf ['A'..'Z']
592602 return (UpperAlpha, ord ch - ord 'A' + 1)
593603
594604-- | Parses a roman numeral i or I
595−romanOne :: Parser [Char] st (ListNumberStyle, Int)
605+romanOne :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)
596606romanOne = (char 'i' >> return (LowerRoman, 1)) <|>
597607 (char 'I' >> return (UpperRoman, 1))
598608
599609-- | Parses an ordered list marker and returns list attributes.
600−anyOrderedListMarker :: Parser [Char] ParserState ListAttributes
610+anyOrderedListMarker :: Stream s m Char => ParserT s ParserState m ListAttributes
601611anyOrderedListMarker = choice $
602612 [delimParser numParser | delimParser <- [inPeriod, inOneParen, inTwoParens],
603613 numParser <- [decimal, exampleNum, defaultNum, romanOne,
604614 lowerAlpha, lowerRoman, upperAlpha, upperRoman]]
605615
606616-- | Parses a list number (num) followed by a period, returns list attributes.
607−inPeriod :: Parser [Char] st (ListNumberStyle, Int)
608− -> Parser [Char] st ListAttributes
617+inPeriod :: Stream s m Char
618+ => ParserT s st m (ListNumberStyle, Int)
619+ -> ParserT s st m ListAttributes
609620inPeriod num = try $ do
610621 (style, start) <- num
611622 char '.'
@@ -615,16 +626,18 @@ inPeriod num = try $ do
615626 return (start, style, delim)
616627
617628-- | Parses a list number (num) followed by a paren, returns list attributes.
618−inOneParen :: Parser [Char] st (ListNumberStyle, Int)
619− -> Parser [Char] st ListAttributes
629+inOneParen :: Stream s m Char
630+ => ParserT s st m (ListNumberStyle, Int)
631+ -> ParserT s st m ListAttributes
620632inOneParen num = try $ do
621633 (style, start) <- num
622634 char ')'
623635 return (start, style, OneParen)
624636
625637-- | Parses a list number (num) enclosed in parens, returns list attributes.
626−inTwoParens :: Parser [Char] st (ListNumberStyle, Int)
627− -> Parser [Char] st ListAttributes
638+inTwoParens :: Stream s m Char
639+ => ParserT s st m (ListNumberStyle, Int)
640+ -> ParserT s st m ListAttributes
628641inTwoParens num = try $ do
629642 char '('
630643 (style, start) <- num
@@ -633,9 +646,10 @@ inTwoParens num = try $ do
633646
634647-- | Parses an ordered list marker with a given style and delimiter,
635648-- returns number.
636−orderedListMarker :: ListNumberStyle
649+orderedListMarker :: Stream s m Char
650+ => ListNumberStyle
637651 -> ListNumberDelim
638− -> Parser [Char] ParserState Int
652+ -> ParserT s ParserState m Int
639653orderedListMarker style delim = do
640654 let num = defaultNum <|> -- # can continue any kind of list
641655 case style of
@@ -655,12 +669,12 @@ orderedListMarker style delim = do
655669 return start
656670
657671-- | Parses a character reference and returns a Str element.
658−charRef :: Parser [Char] st Inline
672+charRef :: Stream s m Char => ParserT s st m Inline
659673charRef = do
660674 c <- characterReference
661675 return $ Str [c]
662676
663−lineBlockLine :: Parser [Char] st String
677+lineBlockLine :: Stream [Char] m Char => ParserT [Char] st m String
664678lineBlockLine = try $ do
665679 char '|'
666680 char ' '
@@ -671,7 +685,7 @@ lineBlockLine = try $ do
671685 return $ white ++ unwords (line : continuations)
672686
673687-- | Parses an RST-style line block and returns a list of strings.
674−lineBlockLines :: Parser [Char] st [String]
688+lineBlockLines :: Stream [Char] m Char => ParserT [Char] st m [String]
675689lineBlockLines = try $ do
676690 lines' <- many1 lineBlockLine
677691 skipMany1 $ blankline <|> try (char '|' >> blankline)
@@ -679,11 +693,12 @@ lineBlockLines = try $ do
679693
680694-- | Parse a table using 'headerParser', 'rowParser',
681695-- 'lineParser', and 'footerParser'.
682−tableWith :: Parser [Char] ParserState ([[Block]], [Alignment], [Int])
683− -> ([Int] -> Parser [Char] ParserState [[Block]])
684− -> Parser [Char] ParserState sep
685− -> Parser [Char] ParserState end
686− -> Parser [Char] ParserState Block
696+tableWith :: Stream s m Char
697+ => ParserT s ParserState m ([[Block]], [Alignment], [Int])
698+ -> ([Int] -> ParserT s ParserState m [[Block]])
699+ -> ParserT s ParserState m sep
700+ -> ParserT s ParserState m end
701+ -> ParserT s ParserState m Block
687702tableWith headerParser rowParser lineParser footerParser = try $ do
688703 (heads, aligns, indices) <- headerParser
689704 lines' <- rowParser indices `sepEndBy1` lineParser
@@ -725,9 +740,10 @@ widthsFromIndices numColumns' indices =
725740-- (which may be grid), then the rows,
726741-- which may be grid, separated by blank lines, and
727742-- ending with a footer (dashed line followed by blank line).
728−gridTableWith :: Parser [Char] ParserState [Block] -- ^ Block list parser
743+gridTableWith :: Stream [Char] m Char
744+ => ParserT [Char] ParserState m [Block] -- ^ Block list parser
729745 -> Bool -- ^ Headerless table
730− -> Parser [Char] ParserState Block
746+ -> ParserT [Char] ParserState m Block
731747gridTableWith blocks headless =
732748 tableWith (gridTableHeader headless blocks) (gridTableRow blocks)
733749 (gridTableSep '-') gridTableFooter
@@ -736,13 +752,13 @@ gridTableSplitLine :: [Int] -> String -> [String]
736752gridTableSplitLine indices line = map removeFinalBar $ tail $
737753 splitStringByIndices (init indices) $ trimr line
738754
739−gridPart :: Char -> Parser [Char] st (Int, Int)
755+gridPart :: Stream s m Char => Char -> ParserT s st m (Int, Int)
740756gridPart ch = do
741757 dashes <- many1 (char ch)
742758 char '+'
743759 return (length dashes, length dashes + 1)
744760
745−gridDashedLines :: Char -> Parser [Char] st [(Int,Int)]
761+gridDashedLines :: Stream s m Char => Char -> ParserT s st m [(Int,Int)]
746762gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) >>~ blankline
747763
748764removeFinalBar :: String -> String
@@ -750,13 +766,14 @@ removeFinalBar =
750766 reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse
751767
752768-- | Separator between rows of grid table.
753−gridTableSep :: Char -> Parser [Char] ParserState Char
769+gridTableSep :: Stream s m Char => Char -> ParserT s ParserState m Char
754770gridTableSep ch = try $ gridDashedLines ch >> return '\n'
755771
756772-- | Parse header for a grid table.
757−gridTableHeader :: Bool -- ^ Headerless table
758− -> Parser [Char] ParserState [Block]
759− -> Parser [Char] ParserState ([[Block]], [Alignment], [Int])
773+gridTableHeader :: Stream [Char] m Char
774+ => Bool -- ^ Headerless table
775+ -> ParserT [Char] ParserState m [Block]
776+ -> ParserT [Char] ParserState m ([[Block]], [Alignment], [Int])
760777gridTableHeader headless blocks = try $ do
761778 optional blanklines
762779 dashes <- gridDashedLines '-'
@@ -779,16 +796,17 @@ gridTableHeader headless blocks = try $ do
779796 heads <- mapM (parseFromString blocks) $ map trim rawHeads
780797 return (heads, aligns, indices)
781798
782−gridTableRawLine :: [Int] -> Parser [Char] ParserState [String]
799+gridTableRawLine :: Stream s m Char => [Int] -> ParserT s ParserState m [String]
783800gridTableRawLine indices = do
784801 char '|'
785802 line <- many1Till anyChar newline
786803 return (gridTableSplitLine indices line)
787804
788805-- | Parse row of grid table.
789−gridTableRow :: Parser [Char] ParserState [Block]
806+gridTableRow :: Stream [Char] m Char
807+ => ParserT [Char] ParserState m [Block]
790808 -> [Int]
791− -> Parser [Char] ParserState [[Block]]
809+ -> ParserT [Char] ParserState m [[Block]]
792810gridTableRow blocks indices = do
793811 colLines <- many1 (gridTableRawLine indices)
794812 let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $
@@ -807,15 +825,16 @@ compactifyCell :: [Block] -> [Block]
807825compactifyCell bs = head $ compactify [bs]
808826
809827-- | Parse footer for a grid table.
810−gridTableFooter :: Parser [Char] ParserState [Char]
828+gridTableFooter :: Stream s m Char => ParserT s ParserState m [Char]
811829gridTableFooter = blanklines
812830
813831---
814832
815833-- | Parse a string with a given parser and state.
816−readWith :: Parser [Char] st a -- ^ parser
834+readWith :: (Show s, Stream s Identity Char)
835+ => ParserT s st Identity a -- ^ parser
817836 -> st -- ^ initial state
818− -> [Char] -- ^ input
837+ -> s -- ^ input
819838 -> a
820839readWith parser state input =
821840 case runParser parser state "source" input of
@@ -823,15 +842,16 @@ readWith parser state input =
823842 let errPos = errorPos err'
824843 errLine = sourceLine errPos
825844 errColumn = sourceColumn errPos
826− theline = (lines input ++ [""]) !! (errLine - 1)
845+ theline = (lines (show input) ++ [""]) !! (errLine - 1)
827846 in error $ "\nError at " ++ show err' ++ "\n" ++
828847 theline ++ "\n" ++ replicate (errColumn - 1) ' ' ++
829848 "^"
830849 Right result -> result
831850
832851-- | Parse a string with @parser@ (for testing).
833−testStringWith :: (Show a) => Parser [Char] ParserState a
834− -> String
852+testStringWith :: (Show s, Show a, Stream s Identity Char)
853+ => ParserT s ParserState Identity a
854+ -> s
835855 -> IO ()
836856testStringWith parser str = UTF8.putStrLn $ show $
837857 readWith parser defaultParserState str
@@ -878,7 +898,7 @@ instance HasMeta ParserState where
878898
879899class HasReaderOptions st where
880900 extractReaderOptions :: st -> ReaderOptions
881− getOption :: (ReaderOptions -> b) -> Parser s st b
901+ getOption :: (Stream s m t) => (ReaderOptions -> b) -> ParserT s st m b
882902 -- default
883903 getOption f = (f . extractReaderOptions) `fmap` getState
884904
@@ -946,19 +966,19 @@ defaultParserState =
946966 stateWarnings = []}
947967
948968-- | Succeed only if the extension is enabled.
949−guardEnabled :: HasReaderOptions st => Extension -> Parser s st ()
969+guardEnabled :: (Stream s m a, HasReaderOptions st) => Extension -> ParserT s st m ()
950970guardEnabled ext = getOption readerExtensions >>= guard . Set.member ext
951971
952972-- | Succeed only if the extension is disabled.
953−guardDisabled :: HasReaderOptions st => Extension -> Parser s st ()
973+guardDisabled :: (Stream s m a, HasReaderOptions st) => Extension -> ParserT s st m ()
954974guardDisabled ext = getOption readerExtensions >>= guard . not . Set.member ext
955975
956976-- | Update the position on which the last string ended.
957−updateLastStrPos :: HasLastStrPosition st => Parser s st ()
977+updateLastStrPos :: (Stream s m a, HasLastStrPosition st) => ParserT s st m ()
958978updateLastStrPos = getPosition >>= updateState . setLastStrPos
959979
960980-- | Whether we are right after the end of a string.
961−notAfterString :: HasLastStrPosition st => Parser s st Bool
981+notAfterString :: (Stream s m a, HasLastStrPosition st) => ParserT s st m Bool
962982notAfterString = do
963983 pos <- getPosition
964984 st <- getState
@@ -998,8 +1018,8 @@ type SubstTable = M.Map Key Inlines
9981018-- and the auto_identifers extension is set, generate a new
9991019-- unique identifier, and update the list of identifiers
10001020-- in state.
1001−registerHeader :: (HasReaderOptions st, HasHeaderMap st, HasIdentifierList st)
1002− => Attr -> Inlines -> Parser s st Attr
1021+registerHeader :: (Stream s m a, HasReaderOptions st, HasHeaderMap st, HasIdentifierList st)
1022+ => Attr -> Inlines -> ParserT s st m Attr
10031023registerHeader (ident,classes,kvs) header' = do
10041024 ids <- extractIdentifierList `fmap` getState
10051025 exts <- getOption readerExtensions
@@ -1020,25 +1040,28 @@ registerHeader (ident,classes,kvs) header' = do
10201040 return (ident,classes,kvs)
10211041
10221042-- | Fail unless we're in "smart typography" mode.
1023−failUnlessSmart :: HasReaderOptions st => Parser s st ()
1043+failUnlessSmart :: (Stream s m a, HasReaderOptions st) => ParserT s st m ()
10241044failUnlessSmart = getOption readerSmart >>= guard
10251045
1026−smartPunctuation :: Parser [Char] ParserState Inlines
1027− -> Parser [Char] ParserState Inlines
1046+smartPunctuation :: Stream s m Char
1047+ => ParserT s ParserState m Inlines
1048+ -> ParserT s ParserState m Inlines
10281049smartPunctuation inlineParser = do
10291050 failUnlessSmart
10301051 choice [ quoted inlineParser, apostrophe, dash, ellipses ]
10311052
1032−apostrophe :: Parser [Char] ParserState Inlines
1053+apostrophe :: Stream s m Char => ParserT s st m Inlines
10331054apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\x2019")
10341055
1035−quoted :: Parser [Char] ParserState Inlines
1036− -> Parser [Char] ParserState Inlines
1056+quoted :: Stream s m Char
1057+ => ParserT s ParserState m Inlines
1058+ -> ParserT s ParserState m Inlines
10371059quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser
10381060
1039−withQuoteContext :: QuoteContext
1040− -> Parser [tok] ParserState a
1041− -> Parser [tok] ParserState a
1061+withQuoteContext :: Stream s m t
1062+ => QuoteContext
1063+ -> ParserT s ParserState m a
1064+ -> ParserT s ParserState m a
10421065withQuoteContext context parser = do
10431066 oldState <- getState
10441067 let oldQuoteContext = stateQuoteContext oldState
@@ -1048,99 +1071,112 @@ withQuoteContext context parser = do
10481071 setState newState { stateQuoteContext = oldQuoteContext }
10491072 return result
10501073
1051−singleQuoted :: Parser [Char] ParserState Inlines
1052− -> Parser [Char] ParserState Inlines
1074+singleQuoted :: Stream s m Char
1075+ => ParserT s ParserState m Inlines
1076+ -> ParserT s ParserState m Inlines
10531077singleQuoted inlineParser = try $ do
10541078 singleQuoteStart
10551079 withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>=
10561080 return . B.singleQuoted . mconcat
10571081
1058−doubleQuoted :: Parser [Char] ParserState Inlines
1059− -> Parser [Char] ParserState Inlines
1082+doubleQuoted :: Stream s m Char
1083+ => ParserT s ParserState m Inlines
1084+ -> ParserT s ParserState m Inlines
10601085doubleQuoted inlineParser = try $ do
10611086 doubleQuoteStart
10621087 withQuoteContext InDoubleQuote $ manyTill inlineParser doubleQuoteEnd >>=
10631088 return . B.doubleQuoted . mconcat
10641089
1065−failIfInQuoteContext :: QuoteContext -> Parser [tok] ParserState ()
1090+failIfInQuoteContext :: Stream s m t
1091+ => QuoteContext
1092+ -> ParserT s ParserState m ()
10661093failIfInQuoteContext context = do
10671094 st <- getState
10681095 if stateQuoteContext st == context
10691096 then fail "already inside quotes"
10701097 else return ()
10711098
1072−charOrRef :: [Char] -> Parser [Char] st Char
1099+charOrRef :: Stream s m Char => String -> ParserT s st m Char
10731100charOrRef cs =
10741101 oneOf cs <|> try (do c <- characterReference
10751102 guard (c `elem` cs)
10761103 return c)
10771104
1078−singleQuoteStart :: Parser [Char] ParserState ()
1105+singleQuoteStart :: Stream s m Char
1106+ => ParserT s ParserState m ()
10791107singleQuoteStart = do
10801108 failIfInQuoteContext InSingleQuote
10811109 -- single quote start can't be right after str
10821110 guard =<< notAfterString
10831111 () <$ charOrRef "'\8216\145"
10841112
1085−singleQuoteEnd :: Parser [Char] st ()
1113+singleQuoteEnd :: Stream s m Char
1114+ => ParserT s st m ()
10861115singleQuoteEnd = try $ do
10871116 charOrRef "'\8217\146"
10881117 notFollowedBy alphaNum
10891118
1090−doubleQuoteStart :: Parser [Char] ParserState ()
1119+doubleQuoteStart :: Stream s m Char
1120+ => ParserT s ParserState m ()
10911121doubleQuoteStart = do
10921122 failIfInQuoteContext InDoubleQuote
10931123 try $ do charOrRef "\"\8220\147"
10941124 notFollowedBy . satisfy $ flip elem [' ', '\t', '\n']
10951125
1096−doubleQuoteEnd :: Parser [Char] st ()
1097−doubleQuoteEnd = do
1098− charOrRef "\"\8221\148"
1099− return ()
1126+doubleQuoteEnd :: Stream s m Char
1127+ => ParserT s st m ()
1128+doubleQuoteEnd = void (charOrRef "\"\8221\148")
11001129
1101−ellipses :: Parser [Char] st Inlines
1130+ellipses :: Stream s m Char
1131+ => ParserT s st m Inlines
11021132ellipses = do
11031133 try (charOrRef "\8230\133") <|> try (string "..." >> return '…')
11041134 return (B.str "\8230")
11051135
1106−dash :: Parser [Char] ParserState Inlines
1136+dash :: Stream s m Char => ParserT s ParserState m Inlines
11071137dash = do
11081138 oldDashes <- getOption readerOldDashes
11091139 if oldDashes
11101140 then emDashOld <|> enDashOld
1111− else B.str `fmap` (hyphenDash <|> emDash <|> enDash)
1141+ else B.str <$> (hyphenDash <|> emDash <|> enDash)
11121142
11131143-- Two hyphens = en-dash, three = em-dash
1114−hyphenDash :: Parser [Char] st String
1144+hyphenDash :: Stream s m Char
1145+ => ParserT s st m String
11151146hyphenDash = do
11161147 try $ string "--"
11171148 option "\8211" (char '-' >> return "\8212")
11181149
1119−emDash :: Parser [Char] st String
1150+emDash :: Stream s m Char
1151+ => ParserT s st m String
11201152emDash = do
11211153 try (charOrRef "\8212\151")
11221154 return "\8212"
11231155
1124−enDash :: Parser [Char] st String
1156+enDash :: Stream s m Char
1157+ => ParserT s st m String
11251158enDash = do
11261159 try (charOrRef "\8212\151")
11271160 return "\8211"
11281161
1129−enDashOld :: Parser [Char] st Inlines
1162+enDashOld :: Stream s m Char
1163+ => ParserT s st m Inlines
11301164enDashOld = do
11311165 try (charOrRef "\8211\150") <|>
11321166 try (char '-' >> lookAhead (satisfy isDigit) >> return '–')
11331167 return (B.str "\8211")
11341168
1135−emDashOld :: Parser [Char] st Inlines
1169+emDashOld :: Stream s m Char
1170+ => ParserT s st m Inlines
11361171emDashOld = do
11371172 try (charOrRef "\8212\151") <|> (try $ string "--" >> optional (char '-') >> return '-')
11381173 return (B.str "\8212")
11391174
11401175-- This is used to prevent exponential blowups for things like:
11411176-- a**a*a**a*a**a*a**a*a**a*a**a*a**
1142−nested :: Parser s ParserState a
1143− -> Parser s ParserState a
1177+nested :: Stream s m a
1178+ => ParserT s ParserState m a
1179+ -> ParserT s ParserState m a
11441180nested p = do
11451181 nestlevel <- stateMaxNestingLevel `fmap` getState
11461182 guard $ nestlevel > 0
@@ -1149,7 +1185,8 @@ nested p = do
11491185 updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }
11501186 return res
11511187
1152−citeKey :: HasLastStrPosition st => Parser [Char] st (Bool, String)
1188+citeKey :: (Stream s m Char, HasLastStrPosition st)
1189+ => ParserT s st m (Bool, String)
11531190citeKey = try $ do
11541191 guard =<< notAfterString
11551192 suppress_author <- option False (char '-' *> return True)
@@ -1166,7 +1203,8 @@ citeKey = try $ do
11661203--
11671204
11681205-- | Parse a \newcommand or \renewcommand macro definition.
1169−macro :: (HasMacros st, HasReaderOptions st) => Parser [Char] st Blocks
1206+macro :: (Stream [Char] m Char, HasMacros st, HasReaderOptions st)
1207+ => ParserT [Char] st m Blocks
11701208macro = do
11711209 apply <- getOption readerApplyMacros
11721210 inp <- getInput
@@ -1181,7 +1219,9 @@ macro = do
11811219 else return $ rawBlock "latex" def'
11821220
11831221-- | Apply current macros to string.
1184−applyMacros' :: String -> Parser [Char] ParserState String
1222+applyMacros' :: Stream [Char] m Char
1223+ => String
1224+ -> ParserT [Char] ParserState m String
11851225applyMacros' target = do
11861226 apply <- getOption readerApplyMacros
11871227 if apply