summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2010-11-12 00:37:44 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2010-11-12 00:37:44 -0800
commit79bab2d210ffadaf4f3b6a2a7ebc33ea546dd5e0 (patch)
tree00a7781d36f51fb186d608083c9657ed371729c5
parent5c6dc5767df68ae739138ae38f2baf75949ef3e6 (diff)
Revised citation parsers for markdown reader.
Added a form for in-text citations: @doe99 [30; see also @smith99].
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs140
1 files changed, 96 insertions, 44 deletions
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 7a42d903e..eb9646df2 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -373,6 +373,7 @@ attributes = try $ do
attribute :: GenParser Char st ([Char], [[Char]], [([Char], [Char])])
attribute = identifierAttr <|> classAttr <|> keyValAttr
+
identifier :: GenParser Char st [Char]
identifier = do
first <- letter
@@ -912,7 +913,7 @@ inlineParsers = [ str
, note
, inlineNote
, link
- , inlineCitation
+ , cite
, image
, math
, strikeout
@@ -1303,48 +1304,99 @@ rawHtmlInline' = do
else choice [htmlComment, anyHtmlInlineTag]
return $ HtmlInline result
-inlineCitation :: GenParser Char ParserState Inline
-inlineCitation = try $ do
+-- Citations
+
+cite :: GenParser Char ParserState Inline
+cite = do
failIfStrict
- cit <- citeMarker
- let citations = readWith parseCitation defaultParserState cit
- mr <- mapM chkCit citations
- if catMaybes mr /= []
- then return $ Cite citations []
- else fail "no citation found"
-
-chkCit :: Citation -> GenParser Char ParserState (Maybe Citation)
-chkCit t = do
+ textualCite <|> normalCite
+
+spnl :: GenParser Char st ()
+spnl = try $ skipSpaces >> optional newline >> skipSpaces >>
+ notFollowedBy (char '\n')
+
+textualCite :: GenParser Char ParserState Inline
+textualCite = try $ do
+ key <- citeKey
st <- getState
- case lookupKeySrc (stateKeys st) (Key [Str $ citationId t]) of
- Just _ -> fail "This is a link"
- Nothing -> if elem (citationId t) $ stateCitations st
- then return $ Just t
- else return $ Nothing
-
-citeMarker :: GenParser Char ParserState String
-citeMarker = char '[' >> manyTill ( noneOf "\n" <|> (newline >>~ notFollowedBy blankline) ) (char ']')
-
-parseCitation :: GenParser Char ParserState [Citation]
-parseCitation = try $ sepBy (parseLabel) (skipMany1 $ char ';')
-
-parseLabel :: GenParser Char ParserState Citation
-parseLabel = try $ do
- r <- many (noneOf ";")
- let t' s = if s /= [] then tail s else []
- trim = unwords . words
- pref = takeWhile (/= '@') r
- rest = t' $ dropWhile (/= '@') r
- cit = takeWhile (/= ',') rest
- loc = t' $ dropWhile (/= ',') rest
- (p,na) = if pref /= [] && last pref == '-'
- then (init pref, True )
- else (pref , False)
- (p',o) = if p /= [] && last p == '+'
- then (init p , True )
- else (p , False)
- mode = case (na,o) of
- (True, False) -> SuppressAuthor
- (False,True ) -> AuthorInText
- _ -> NormalCitation
- return $ Citation cit (trim p') (trim loc) mode 0 0
+ unless (key `elem` stateCitations st) $
+ fail "not a citation"
+ let first = Citation{ citationId = key
+ , citationPrefix = ""
+ , citationLocator = ""
+ , citationMode = AuthorInText
+ , citationNoteNum = 0
+ , citationHash = 0
+ }
+ option (Cite [first] []) $ try $ do
+ spnl
+ char '['
+ spnl
+ bareloc <- option "" locator
+ rest <- many $ try $ do
+ char ';'
+ spnl
+ citation
+ spnl
+ char ']'
+ let first' = if null bareloc
+ then first
+ else first{ citationLocator = bareloc
+ , citationMode = AuthorInText }
+ return $ Cite (first' : rest) []
+
+normalCite :: GenParser Char ParserState Inline
+normalCite = try $ do
+ cites <- citeList
+ return $ Cite cites []
+
+citeKey :: GenParser Char st String
+citeKey = try $ do
+ char '@'
+ first <- letter
+ rest <- many $ noneOf ",;]@ \t\n"
+ return (first:rest)
+
+locator :: GenParser Char st String
+locator = try $ do
+ optional $ char ','
+ spnl
+ -- TODO should eventually be list of inlines
+ many1 $ (char '\\' >> oneOf "];\n") <|> noneOf "];\n" <|>
+ (char '\n' >> notFollowedBy blankline >> return ' ')
+
+prefix :: GenParser Char st String
+prefix = try $ liftM removeLeadingTrailingSpace $
+ many $ (char '\\' >> anyChar) <|> noneOf "@]\n" <|>
+ (char '-' >> notFollowedBy (char '@') >> return '-') <|>
+ (char '\n' >> notFollowedBy blankline >> return ' ')
+
+citeList :: GenParser Char st [Citation]
+citeList = try $ do
+ char '['
+ spnl
+ first <- citation
+ spnl
+ rest <- many $ try $ do
+ char ';'
+ spnl
+ citation
+ spnl
+ char ']'
+ return (first:rest)
+
+citation :: GenParser Char st Citation
+citation = try $ do
+ suppress_auth <- option False (char '-' >> return True)
+ pref <- prefix
+ key <- citeKey
+ loc <- locator
+ return $ Citation{ citationId = key
+ , citationPrefix = pref
+ , citationLocator = loc
+ , citationMode = if suppress_auth
+ then SuppressAuthor
+ else NormalCitation
+ , citationNoteNum = 0
+ , citationHash = 0
+ }