git.iko.soy/typeable/pandoc
on master help sign in
More refactoring of LaTeX reader code.
41663e9John MacFarlane
src/Text/Pandoc/Readers/LaTeX.hs+1−1
@@ -1486,7 +1486,7 @@ authors = try $ do
1486
1486
1487macroDef :: PandocMonad m => LP m Blocks
1487macroDef :: PandocMonad m => LP m Blocks
1488macroDef =
1488macroDef =
1489− mempty <$ ((commandDef <|> environmentDef) <* doMacros 0)
1489+ mempty <$ ((commandDef <|> environmentDef) <* doMacros)
1490 where commandDef = do
1490 where commandDef = do
1491 (name, macro') <- newcommand <|> letmacro <|> defmacro
1491 (name, macro') <- newcommand <|> letmacro <|> defmacro
1492 guardDisabled Ext_latex_macros <|>
1492 guardDisabled Ext_latex_macros <|>
src/Text/Pandoc/Readers/LaTeX/Parsing.hs+36−33
@@ -110,6 +110,8 @@ import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),
110import Text.Pandoc.Shared
110import Text.Pandoc.Shared
111import Text.Parsec.Pos
111import Text.Parsec.Pos
112
112
113+-- import Debug.Trace (traceShowId)
114+
113newtype DottedNum = DottedNum [Int]
115newtype DottedNum = DottedNum [Int]
114 deriving (Show)
116 deriving (Show)
115
117
@@ -231,7 +233,7 @@ rawLaTeXParser retokenize parser valParser = do
231 Right toks' -> do
233 Right toks' -> do
232 res <- lift $ runParserT (do when retokenize $ do
234 res <- lift $ runParserT (do when retokenize $ do
233 -- retokenize, applying macros
235 -- retokenize, applying macros
234− doMacros 0
236+ doMacros
235 ts <- many (satisfyTok (const True))
237 ts <- many (satisfyTok (const True))
236 setInput ts
238 setInput ts
237 rawparser)
239 rawparser)
@@ -246,7 +248,7 @@ rawLaTeXParser retokenize parser valParser = do
246applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
248applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)
247 => String -> ParserT String s m String
249 => String -> ParserT String s m String
248applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|>
250applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|>
249− do let retokenize = doMacros 0 *>
251+ do let retokenize = doMacros *>
250 (toksToString <$> many (satisfyTok (const True)))
252 (toksToString <$> many (satisfyTok (const True)))
251 pstate <- getState
253 pstate <- getState
252 let lstate = def{ sOptions = extractReaderOptions pstate
254 let lstate = def{ sOptions = extractReaderOptions pstate
@@ -371,7 +373,7 @@ satisfyTok :: PandocMonad m => (Tok -> Bool) -> LP m Tok
371satisfyTok f =
373satisfyTok f =
372 try $ do
374 try $ do
373 res <- tokenPrim (T.unpack . untoken) updatePos matcher
375 res <- tokenPrim (T.unpack . untoken) updatePos matcher
374− doMacros 0 -- apply macros on remaining input stream
376+ doMacros -- apply macros on remaining input stream
375 return res
377 return res
376 where matcher t | f t = Just t
378 where matcher t | f t = Just t
377 | otherwise = Nothing
379 | otherwise = Nothing
@@ -379,25 +381,29 @@ satisfyTok f =
379 updatePos _spos _ (Tok pos _ _ : _) = pos
381 updatePos _spos _ (Tok pos _ _ : _) = pos
380 updatePos spos _ [] = incSourceColumn spos 1
382 updatePos spos _ [] = incSourceColumn spos 1
381
383
382−doMacros :: PandocMonad m => Int -> LP m ()
384+doMacros :: PandocMonad m => LP m ()
383−doMacros n = do
385+doMacros = do
384 verbatimMode <- sVerbatimMode <$> getState
386 verbatimMode <- sVerbatimMode <$> getState
385 unless verbatimMode $ do
387 unless verbatimMode $ do
386− inp <- getInput
388+ mbNewInp <- getInput >>= doMacros' 1
389+ case mbNewInp of
390+ Nothing -> return ()
391+ Just inp -> setInput inp
392+
393+doMacros' :: PandocMonad m => Int -> [Tok] -> LP m (Maybe [Tok])
394+doMacros' n inp = do
387− case inp of
395+ case inp of
388− Tok spos (CtrlSeq "begin") _ : Tok _ Symbol "{" :
396+ Tok spos (CtrlSeq "begin") _ : Tok _ Symbol "{" :
389− Tok _ Word name : Tok _ Symbol "}" : ts
397+ Tok _ Word name : Tok _ Symbol "}" : ts
390− -> handleMacros spos name ts
398+ -> handleMacros n spos name ts
391− Tok spos (CtrlSeq "end") _ : Tok _ Symbol "{" :
399+ Tok spos (CtrlSeq "end") _ : Tok _ Symbol "{" :
392− Tok _ Word name : Tok _ Symbol "}" : ts
400+ Tok _ Word name : Tok _ Symbol "}" : ts
393− -> handleMacros spos ("end" <> name) ts
401+ -> handleMacros n spos ("end" <> name) ts
394− Tok _ (CtrlSeq "expandafter") _ : t : ts
402+ Tok _ (CtrlSeq "expandafter") _ : t : ts
395− -> do setInput ts
396− doMacros n
397− getInput >>= setInput . combineTok t
403+ -> (fmap (combineTok t)) <$> doMacros' n ts
398− Tok spos (CtrlSeq name) _ : ts
404+ Tok spos (CtrlSeq name) _ : ts
399− -> handleMacros spos name ts
405+ -> handleMacros n spos name ts
400− _ -> return ()
406+ _ -> return Nothing
401
407
402 where
408 where
403 combineTok (Tok spos (CtrlSeq name) x) (Tok _ Word w : ts)
409 combineTok (Tok spos (CtrlSeq name) x) (Tok _ Word w : ts)
@@ -419,9 +425,7 @@ doMacros n = do
419 getargs argmap rest
425 getargs argmap rest
420 getargs argmap (ArgNum i : Pattern toks : rest) =
426 getargs argmap (ArgNum i : Pattern toks : rest) =
421 try $ do
427 try $ do
422− x <- mconcat <$> manyTill
428+ x <- mconcat <$> manyTill bracedOrToken (matchPattern toks)
423− (braced <|> ((:[]) <$> anyTok))
424− (matchPattern toks)
425 getargs (M.insert i x argmap) rest
429 getargs (M.insert i x argmap) rest
426 getargs argmap (ArgNum i : rest) = do
430 getargs argmap (ArgNum i : rest) = do
427 x <- try $ spaces >> bracedOrToken
431 x <- try $ spaces >> bracedOrToken
@@ -439,10 +443,12 @@ doMacros n = do
439 Tok spos (CtrlSeq x) (txt <> " ") : acc
443 Tok spos (CtrlSeq x) (txt <> " ") : acc
440 addTok _ _ spos t acc = setpos spos t : acc
444 addTok _ _ spos t acc = setpos spos t : acc
441
445
442− handleMacros spos name ts = do
446+ handleMacros n' spos name ts = do
447+ when (n' > 20) -- detect macro expansion loops
448+ $ throwError $ PandocMacroLoop (T.unpack name)
443 macros <- sMacros <$> getState
449 macros <- sMacros <$> getState
444 case M.lookup name macros of
450 case M.lookup name macros of
445− Nothing -> return ()
451+ Nothing -> return Nothing
446 Just (Macro expansionPoint argspecs optarg newtoks) -> do
452 Just (Macro expansionPoint argspecs optarg newtoks) -> do
447 setInput ts
453 setInput ts
448 args <- case optarg of
454 args <- case optarg of
@@ -454,15 +460,12 @@ doMacros n = do
454 -- an argument (in which case we don't want to
460 -- an argument (in which case we don't want to
455 -- expand #1 etc.)
461 -- expand #1 etc.)
456 ts' <- getInput
462 ts' <- getInput
457− setInput $ foldr (addTok False args spos) ts' newtoks
463+ let result = foldr (addTok False args spos) ts' newtoks
458−
459 case expansionPoint of
464 case expansionPoint of
460− ExpandWhenUsed ->
465+ ExpandWhenUsed ->
461− if n > 20 -- detect macro expansion loops
462− then throwError $ PandocMacroLoop (T.unpack name)
463− else doMacros (n + 1)
466+ doMacros' (n' + 1) result >>=
467+ maybe (return (Just result)) (return . Just)
464− ExpandWhenDefined -> return ()
468+ ExpandWhenDefined -> return $ Just result
465−
466
469
467setpos :: SourcePos -> Tok -> Tok
470setpos :: SourcePos -> Tok -> Tok
468setpos spos (Tok _ tt txt) = Tok spos tt txt
471setpos spos (Tok _ tt txt) = Tok spos tt txt