1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{- |
Module : Text.Pandoc.Parsing.Citations
Copyright : © 2006-2024 John MacFarlane
License : GPL-2.0-or-later
Maintainer : John MacFarlane <[email protected]>
Citation parsing.
-}
module Text.Pandoc.Parsing.Citations
( citeKey
)
where
import Control.Monad (guard, MonadPlus(mzero))
import Data.Char (isAlphaNum , isSpace)
import Data.Text (Text)
import Text.Pandoc.Sources
import Text.Parsec
( (<|>)
, Stream(..)
, ParsecT
, lookAhead
, many
, option
, try
)
import Text.Pandoc.Parsing.Capabilities (HasLastStrPosition, notAfterString)
import Text.Pandoc.Parsing.General
import qualified Data.Text as T
citeKey :: (Stream s m Char, UpdateSourcePos s Char, HasLastStrPosition st)
=> Bool -- ^ If True, allow expanded @{..} syntax.
-> ParsecT s st m (Bool, Text)
citeKey allowBraced = try $ do
guard =<< notAfterString
suppress_author <- option False (True <$ char '-')
char '@'
key <- simpleCiteIdentifier
<|> if allowBraced
then charsInBalanced '{' '}'
(T.singleton <$> (satisfy (not . isSpace)))
else mzero
return (suppress_author, key)
simpleCiteIdentifier :: (Stream s m Char, UpdateSourcePos s Char)
=> ParsecT s st m Text
simpleCiteIdentifier = do
firstChar <- alphaNum <|> char '_' <|> char '*' -- @* for wildcard in nocite
let regchar = satisfy (\c -> isAlphaNum c || c == '_')
let internal p = try $ p <* lookAhead regchar
rest <- many $ regchar <|> internal (oneOf ":.#$%&-+?<>~/") <|>
try (oneOf ":/" <* lookAhead (char '/'))
return $ T.pack $ firstChar:rest
|