@@ -2,6 +2,7 @@
2 FlexibleContexts
2 FlexibleContexts
3, GeneralizedNewtypeDeriving
3, GeneralizedNewtypeDeriving
4, TypeSynonymInstances
4, TypeSynonymInstances
5+, MultiParamTypeClasses
5, FlexibleInstances #-}
6, FlexibleInstances #-}
7Copyright (C) 2006-2014 John MacFarlane <jgm@berkeley.edu>
8Copyright (C) 2006-2014 John MacFarlane <jgm@berkeley.edu>
@@ -80,6 +81,7 @@ module Text.Pandoc.Parsing ( anyLine,
80 HeaderType (..),
81 HeaderType (..),
81 ParserContext (..),
82 ParserContext (..),
82 QuoteContext (..),
83 QuoteContext (..),
84+ HasQuoteContext (..),
83 NoteTable,
85 NoteTable,
84 NoteTable',
86 NoteTable',
@@ -88,7 +90,6 @@ module Text.Pandoc.Parsing ( anyLine,
89 registerHeader,
91 registerHeader,
90 smartPunctuation,
92 smartPunctuation,
92 singleQuoteStart,
93 singleQuoteStart,
93 singleQuoteEnd,
94 singleQuoteEnd,
94 doubleQuoteStart,
95 doubleQuoteStart,
@@ -106,6 +107,7 @@ module Text.Pandoc.Parsing ( anyLine,
109 -- * Re-exports from Text.Pandoc.Parsec
111 -- * Re-exports from Text.Pandoc.Parsec
111 runParser,
113 runParser,
@@ -160,7 +162,6 @@ module Text.Pandoc.Parsing ( anyLine,
160 setSourceColumn,
162 setSourceColumn,
161 setSourceLine,
163 setSourceLine,
@@ -170,7 +171,7 @@ import Text.Pandoc.Builder (Blocks, Inlines, rawBlock, HasMeta(..))
170import qualified Text.Pandoc.Builder as B
171import qualified Text.Pandoc.Builder as B
171import Text.Pandoc.XML (fromEntities)
172import Text.Pandoc.XML (fromEntities)
172import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)
173import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)
173−import Text.Parsec
174+import Text.Parsec hiding (token)
174import Text.Parsec.Pos (newPos)
175import Text.Parsec.Pos (newPos)
175import Data.Char ( toLower, toUpper, ord, chr, isAscii, isAlphaNum,
176import Data.Char ( toLower, toUpper, ord, chr, isAscii, isAlphaNum,
176 isHexDigit, isSpace )
177 isHexDigit, isSpace )
@@ -484,7 +485,8 @@ mathDisplayWith op cl = try $ do
484 string op
485 string op
485 many1Till (noneOf "\n" <|> (newline <* notFollowedBy' blankline)) (try $ string cl)
486 many1Till (noneOf "\n" <|> (newline <* notFollowedBy' blankline)) (try $ string cl)
487−mathDisplay :: Stream s m Char => ParserT s ParserState m String
488+mathDisplay :: (HasReaderOptions st, Stream s m Char)
489+ => ParserT s st m String
488mathDisplay =
490mathDisplay =
489 (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
491 (guardEnabled Ext_tex_math_dollars >> mathDisplayWith "$$" "$$")
490 <|> (guardEnabled Ext_tex_math_single_backslash >>
492 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -492,7 +494,8 @@ mathDisplay =
492 <|> (guardEnabled Ext_tex_math_double_backslash >>
494 <|> (guardEnabled Ext_tex_math_double_backslash >>
493 mathDisplayWith "\\\\[" "\\\\]")
495 mathDisplayWith "\\\\[" "\\\\]")
495−mathInline :: Stream s m Char => ParserT s ParserState m String
497+mathInline :: (HasReaderOptions st , Stream s m Char)
498+ => ParserT s st m String
496mathInline =
499mathInline =
497 (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
500 (guardEnabled Ext_tex_math_dollars >> mathInlineWith "$" "$")
498 <|> (guardEnabled Ext_tex_math_single_backslash >>
501 <|> (guardEnabled Ext_tex_math_single_backslash >>
@@ -909,6 +912,21 @@ class HasReaderOptions st where
909 -- default
912 -- default
910 getOption f = (f . extractReaderOptions) <$> getState
913 getOption f = (f . extractReaderOptions) <$> getState
915+class HasQuoteContext st m where
916+ getQuoteContext :: (Stream s m t) => ParsecT s st m QuoteContext
917+ withQuoteContext :: QuoteContext -> ParsecT s st m a -> ParsecT s st m a
919+instance Monad m => HasQuoteContext ParserState m where
920+ getQuoteContext = stateQuoteContext <$> getState
921+ withQuoteContext context parser = do
922+ oldState <- getState
923+ let oldQuoteContext = stateQuoteContext oldState
924+ setState oldState { stateQuoteContext = context }
926+ newState <- getState
927+ setState newState { stateQuoteContext = oldQuoteContext }
912instance HasReaderOptions ParserState where
930instance HasReaderOptions ParserState where
913 extractReaderOptions = stateOptions
931 extractReaderOptions = stateOptions
@@ -1051,9 +1069,9 @@ registerHeader (ident,classes,kvs) header' = do
1051failUnlessSmart :: (Stream s m a, HasReaderOptions st) => ParserT s st m ()
1069failUnlessSmart :: (Stream s m a, HasReaderOptions st) => ParserT s st m ()
1052failUnlessSmart = getOption readerSmart >>= guard
1070failUnlessSmart = getOption readerSmart >>= guard
1054−smartPunctuation :: Stream s m Char
1072+smartPunctuation :: (HasReaderOptions st, HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)
1055− => ParserT s ParserState m Inlines
1073+ => ParserT s st m Inlines
1056− -> ParserT s ParserState m Inlines
1074+ -> ParserT s st m Inlines
1057smartPunctuation inlineParser = do
1075smartPunctuation inlineParser = do
1058 failUnlessSmart
1076 failUnlessSmart
1059 choice [ quoted inlineParser, apostrophe, dash, ellipses ]
1077 choice [ quoted inlineParser, apostrophe, dash, ellipses ]
@@ -1061,46 +1079,33 @@ smartPunctuation inlineParser = do
1061apostrophe :: Stream s m Char => ParserT s st m Inlines
1079apostrophe :: Stream s m Char => ParserT s st m Inlines
1062apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\x2019")
1080apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\x2019")
1064−quoted :: Stream s m Char
1082+quoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)
1065− => ParserT s ParserState m Inlines
1083+ => ParserT s st m Inlines
1066− -> ParserT s ParserState m Inlines
1084+ -> ParserT s st m Inlines
1067quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser
1085quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser
1069−withQuoteContext :: Stream s m t
1071− -> ParserT s ParserState m a
1072− -> ParserT s ParserState m a
1073−withQuoteContext context parser = do
1074− oldState <- getState
1075− let oldQuoteContext = stateQuoteContext oldState
1076− setState oldState { stateQuoteContext = context }
1078− newState <- getState
1079− setState newState { stateQuoteContext = oldQuoteContext }
1082−singleQuoted :: Stream s m Char
1087+singleQuoted :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)
1083− => ParserT s ParserState m Inlines
1088+ => ParserT s st m Inlines
1084− -> ParserT s ParserState m Inlines
1089+ -> ParserT s st m Inlines
1085singleQuoted inlineParser = try $ do
1090singleQuoted inlineParser = try $ do
1086 singleQuoteStart
1091 singleQuoteStart
1087 withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>=
1092 withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>=
1088 return . B.singleQuoted . mconcat
1093 return . B.singleQuoted . mconcat
1090−doubleQuoted :: Stream s m Char
1095+doubleQuoted :: (HasQuoteContext st m, Stream s m Char)
1091− => ParserT s ParserState m Inlines
1096+ => ParserT s st m Inlines
1092− -> ParserT s ParserState m Inlines
1097+ -> ParserT s st m Inlines
1093doubleQuoted inlineParser = try $ do
1098doubleQuoted inlineParser = try $ do
1094 doubleQuoteStart
1099 doubleQuoteStart
1095 withQuoteContext InDoubleQuote $ manyTill inlineParser doubleQuoteEnd >>=
1100 withQuoteContext InDoubleQuote $ manyTill inlineParser doubleQuoteEnd >>=
1096 return . B.doubleQuoted . mconcat
1101 return . B.doubleQuoted . mconcat
1098−failIfInQuoteContext :: Stream s m t
1103+failIfInQuoteContext :: (HasQuoteContext st m, Stream s m t)
1099 => QuoteContext
1104 => QuoteContext
1100− -> ParserT s ParserState m ()
1105+ -> ParserT s st m ()
1101failIfInQuoteContext context = do
1106failIfInQuoteContext context = do
1102− st <- getState
1107+ context' <- getQuoteContext
1103− if stateQuoteContext st == context
1108+ if context' == context
1104 then fail "already inside quotes"
1109 then fail "already inside quotes"
1105 else return ()
1110 else return ()
@@ -1110,8 +1115,8 @@ charOrRef cs =
1110 guard (c `elem` cs)
1115 guard (c `elem` cs)
1111 return c)
1116 return c)
1113−singleQuoteStart :: Stream s m Char
1118+singleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)
1114− => ParserT s ParserState m ()
1119+ => ParserT s st m ()
1115singleQuoteStart = do
1120singleQuoteStart = do
1116 failIfInQuoteContext InSingleQuote
1121 failIfInQuoteContext InSingleQuote
1117 -- single quote start can't be right after str
1122 -- single quote start can't be right after str
@@ -1124,8 +1129,8 @@ singleQuoteEnd = try $ do
1124 charOrRef "'\8217\146"
1129 charOrRef "'\8217\146"
1125 notFollowedBy alphaNum
1130 notFollowedBy alphaNum
1127−doubleQuoteStart :: Stream s m Char
1132+doubleQuoteStart :: (HasQuoteContext st m, Stream s m Char)
1128− => ParserT s ParserState m ()
1133+ => ParserT s st m ()
1129doubleQuoteStart = do
1134doubleQuoteStart = do
1130 failIfInQuoteContext InDoubleQuote
1135 failIfInQuoteContext InDoubleQuote
1131 try $ do charOrRef "\"\8220\147"
1136 try $ do charOrRef "\"\8220\147"
@@ -1179,6 +1184,14 @@ citeKey = try $ do
1179 let key = firstChar:rest
1184 let key = firstChar:rest
1180 return (suppress_author, key)
1185 return (suppress_author, key)
1188+token :: (Stream s m t)
1190+ -> (t -> SourcePos)
1192+ -> ParsecT s st m a
1193+token pp pos match = tokenPrim pp (\_ t _ -> pos t) match
1183-- Macros
1196-- Macros
@@ -1200,9 +1213,9 @@ macro = do
1200 else return $ rawBlock "latex" def'
1213 else return $ rawBlock "latex" def'
1202-- | Apply current macros to string.
1215-- | Apply current macros to string.
1203−applyMacros' :: Stream [Char] m Char
1216+applyMacros' :: (HasReaderOptions st, HasMacros st, Stream [Char] m Char)
1204 => String
1217 => String
1205− -> ParserT [Char] ParserState m String
1218+ -> ParserT [Char] st m String
1206applyMacros' target = do
1219applyMacros' target = do
1207 apply <- getOption readerApplyMacros
1220 apply <- getOption readerApplyMacros
1208 if apply
1221 if apply