git.iko.soy/typeable/pandoc
on master help sign in
Roff reader: improve lexing of conditionals.

Partially addreses #5039.

commit9e369e90164fe832d4e09ba51fbdf4ba4d2f9ba1 authorJohn MacFarlane <jgm@berkeley.edu> dateFri 2 Nov 2018, 17:23 (8 years ago) parente01ca77
1 file changed+49−28
src/Text/Pandoc/Readers/Roff.hs+49−28
src/Text/Pandoc/Readers/Roff.hs+49−28
@@ -48,7 +48,7 @@ where
4848
4949import Prelude
5050import Safe (lastDef)
51−import Control.Monad (void, mzero, guard, when, mplus)
51+import Control.Monad (void, mzero, mplus)
5252import Control.Monad.Except (throwError)
5353import Text.Pandoc.Class
5454 (getResourcePath, readFileFromDirs, PandocMonad(..), report)
@@ -56,7 +56,7 @@ import Data.Char (isLower, toLower, toUpper, chr,
5656 isAscii, isAlphaNum, isSpace)
5757import Data.Default (Default)
5858import qualified Data.Map as M
59−import Data.List (intercalate, isSuffixOf)
59+import Data.List (intercalate)
6060import qualified Data.Text as T
6161import Text.Pandoc.Logging (LogMessage(..))
6262import Text.Pandoc.Options
@@ -117,11 +117,12 @@ data RoffMode = NormalMode
117117 | CopyMode
118118 deriving Show
119119
120−data RoffState = RoffState { customMacros :: M.Map String RoffTokens
121− , prevFont :: FontSpec
122− , currentFont :: FontSpec
123− , tableTabChar :: Char
124− , roffMode :: RoffMode
120+data RoffState = RoffState { customMacros :: M.Map String RoffTokens
121+ , prevFont :: FontSpec
122+ , currentFont :: FontSpec
123+ , tableTabChar :: Char
124+ , roffMode :: RoffMode
125+ , lastExpression :: Maybe Bool
125126 } deriving Show
126127
127128instance Default RoffState where
@@ -137,6 +138,7 @@ instance Default RoffState where
137138 , currentFont = defaultFontSpec
138139 , tableTabChar = '\t'
139140 , roffMode = NormalMode
141+ , lastExpression = Nothing
140142 }
141143
142144type RoffLexer m = ParserT [Char] RoffState m
@@ -349,15 +351,16 @@ lexComment = do
349351lexMacro :: PandocMonad m => RoffLexer m RoffTokens
350352lexMacro = do
351353 pos <- getPosition
352− guard $ sourceColumn pos == 1
354+ -- we don't want this because of '.ie .B foo':
355+ -- guard $ sourceColumn pos == 1
353356 char '.' <|> char '\''
354357 skipMany spacetab
355358 macroName <- many (satisfy (not . isSpace))
356359 case macroName of
357360 "nop" -> return mempty
358− "ie" -> lexConditional
359− "if" -> lexConditional
360− "el" -> skipConditional
361+ "ie" -> lexConditional "ie"
362+ "if" -> lexConditional "if"
363+ "el" -> lexConditional "el"
361364 "TS" -> lexTable pos
362365
363366 _ -> do
@@ -484,18 +487,43 @@ tableColFormat = do
484487
485488-- We don't fully handle the conditional. But we do
486489-- include everything under '.ie n', which occurs commonly
487−-- in man pages. We always skip the '.el' part.
488−lexConditional :: PandocMonad m => RoffLexer m RoffTokens
489−lexConditional = do
490+-- in man pages.
491+lexConditional :: PandocMonad m => String -> RoffLexer m RoffTokens
492+lexConditional mname = do
493+ pos <- getPosition
494+ skipMany spacetab
495+ mbtest <- if mname == "el"
496+ then fmap not . lastExpression <$> getState
497+ else expression
490498 skipMany spacetab
491− lexNCond <|> skipConditional
499+ st <- getState -- save state, so we can reset it
500+ ifPart <- lexGroup
501+ <|> (char '\\' >> newline >> manToken)
502+ <|> manToken
503+ case mbtest of
504+ Nothing -> do
505+ putState st -- reset state, so we don't record macros in skipped section
506+ report $ SkippedContent ('.':mname) pos
507+ return mempty
508+ Just True -> return ifPart
509+ Just False -> do
510+ putState st
511+ return mempty
492512
493−-- n means nroff mode
494−lexNCond :: PandocMonad m => RoffLexer m RoffTokens
495−lexNCond = do
496− newline
497− many1 spacetab
498− lexGroup <|> manToken
513+expression :: PandocMonad m => RoffLexer m (Maybe Bool)
514+expression = do
515+ raw <- charsInBalanced '(' ')' (satisfy (/= '\n'))
516+ <|> many1 nonspaceChar
517+ returnValue $
518+ case raw of
519+ "1" -> Just True
520+ "n" -> Just True -- nroff mode
521+ "t" -> Just False -- troff mode
522+ _ -> Nothing
523+ where
524+ returnValue v = do
525+ modifyState $ \st -> st{ lastExpression = v }
526+ return v
499527
500528lexGroup :: PandocMonad m => RoffLexer m RoffTokens
501529lexGroup = do
@@ -505,13 +533,6 @@ lexGroup = do
505533 groupstart = try $ string "\\{\\" >> newline
506534 groupend = try $ string "\\}" >> eofline
507535
508−skipConditional :: PandocMonad m => RoffLexer m RoffTokens
509−skipConditional = do
510− rest <- anyLine
511− when ("\\{\\" `isSuffixOf` rest) $
512− void $ manyTill anyChar (try (string "\\}"))
513− return mempty
514−
515536lexIncludeFile :: PandocMonad m => [Arg] -> RoffLexer m RoffTokens
516537lexIncludeFile args = do
517538 pos <- getPosition