aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2018-10-15 11:27:04 -0700
committerJohn MacFarlane <jgm@berkeley.edu>2018-10-15 11:27:04 -0700
commite6ee032a6de22f5a2dd18030d0956e67d1fc26ba (patch)
tree151059b0e7a2cd5ff3e1046ecae373f29b164b93
parent68ec8380149a314f261e25ca60c6f65b0436b9e4 (diff)
downloadpandoc-e6ee032a6de22f5a2dd18030d0956e67d1fc26ba.tar.gz
LaTeX reader: improved parsing of `\def`, `\let`.
We now correctly parse: ``` \def\bar{hello} \let\fooi\bar \def\fooii{\bar} \fooi +\fooii \def\bar{goodbye} \fooi +\fooii ```
-rw-r--r--src/Text/Pandoc/Readers/LaTeX.hs29
-rw-r--r--src/Text/Pandoc/Readers/LaTeX/Parsing.hs39
2 files changed, 41 insertions, 27 deletions
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
index 6c708c6ed..3751921ce 100644
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -1506,21 +1506,28 @@ macroDef =
letmacro :: PandocMonad m => LP m (Text, Macro)
letmacro = do
controlSeq "let"
- Tok _ (CtrlSeq name) _ <- anyControlSeq
- optional $ symbol '='
- spaces
- contents <- bracedOrToken
- return (name, Macro ExpandWhenDefined [] Nothing contents)
+ (name, contents) <- withVerbatimMode $ do
+ Tok _ (CtrlSeq name) _ <- withVerbatimMode anyControlSeq
+ optional $ symbol '='
+ spaces
+ -- we first parse in verbatim mode, and then expand macros,
+ -- because we don't want \let\foo\bar to turn into
+ -- \let\foo hello if we have previously \def\bar{hello}
+ contents <- bracedOrToken
+ return (name, contents)
+ contents' <- fromMaybe contents <$> doMacros' 0 contents
+ return (name, Macro ExpandWhenDefined [] Nothing contents')
defmacro :: PandocMonad m => LP m (Text, Macro)
-defmacro = try $ do
- controlSeq "def"
- Tok _ (CtrlSeq name) _ <- anyControlSeq
- argspecs <- many (argspecArg <|> argspecPattern)
+defmacro = try $
-- we use withVerbatimMode, because macros are to be expanded
-- at point of use, not point of definition
- contents <- withVerbatimMode bracedOrToken
- return (name, Macro ExpandWhenUsed argspecs Nothing contents)
+ withVerbatimMode $ do
+ controlSeq "def"
+ Tok _ (CtrlSeq name) _ <- anyControlSeq
+ argspecs <- many (argspecArg <|> argspecPattern)
+ contents <- bracedOrToken
+ return (name, Macro ExpandWhenUsed argspecs Nothing contents)
argspecArg :: PandocMonad m => LP m ArgSpec
argspecArg = do
diff --git a/src/Text/Pandoc/Readers/LaTeX/Parsing.hs b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
index 74305b824..c348ba572 100644
--- a/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
+++ b/src/Text/Pandoc/Readers/LaTeX/Parsing.hs
@@ -49,6 +49,7 @@ module Text.Pandoc.Readers.LaTeX.Parsing
, toksToString
, satisfyTok
, doMacros
+ , doMacros'
, setpos
, anyControlSeq
, anySymbol
@@ -451,22 +452,28 @@ doMacros' n inp = do
case M.lookup name macros of
Nothing -> return Nothing
Just (Macro expansionPoint argspecs optarg newtoks) -> do
- setInput ts
- args <- case optarg of
- Nothing -> getargs M.empty argspecs
- Just o -> do
- x <- option o bracketedToks
- getargs (M.singleton 1 x) argspecs
- -- first boolean param is true if we're tokenizing
- -- an argument (in which case we don't want to
- -- expand #1 etc.)
- ts' <- getInput
- let result = foldr (addTok False args spos) ts' newtoks
- case expansionPoint of
- ExpandWhenUsed ->
- doMacros' (n' + 1) result >>=
- maybe (return (Just result)) (return . Just)
- ExpandWhenDefined -> return $ Just result
+ let getargs' = do
+ args <- case optarg of
+ Nothing -> getargs M.empty argspecs
+ Just o -> do
+ x <- option o bracketedToks
+ getargs (M.singleton 1 x) argspecs
+ rest <- getInput
+ return (args, rest)
+ lstate <- getState
+ res <- lift $ runParserT getargs' lstate "args" ts
+ case res of
+ Left _ -> fail $ "Could not parse arguments for " ++
+ T.unpack name
+ Right (args, rest) -> do
+ -- first boolean param is true if we're tokenizing
+ -- an argument (in which case we don't want to
+ -- expand #1 etc.)
+ let result = foldr (addTok False args spos) rest newtoks
+ case expansionPoint of
+ ExpandWhenUsed ->
+ maybe (Just result) Just <$> doMacros' (n' + 1) result
+ ExpandWhenDefined -> return $ Just result
setpos :: SourcePos -> Tok -> Tok
setpos spos (Tok _ tt txt) = Tok spos tt txt