@@ -153,21 +153,45 @@ characterCodeMap =
153 M.fromList $ map (\(x,y) -> (y,x)) $ characterCodes ++ combiningAccents
153 M.fromList $ map (\(x,y) -> (y,x)) $ characterCodes ++ combiningAccents
155escapeLexer :: PandocMonad m => ManLexer m String
155escapeLexer :: PandocMonad m => ManLexer m String
156−escapeLexer = do
156+escapeLexer = try $ do
157 char '\\'
157 char '\\'
158+ c <- noneOf ['*','$'] -- see escStar, macroArg
158− twoCharGlyph <|> bracketedGlyph <|> escFont <|> escSingle <|> escStar
161+ '[' -> bracketedGlyph
163+ '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment
164+ '#' -> mempty <$ manyTill anyChar newline
165+ '%' -> return mempty
166+ '{' -> return mempty
167+ '}' -> return mempty
168+ '&' -> return mempty
169+ '\n' -> return mempty
170+ ':' -> return mempty
171+ '0' -> return mempty
172+ 'c' -> return mempty
184+ _ -> escUnknown [c] "\xFFFD"
162 twoCharGlyph = do
188 twoCharGlyph = do
164 cs <- count 2 anyChar
189 cs <- count 2 anyChar
165 case M.lookup cs characterCodeMap of
190 case M.lookup cs characterCodeMap of
166 Just c -> return [c]
191 Just c -> return [c]
167 Nothing -> escUnknown ('\\':'(':cs) "\xFFFD"
192 Nothing -> escUnknown ('\\':'(':cs) "\xFFFD"
169 bracketedGlyph =
194 bracketedGlyph =
171 ( ucharCode `sepBy1` (char '_')
195 ( ucharCode `sepBy1` (char '_')
172 <|> charCode `sepBy1` (many1 Parsec.space)
196 <|> charCode `sepBy1` (many1 Parsec.space)
173 ) <* char ']'
197 ) <* char ']'
@@ -185,65 +209,9 @@ escapeLexer = do
185 Nothing -> escUnknown ("\\[" ++ cs ++ "]") '\xFFFD'
209 Nothing -> escUnknown ("\\[" ++ cs ++ "]") '\xFFFD'
186 Just c -> return c
210 Just c -> return c
191− cs <- count 2 anyChar
193− "HF" -> mempty <$ modifyState (\st ->
194− st{fontKind = S.insert Bold (fontKind st) })
195− "Tm" -> return "\x2122"
196− "lq" -> return "\x201c"
197− "rq" -> return "\x201d"
198− _ -> resolveString cs <|> escUnknown ("\\(" ++ cs) "\xFFFD")
201− cs <- many (noneOf "\t\n\r ]")
203− resolveString cs <|> escUnknown ("\\[" ++ cs ++ "]") "\xFFFD" )
207− 'R' -> return "\xae"
208− 'S' -> return mempty -- switch back to default font size
209− _ -> resolveString [c] <|> escUnknown ['\\',c] "\xFFFD" )
211− -- strings and macros share namespace
212− resolveString stringname = do
213− ManTokens ts <- resolveMacro stringname []
214− case Foldable.toList ts of
215− [MLine [RoffStr (s,_)]] -> return s
219− c <- noneOf ['*','[','(']
221− '"' -> mempty <$ skipMany (satisfy (/='\n')) -- line comment
222− '#' -> mempty <$ manyTill anyChar newline
223− '%' -> return mempty
224− '{' -> return mempty
225− '}' -> return mempty
226− '&' -> return mempty
227− '\n' -> return mempty
228− ':' -> return mempty
229− '0' -> return mempty
230− 'c' -> return mempty
242− _ -> escUnknown [c] "\xFFFD"
244 escFont :: PandocMonad m => ManLexer m String
213 escFont :: PandocMonad m => ManLexer m String
245 escFont = do
214 escFont = do
247 font <- choice [ S.singleton <$> letterFontKind
215 font <- choice [ S.singleton <$> letterFontKind
248 , char '(' >> anyChar >> anyChar >> return (S.singleton Regular)
216 , char '(' >> anyChar >> anyChar >> return (S.singleton Regular)
249 , try lettersFont
217 , try lettersFont
@@ -371,68 +339,107 @@ lexArgs = do
372 plainArg :: PandocMonad m => ManLexer m [LinePart]
340 plainArg :: PandocMonad m => ManLexer m [LinePart]
373 plainArg = do
341 plainArg = do
374− -- TODO skip initial spaces, then parse many linePart til a spaec
375 skipMany spacetab
342 skipMany spacetab
376− many (macroArg <|> esc <|> regularText <|> unescapedQuote)
344+ many (macroArg <|> esc <|> regularText <|> unescapedQuote <|> escStar)
377 where unescapedQuote = do
345 where unescapedQuote = do
379 fonts <- currentFont
347 fonts <- currentFont
380− return $ RoffStr ("\"", fonts)
348+ return [RoffStr ("\"", fonts)]
383 quotedArg :: PandocMonad m => ManLexer m [LinePart]
351 quotedArg :: PandocMonad m => ManLexer m [LinePart]
384 quotedArg = do
352 quotedArg = do
386− xs <- many (macroArg <|> esc <|> regularText <|> spaceTabChar
355+ many (macroArg <|> esc <|> escStar <|> regularText
387− <|> escapedQuote)
356+ <|> spaceTabChar <|> escapedQuote)
389 return xs
358 return xs
390 where escapedQuote = try $ do
359 where escapedQuote = try $ do
393 fonts <- currentFont
362 fonts <- currentFont
394− return $ RoffStr ("\"", fonts)
363+ return [RoffStr ("\"", fonts)]
365+escStar :: PandocMonad m => ManLexer m [LinePart]
370+ let retstr s = return [RoffStr (s, font)]
374+ cs <- count 2 anyChar
376+ "HF" -> mempty <$ modifyState (\st ->
377+ st{fontKind = S.insert Bold (fontKind st) })
378+ "Tm" -> retstr "\x2122"
379+ "lq" -> retstr "\x201c"
380+ "rq" -> retstr "\x201d"
381+ _ -> resolveString cs
383+ cs <- many (noneOf "\t\n\r ]")
386+ 'R' -> retstr "\xae"
387+ 'S' -> return mempty -- switch back to default font size
388+ _ -> resolveString [c]
392+ -- strings and macros share namespace
393+ resolveString stringname = do
394+ ManTokens ts <- resolveMacro stringname []
395+ case Foldable.toList ts of
396+ [MLine xs] -> return xs
399+ report $ SkippedContent ("unknown string " ++ stringname) pos
396lexLine :: PandocMonad m => ManLexer m ManTokens
402lexLine :: PandocMonad m => ManLexer m ManTokens
397lexLine = do
403lexLine = do
398− lnparts <- many1 linePart
404+ lnparts <- mconcat <$> many1 linePart
400 return $ singleTok $ MLine lnparts
406 return $ singleTok $ MLine lnparts
403−linePart :: PandocMonad m => ManLexer m LinePart
409+linePart :: PandocMonad m => ManLexer m [LinePart]
410+linePart = macroArg <|> esc <|> escStar <|>
404−linePart = macroArg <|> esc <|> regularText <|> quoteChar <|> spaceTabChar
411+ regularText <|> quoteChar <|> spaceTabChar
406−macroArg :: PandocMonad m => ManLexer m LinePart
413+macroArg :: PandocMonad m => ManLexer m [LinePart]
407macroArg = try $ do
414macroArg = try $ do
408 char '\\'
415 char '\\'
410 x <- digit
417 x <- digit
411− return $ MacroArg $ ord x - ord '0'
418+ return [MacroArg $ ord x - ord '0']
413−esc :: PandocMonad m => ManLexer m LinePart
420+esc :: PandocMonad m => ManLexer m [LinePart]
415 s <- escapeLexer
422 s <- escapeLexer
416 font <- currentFont
423 font <- currentFont
417− return $ RoffStr (s, font)
424+ return [RoffStr (s, font)]
419−regularText :: PandocMonad m => ManLexer m LinePart
426+regularText :: PandocMonad m => ManLexer m [LinePart]
420regularText = do
427regularText = do
421 s <- many1 $ noneOf "\n\r\t \\\""
428 s <- many1 $ noneOf "\n\r\t \\\""
422 font <- currentFont
429 font <- currentFont
423− return $ RoffStr (s, font)
430+ return [RoffStr (s, font)]
425−quoteChar :: PandocMonad m => ManLexer m LinePart
432+quoteChar :: PandocMonad m => ManLexer m [LinePart]
426quoteChar = do
433quoteChar = do
428 font <- currentFont
435 font <- currentFont
429− return $ RoffStr ("\"", font)
436+ return [RoffStr ("\"", font)]
431−spaceTabChar :: PandocMonad m => ManLexer m LinePart
438+spaceTabChar :: PandocMonad m => ManLexer m [LinePart]
432spaceTabChar = do
439spaceTabChar = do
433 c <- spacetab
440 c <- spacetab
434 font <- currentFont
441 font <- currentFont
435− return $ RoffStr ([c], font)
442+ return [RoffStr ([c], font)]
437lexEmptyLine :: PandocMonad m => ManLexer m ManTokens
444lexEmptyLine :: PandocMonad m => ManLexer m ManTokens
438lexEmptyLine = char '\n' >> return (singleTok MEmptyLine)
445lexEmptyLine = char '\n' >> return (singleTok MEmptyLine)