git.iko.soy/typeable/pandoc
on master help sign in
Successful parsing of all Linux mans, except zic.8
753a4d3Yan Pas
src/Text/Pandoc/Readers/Man.hs+29−9
@@ -149,12 +149,12 @@ readMan opts txt = do
149--
149--
150
150
151lexMan :: PandocMonad m => ManLexer m [ManToken]
151lexMan :: PandocMonad m => ManLexer m [ManToken]
152−lexMan = many (lexMacro <|> lexLine <|> lexEmptyLine)
152+lexMan = many (lexComment <|> lexMacro <|> lexLine <|> lexEmptyLine)
153
153
154parseMan :: PandocMonad m => ManParser m Pandoc
154parseMan :: PandocMonad m => ManParser m Pandoc
155parseMan = do
155parseMan = do
156 let parsers = [ try parseList, parseTitle, parsePara, parseSkippedContent
156 let parsers = [ try parseList, parseTitle, parsePara, parseSkippedContent
157− , parseCodeBlock, parseHeader, parseSkipMacro]
157+ , try parseCodeBlock, parseHeader, parseSkipMacro]
158 blocks <- many $ choice parsers
158 blocks <- many $ choice parsers
159 parserst <- getState
159 parserst <- getState
160 return $ Pandoc (stateMeta parserst) (filter (not . isNull) blocks)
160 return $ Pandoc (stateMeta parserst) (filter (not . isNull) blocks)
@@ -174,7 +174,7 @@ spacetab = char ' ' <|> char '\t'
174escapeLexer :: PandocMonad m => ManLexer m EscapeThing
174escapeLexer :: PandocMonad m => ManLexer m EscapeThing
175escapeLexer = do
175escapeLexer = do
176 char '\\'
176 char '\\'
177− choice [escChar, escFont]
177+ choice [escChar, escFont, escUnknown]
178 where
178 where
179
179
180 escChar :: PandocMonad m => ManLexer m EscapeThing
180 escChar :: PandocMonad m => ManLexer m EscapeThing
@@ -182,7 +182,7 @@ escapeLexer = do
182 let skipSeqs = ["%", "{", "}", "&", "\n", ":", "\"", "0", "c"]
182 let skipSeqs = ["%", "{", "}", "&", "\n", ":", "\"", "0", "c"]
183 subsSeqs = [ ("-", '-'), (" ", ' '), ("\\", '\\'), ("[lq]", '“'), ("[rq]", '”')
183 subsSeqs = [ ("-", '-'), (" ", ' '), ("\\", '\\'), ("[lq]", '“'), ("[rq]", '”')
184 , ("[em]", '—'), ("[en]", '–'), ("*(lq", '«'), ("*(rq", '»')
184 , ("[em]", '—'), ("[en]", '–'), ("*(lq", '«'), ("*(rq", '»')
185− , ("t", '\t'), ("e", '\\') ]
185+ , ("t", '\t'), ("e", '\\'), ("`", '`') ]
186 substitute :: PandocMonad m => (String,Char) -> ManLexer m EscapeThing
186 substitute :: PandocMonad m => (String,Char) -> ManLexer m EscapeThing
187 substitute (from,to) = try $ string from >> return (EChar to)
187 substitute (from,to) = try $ string from >> return (EChar to)
188 skip :: PandocMonad m => String -> ManLexer m EscapeThing
188 skip :: PandocMonad m => String -> ManLexer m EscapeThing
@@ -201,6 +201,7 @@ escapeLexer = do
201 , try (char '[' >> letterFont >>= \f -> char ']' >> return f)
201 , try (char '[' >> letterFont >>= \f -> char ']' >> return f)
202 , try $ string "[BI]" >> return ItalicBold
202 , try $ string "[BI]" >> return ItalicBold
203 , char '[' >> many letter >> char ']' >> return Regular
203 , char '[' >> many letter >> char ']' >> return Regular
204+ , digit >> return Regular
204 ]
205 ]
205 modifyState (\r -> r {fontKind = font})
206 modifyState (\r -> r {fontKind = font})
206 return $ EFont font
207 return $ EFont font
@@ -214,11 +215,27 @@ escapeLexer = do
214 , (char 'P' <|> char 'R') >> return Regular
215 , (char 'P' <|> char 'R') >> return Regular
215 ]
216 ]
216
217
218+ escUnknown :: PandocMonad m => ManLexer m EscapeThing
219+ escUnknown = do
220+ c <- anyChar
221+ pos <- getPosition
222+ logOutput $ SkippedContent ("Unknown escape seq \\" ++ [c]) pos
223+ return ENothing
224+
217currentFont :: PandocMonad m => ManLexer m FontKind
225currentFont :: PandocMonad m => ManLexer m FontKind
218currentFont = do
226currentFont = do
219 RoffState {fontKind = fk} <- getState
227 RoffState {fontKind = fk} <- getState
220 return fk
228 return fk
221
229
230+-- separate function from lexMacro since real man files sometimes do not follow the rules
231+lexComment :: PandocMonad m => ManLexer m ManToken
232+lexComment = do
233+ try $ string ".\\\""
234+ many space
235+ body <- many $ noneOf "\n"
236+ char '\n'
237+ return $ MComment body
238+
222lexMacro :: PandocMonad m => ManLexer m ManToken
239lexMacro :: PandocMonad m => ManLexer m ManToken
223lexMacro = do
240lexMacro = do
224 char '.' <|> char '\''
241 char '.' <|> char '\''
@@ -249,7 +266,7 @@ lexMacro = do
249
266
250 where
267 where
251
268
252− -- TODO rework args
269+ -- TODO better would be [[RoffStr]], since one arg may have different fonts
253 lexArgs :: PandocMonad m => ManLexer m [RoffStr]
270 lexArgs :: PandocMonad m => ManLexer m [RoffStr]
254 lexArgs = do
271 lexArgs = do
255 args <- many oneArg
272 args <- many oneArg
@@ -261,21 +278,24 @@ lexMacro = do
261 oneArg :: PandocMonad m => ManLexer m RoffStr
278 oneArg :: PandocMonad m => ManLexer m RoffStr
262 oneArg = do
279 oneArg = do
263 many1 spacetab
280 many1 spacetab
281+ many $ try $ string "\\\n"
264− quotedArg <|> plainArg
282+ try quotedArg <|> plainArg -- try, because there are some erroneous files, e.g. linux/bpf.2
265
283
266 plainArg :: PandocMonad m => ManLexer m RoffStr
284 plainArg :: PandocMonad m => ManLexer m RoffStr
267 plainArg = do
285 plainArg = do
286+ indents <- many spacetab
268 arg <- many1 $ escChar <|> (Just <$> noneOf " \t\n")
287 arg <- many1 $ escChar <|> (Just <$> noneOf " \t\n")
269 f <- currentFont
288 f <- currentFont
270− return (catMaybes arg, f)
289+ return (indents ++ catMaybes arg, f)
271
290
272 quotedArg :: PandocMonad m => ManLexer m RoffStr
291 quotedArg :: PandocMonad m => ManLexer m RoffStr
273 quotedArg = do
292 quotedArg = do
274 char '"'
293 char '"'
275− val <- catMaybes <$> many quotedChar
294+ val <- many quotedChar
276 char '"'
295 char '"'
296+ val2 <- many $ escChar <|> (Just <$> noneOf " \t\n")
277 f <- currentFont
297 f <- currentFont
278− return (val, f)
298+ return (catMaybes $ val ++ val2, f)
279
299
280 quotedChar :: PandocMonad m => ManLexer m (Maybe Char)
300 quotedChar :: PandocMonad m => ManLexer m (Maybe Char)
281 quotedChar = escChar <|> (Just <$> noneOf "\"\n") <|> (Just <$> try (string "\"\"" >> return '"'))
301 quotedChar = escChar <|> (Just <$> noneOf "\"\n") <|> (Just <$> try (string "\"\"" >> return '"'))