mirror of
https://github.com/jgm/pandoc.git
synced 2026-08-28 19:26:45 +00:00
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
```
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user