@@ -36,6 +36,9 @@ import qualified Data.Map as M
3636import Text.CSL hiding ( Cite(..), Citation(..) )
3737import qualified Text.CSL as CSL ( Cite(..) )
3838import Text.Pandoc.Definition
39+import Text.Pandoc.Shared (stringify)
40+import Text.ParserCombinators.Parsec
41+import Control.Monad
3942
4043-- | Process a 'Pandoc' document by adding citations formatted
4144-- according to a CSL style, using 'citeproc' from citeproc-hs.
@@ -152,7 +155,7 @@ setCitationNoteNum i = map $ \c -> c { citationNoteNum = i}
152155toCslCite :: Citation -> CSL.Cite
153156toCslCite c
154157 = let (l, s) = locatorWords $ citationSuffix c
155− (la,lo) = parseLocator $ unwords l
158+ (la,lo) = parseLocator l
156159 citMode = case citationMode c of
157160 AuthorInText -> (True, False)
158161 SuppressAuthor -> (False,True )
@@ -168,30 +171,34 @@ toCslCite c
168171 , CSL.citeHash = citationHash c
169172 }
170173
171−locatorWords :: [Inline] -> ([String], [Inline])
172−locatorWords (Space : t) = locatorWords t
173−locatorWords (Str "" : t) = locatorWords t
174−locatorWords a@(Str (',' : s) : t)
175− = if ws /= [] then (ws, t') else ([], a)
176− where
177− (ws, t') = locatorWords (Str s:t)
178−locatorWords i
179− = if any isDigit w then (w':ws, s'') else ([], i)
180− where
181− (w, s') = locatorWord i
182− (ws, s'') = locatorWords s'
183− w' = if ws == [] then w else w ++ ","
184−
185−locatorWord :: [Inline] -> (String, [Inline])
186−locatorWord (Space : r) = (" " ++ ts, r')
187− where
188− (ts, r') = locatorWord r
189−locatorWord (Str t : r)
190− | t' /= "" = (w , Str t' : r)
191− | otherwise = (t ++ ts, r' )
192− where
193− w = takeWhile (/= ',') t
194− t' = dropWhile (/= ',') t
195− (ts, r') = locatorWord r
196−locatorWord i = ("", i)
174+locatorWords :: [Inline] -> (String, [Inline])
175+locatorWords inp =
176+ case parse (liftM2 (,) pLocator getInput) "suffix" inp of
177+ Right r -> r
178+ Left _ -> ("",inp)
179+
180+pMatch :: (Inline -> Bool) -> GenParser Inline st Inline
181+pMatch condition = try $ do
182+ t <- anyToken
183+ guard $ condition t
184+ return t
185+
186+pSpace :: GenParser Inline st Inline
187+pSpace = pMatch (== Space)
188+
189+pLocator :: GenParser Inline st String
190+pLocator = try $ do
191+ optional $ pMatch (== Str ",")
192+ optional pSpace
193+ f <- many1 (notFollowedBy pSpace >> anyToken)
194+ gs <- many1 pWordWithDigits
195+ return $ stringify f ++ (' ' : unwords gs)
196+
197+pWordWithDigits :: GenParser Inline st String
198+pWordWithDigits = try $ do
199+ pSpace
200+ r <- many1 (notFollowedBy pSpace >> anyToken)
201+ let s = stringify r
202+ guard $ any isDigit s
203+ return s
197204