{-# LANGUAGE TupleSections #-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
{-# OPTIONS_GHC -fno-warn-unused-local-binds #-}

module Bio.Uniprot.Parser where

import           Prelude              hiding (null)
import qualified Prelude              as P (concat, init, last, null, tail)

import           Bio.Uniprot.Type
import           Control.Applicative  (liftA2, (<|>))
import           Control.Monad        (unless)
import           Data.Attoparsec.Text
import           Data.Bifunctor       (second)
import           Data.Char            (isSpace)
import           Data.Functor         (($>))
import           Data.Text            (Text, append, isPrefixOf, null, pack,
                                       splitOn, unpack)

-- | Describes possible name type of DE section.
data NameType = RecName | AltName | SubName | Flags | None
  deriving (Int -> NameType -> ShowS
[NameType] -> ShowS
NameType -> String
(Int -> NameType -> ShowS)
-> (NameType -> String) -> ([NameType] -> ShowS) -> Show NameType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NameType] -> ShowS
$cshowList :: [NameType] -> ShowS
show :: NameType -> String
$cshow :: NameType -> String
showsPrec :: Int -> NameType -> ShowS
$cshowsPrec :: Int -> NameType -> ShowS
Show)

-- | Parses ID line of UniProt-KB text file.
parseID :: Parser ID
parseID :: Parser ID
parseID = do
    Text -> Parser Text
string Text
"ID   "
    Text
entryName <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Z0-9_")
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Status
status <- (Text -> Parser Text
string Text
"Reviewed" Parser Text -> Status -> Parser Text Status
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Status
Reviewed) Parser Text Status -> Parser Text Status -> Parser Text Status
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
              (Text -> Parser Text
string Text
"Unreviewed" Parser Text -> Status -> Parser Text Status
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Status
Unreviewed)
    Char -> Parser Text Char
char Char
';'
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Int
seqLength <- Parser Int
forall a. Integral a => Parser a
decimal
    Parser Text Char
space Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"AA."
    ID -> Parser ID
forall (f :: * -> *) a. Applicative f => a -> f a
pure ID :: Text -> Status -> Int -> ID
ID{Int
Text
Status
seqLength :: Int
status :: Status
entryName :: Text
seqLength :: Int
status :: Status
entryName :: Text
..}

-- | Parses AC lines of UniProt-KB text file.
parseAC :: Parser AC
parseAC :: Parser AC
parseAC = do
    Parser ()
parseStartAC
    [Text]
initAC <- [[Text]] -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
P.concat ([[Text]] -> [Text]) -> Parser Text [[Text]] -> Parser Text [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text [Text] -> Parser Text [[Text]]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text [Text]
parseOneAC Parser Text [Text] -> Parser () -> Parser Text [Text]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine Parser Text [Text] -> Parser () -> Parser Text [Text]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
parseStartAC)
    [Text]
lastAC <- Parser Text [Text]
parseOneAC
    let accessionNumbers :: [Text]
accessionNumbers = [Text]
initAC [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
lastAC
    AC -> Parser AC
forall (f :: * -> *) a. Applicative f => a -> f a
pure AC :: [Text] -> AC
AC{[Text]
accessionNumbers :: [Text]
accessionNumbers :: [Text]
..}
  where
    parseStartAC :: Parser ()
    parseStartAC :: Parser ()
parseStartAC = Text -> Parser Text
string Text
"AC" Parser Text -> Parser Text String -> Parser Text String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
3 Parser Text Char
space Parser Text String -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

    parseOneAC :: Parser [Text]
    parseOneAC :: Parser Text [Text]
parseOneAC = Parser Text -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Parser Text -> Parser Text [Text])
-> Parser Text -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ do
        Text
res <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Z0-9_")
        Char -> Parser Text Char
char Char
';'
        Char -> Parser Text Char -> Parser Text Char
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Char
' ' ((Char -> Bool) -> Parser Text Char
satisfy Char -> Bool
isHorizontalSpace)
        Text -> Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
res

-- | Parses 3 DT lines of UniProt-KB text file.
parseDT :: Parser DT
parseDT :: Parser DT
parseDT = do
    (Text
dbIntegrationDate, Text
dbName) <- Text -> Parser (Text, Text)
parseOneDT Text
"integrated into UniProtKB/" Parser (Text, Text) -> Parser () -> Parser (Text, Text)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine
    (Text
seqVersionDate, Int
seqVersion) <- (Text -> Int) -> (Text, Text) -> (Text, Int)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (String -> Int
forall a. Read a => String -> a
read (String -> Int) -> (Text -> String) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack) ((Text, Text) -> (Text, Int))
-> Parser (Text, Text) -> Parser Text (Text, Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser (Text, Text)
parseOneDT Text
"sequence version " Parser Text (Text, Int) -> Parser () -> Parser Text (Text, Int)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine
    (Text
entryVersionDate, Int
entryVersion) <- (Text -> Int) -> (Text, Text) -> (Text, Int)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (String -> Int
forall a. Read a => String -> a
read (String -> Int) -> (Text -> String) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack) ((Text, Text) -> (Text, Int))
-> Parser (Text, Text) -> Parser Text (Text, Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser (Text, Text)
parseOneDT Text
"entry version "
    DT -> Parser DT
forall (f :: * -> *) a. Applicative f => a -> f a
pure DT :: Text -> Text -> Text -> Int -> Text -> Int -> DT
DT{Int
Text
entryVersion :: Int
entryVersionDate :: Text
seqVersion :: Int
seqVersionDate :: Text
dbName :: Text
dbIntegrationDate :: Text
entryVersion :: Int
entryVersionDate :: Text
seqVersion :: Int
seqVersionDate :: Text
dbName :: Text
dbIntegrationDate :: Text
..}
  where
    parseOneDT :: Text -> Parser (Text, Text)
    parseOneDT :: Text -> Parser (Text, Text)
parseOneDT Text
txt = do
        Text -> Parser Text
string Text
"DT   "
        Text
day <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Z0-9-")
        Char -> Parser Text Char
char Char
','
        Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
        Text -> Parser Text
string Text
txt
        Text
x <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Za-z0-9_-")
        Char -> Parser Text Char
char Char
'.'
        (Text, Text) -> Parser (Text, Text)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
day, Text
x)

-- | Parses DE lines of UniProt-KB text file.
parseDE :: Parser DE
parseDE :: Parser DE
parseDE = do
    Maybe Name
recName  <- Parser Name -> Parser (Maybe Name)
forall a. Parser a -> Parser (Maybe a)
optional (Parser Name -> Parser (Maybe Name))
-> Parser Name -> Parser (Maybe Name)
forall a b. (a -> b) -> a -> b
$ Int -> NameType -> Parser Name
parseNameDE Int
0 NameType
RecName
    [AltName]
altNames <- Parser Text AltName -> Parser Text [AltName]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser Text AltName
parseAltDE Int
0)
    [Name]
subNames <- Parser Name -> Parser Text [Name]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser Name -> Parser Name
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> NameType -> Parser Name
parseNameDE Int
0 NameType
SubName)
    [DE]
includes <- Parser DE -> Parser Text [DE]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser DE -> Parser DE
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Text -> Parser DE
parseInternal Text
"Includes")
    [DE]
contains <- Parser DE -> Parser Text [DE]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser DE -> Parser DE
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Text -> Parser DE
parseInternal Text
"Contains")
    [Flag]
flags    <- [Flag] -> Parser Text [Flag] -> Parser Text [Flag]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser ()
endOfLine Parser () -> Parser Text [Flag] -> Parser Text [Flag]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text [Flag]
parseFlagsDE)
    DE -> Parser DE
forall (f :: * -> *) a. Applicative f => a -> f a
pure DE :: Maybe Name -> [AltName] -> [Name] -> [DE] -> [DE] -> [Flag] -> DE
DE{[DE]
[Flag]
[AltName]
[Name]
Maybe Name
flags :: [Flag]
contains :: [DE]
includes :: [DE]
subNames :: [Name]
altNames :: [AltName]
recName :: Maybe Name
flags :: [Flag]
contains :: [DE]
includes :: [DE]
subNames :: [Name]
altNames :: [AltName]
recName :: Maybe Name
..}
  where
    -- | Parses name section like RecName, AltName or SubName.
    parseNameDE :: Int -> NameType -> Parser Name
    parseNameDE :: Int -> NameType -> Parser Name
parseNameDE Int
indent NameType
nameType = do
        Text
fullName <- Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
nameType Text
"Full"
        [Text]
shortName <- Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text -> Parser Text [Text])
-> Parser Text -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
None Text
"Short"
        [Text]
ecNumber <- Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text -> Parser Text [Text])
-> Parser Text -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
None Text
"EC"
        Name -> Parser Name
forall (f :: * -> *) a. Applicative f => a -> f a
pure Name :: Text -> [Text] -> [Text] -> Name
Name{[Text]
Text
ecNumber :: [Text]
shortName :: [Text]
fullName :: Text
ecNumber :: [Text]
shortName :: [Text]
fullName :: Text
..}

    -- | Parses flag line of DE section
    parseFlagsDE :: Parser [Flag]
    parseFlagsDE :: Parser Text [Flag]
parseFlagsDE = (Text -> Flag) -> [Text] -> [Flag]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Flag
forall a. Read a => String -> a
read (String -> Flag) -> (Text -> String) -> Text -> Flag
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack) ([Text] -> [Flag]) -> (Text -> [Text]) -> Text -> [Flag]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                       (Text
"; " Text -> Text -> [Text]
`splitOn`) (Text -> [Flag]) -> Parser Text -> Parser Text [Flag]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Text -> Parser Text
parseDELine Int
0 NameType
Flags Text
""

    -- | Parses AltName lines of DE section
    parseAltDE :: Int -> Parser AltName
    parseAltDE :: Int -> Parser Text AltName
parseAltDE Int
indent =
      (Name -> AltName
Simple (Name -> AltName) -> Parser Name -> Parser Text AltName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Parser Name
parseNameDE Int
indent NameType
AltName) Parser Text AltName -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Text -> AltName
Allergen (Text -> AltName) -> Parser Text -> Parser Text AltName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
AltName Text
"Allergen") Parser Text AltName -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Text -> AltName
Biotech (Text -> AltName) -> Parser Text -> Parser Text AltName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
AltName Text
"Biotech") Parser Text AltName -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Text -> AltName
CDAntigen (Text -> AltName) -> Parser Text -> Parser Text AltName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
AltName Text
"CD_antigen") Parser Text AltName -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Text -> AltName
INN (Text -> AltName) -> Parser Text -> Parser Text AltName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
AltName Text
"INN")

    -- | Parses any DE line
    parseDELine :: Int -> NameType -> Text -> Parser Text
    parseDELine :: Int -> NameType -> Text -> Parser Text
parseDELine Int
indent NameType
nameType Text
tpe = do
        Text -> Parser Text
string Text
"DE   "
        Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
indent (Char -> Parser Text Char
char Char
' ')
        case NameType
nameType of
          NameType
None -> Text -> Parser Text
string Text
"         "
          NameType
a    -> Text -> Parser Text
string (Text -> Parser Text) -> Text -> Parser Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text
append (String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ NameType -> String
forall a. Show a => a -> String
show NameType
a) Text
": "
        Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Text -> Bool
null Text
tpe) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$ do
            Text -> Parser Text
string Text
tpe
            Text -> Parser Text
string Text
"="
            () -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Text
result <- String -> Text
pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine))
        Text -> Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Parser Text) -> ([Text] -> Text) -> [Text] -> Parser Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
forall a. [a] -> a
head ([Text] -> Parser Text) -> [Text] -> Parser Text
forall a b. (a -> b) -> a -> b
$ Text
" {ECO" Text -> Text -> [Text]
`splitOn` Text
result

    -- | Parses internal DE entities
    parseInternal :: Text -> Parser DE
    parseInternal :: Text -> Parser DE
parseInternal Text
name = do
        Text -> Parser Text
string Text
"DE   " Parser Text -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
name Parser Text -> Parser Text Char -> Parser Text Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> Parser Text Char
char Char
':'
        Parser ()
endOfLine
        Maybe Name
recName  <- Parser Name -> Parser (Maybe Name)
forall a. Parser a -> Parser (Maybe a)
optional (Parser Name -> Parser (Maybe Name))
-> Parser Name -> Parser (Maybe Name)
forall a b. (a -> b) -> a -> b
$ Int -> NameType -> Parser Name
parseNameDE Int
2 NameType
RecName
        [AltName]
altNames <- Parser Text AltName -> Parser Text [AltName]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser Text AltName -> Parser Text AltName
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser Text AltName
parseAltDE Int
2)
        DE -> Parser DE
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DE -> Parser DE) -> DE -> Parser DE
forall a b. (a -> b) -> a -> b
$ Maybe Name -> [AltName] -> [Name] -> [DE] -> [DE] -> [Flag] -> DE
DE Maybe Name
recName [AltName]
altNames [] [] [] []

-- | Parses DE lines of UniProt-KB text file.
parseGN :: Parser [GN]
parseGN :: Parser [GN]
parseGN = do
    Text -> Parser Text
string Text
"GN   "
    Maybe Text
geneName <- Parser Text -> Parser (Maybe Text)
forall a. Parser a -> Parser (Maybe a)
optional (Parser Text -> Parser (Maybe Text))
-> Parser Text -> Parser (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text
parseDefItem Text
"Name"
    Parser () -> Parser (Maybe ())
forall a. Parser a -> Parser (Maybe a)
optional (Parser () -> Parser (Maybe ())) -> Parser () -> Parser (Maybe ())
forall a b. (a -> b) -> a -> b
$ Text -> Parser ()
parseBreak Text
"GN"
    [Text]
synonyms <- [Text] -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser Text [Text] -> Parser Text [Text])
-> Parser Text [Text] -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text [Text]
parseGNList Text
"Synonyms"
    Parser () -> Parser (Maybe ())
forall a. Parser a -> Parser (Maybe a)
optional (Parser () -> Parser (Maybe ())) -> Parser () -> Parser (Maybe ())
forall a b. (a -> b) -> a -> b
$ Text -> Parser ()
parseBreak Text
"GN"
    [Text]
orderedLocusNames <- [Text] -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser Text [Text] -> Parser Text [Text])
-> Parser Text [Text] -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text [Text]
parseGNList Text
"OrderedLocusNames"
    Parser () -> Parser (Maybe ())
forall a. Parser a -> Parser (Maybe a)
optional (Parser () -> Parser (Maybe ())) -> Parser () -> Parser (Maybe ())
forall a b. (a -> b) -> a -> b
$ Text -> Parser ()
parseBreak Text
"GN"
    [Text]
orfNames <- [Text] -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser Text [Text] -> Parser Text [Text])
-> Parser Text [Text] -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text [Text]
parseGNList Text
"ORFNames"
    let gn :: GN
gn = GN :: Maybe Text -> [Text] -> [Text] -> [Text] -> GN
GN{[Text]
Maybe Text
orfNames :: [Text]
orderedLocusNames :: [Text]
synonyms :: [Text]
geneName :: Maybe Text
orfNames :: [Text]
orderedLocusNames :: [Text]
synonyms :: [Text]
geneName :: Maybe Text
..}
    Parser () -> Parser (Maybe ())
forall a. Parser a -> Parser (Maybe a)
optional (Parser () -> Parser (Maybe ())) -> Parser () -> Parser (Maybe ())
forall a b. (a -> b) -> a -> b
$ Text -> Parser ()
parseBreak Text
"GN"
    [GN]
rest <- [GN] -> Parser [GN] -> Parser [GN]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser [GN] -> Parser [GN]) -> Parser [GN] -> Parser [GN]
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text
string Text
"and" Parser Text -> Parser () -> Parser ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ()
endOfLine Parser () -> Parser [GN] -> Parser [GN]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser [GN]
parseGN
    [GN] -> Parser [GN]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([GN] -> Parser [GN]) -> [GN] -> Parser [GN]
forall a b. (a -> b) -> a -> b
$ GN
gnGN -> [GN] -> [GN]
forall a. a -> [a] -> [a]
:[GN]
rest
  where
    -- | Parses any list item of GN line (like `Synonyms` or `ORFNames`)
    parseGNList :: Text -> Parser [Text]
    parseGNList :: Text -> Parser Text [Text]
parseGNList Text
name = Text -> Text -> [Text]
splitOn Text
", " (Text -> [Text]) -> Parser Text -> Parser Text [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Text
parseDefItem Text
name

-- | Parses OS lines for one record of UniProt-KB text file.
parseOS :: Parser OS
parseOS :: Parser OS
parseOS = Text -> OS
OS (Text -> OS) -> (String -> Text) -> String -> OS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> OS) -> Parser Text String -> Parser OS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> Parser Text
string Text
"OS   " Parser Text -> Parser Text String -> Parser Text String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Int -> Parser Text String
parseMultiLineComment Text
"OS" Int
3)

-- | Parser OG line of UniProt-KB text file.
parseOG :: Parser OG
parseOG :: Parser OG
parseOG = (Parser OG
parseOGNonPlasmid Parser OG -> Parser Text [Text] -> Parser OG
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Char -> Parser Text Char
char Char
' ' Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text
parseEvidence) Parser OG -> Parser Text Char -> Parser OG
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Text Char
char Char
'.') Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
          ([Text] -> OG
Plasmid ([Text] -> OG) -> Parser Text [Text] -> Parser OG
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text [Text]
parseOGPlasmid)
  where
    parseOGNonPlasmid :: Parser OG
    parseOGNonPlasmid :: Parser OG
parseOGNonPlasmid = Text -> Parser Text
string Text
"OG   " Parser Text -> Parser OG -> Parser OG
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>
      ((Text -> Parser Text
string Text
"Hydrogenosome" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> OG
Hydrogenosome) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Mitochondrion" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> OG
Mitochondrion) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Nucleomorph" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> OG
Nucleomorph) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid; Apicoplast" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidApicoplast) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid; Chloroplast" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidChloroplast) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid; Organellar chromatophore" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidOrganellarChromatophore) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid; Cyanelle" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidCyanelle) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid; Non-photosynthetic plastid" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidNonPhotosynthetic) Parser OG -> Parser OG -> Parser OG
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
       (Text -> Parser Text
string Text
"Plastid" Parser Text -> OG -> Parser OG
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Plastid -> OG
Plastid Plastid
PlastidSimple))

    parseOGPlasmid :: Parser [Text]
    parseOGPlasmid :: Parser Text [Text]
parseOGPlasmid = do
        Text -> Parser Text
string Text
"OG   "
        Text
name <- Parser Text
parseAnyPlasmid
        let separator :: Parser (Maybe Text)
separator = Char -> Parser Text Char
char Char
',' Parser Text Char -> Parser (Maybe Text) -> Parser (Maybe Text)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text -> Parser (Maybe Text)
forall a. Parser a -> Parser (Maybe a)
optional Parser Text
" and"
        [Text]
rest <- Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text -> Parser Text [Text])
-> Parser Text -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Parser (Maybe Text)
separator Parser (Maybe Text) -> Parser Text Char -> Parser Text Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Char -> Parser Text Char
char Char
' ' Parser Text Char -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text
parseAnyPlasmid
        Parser (Maybe Text) -> Parser (Maybe (Maybe Text))
forall a. Parser a -> Parser (Maybe a)
optional Parser (Maybe Text)
separator
        [Text]
rest2 <- [[Text]] -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
P.concat ([[Text]] -> [Text]) -> Parser Text [[Text]] -> Parser Text [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text [Text] -> Parser Text [[Text]]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text [Text]
parseOGPlasmid)
        [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Text] -> Parser Text [Text]) -> [Text] -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Text
name Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
rest [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
rest2

    parseAnyPlasmid :: Parser Text
    parseAnyPlasmid :: Parser Text
parseAnyPlasmid = Parser Text
parseOnePlasmid Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      ((Parser Text
"Plasmid" Parser Text -> Parser (Maybe Text) -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text -> Parser (Maybe Text)
forall a. Parser a -> Parser (Maybe a)
optional (Char -> Parser Text Char
char Char
' ' Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text
parseEvidence)
                                  Parser Text -> Parser Text (Maybe Char) -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text Char -> Parser Text (Maybe Char)
forall a. Parser a -> Parser (Maybe a)
optional (Char -> Parser Text Char
char Char
'.')) Parser Text -> Text -> Parser Text
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Text
"") -- ABSAA_ALCSP hack

    parseOnePlasmid :: Parser Text
    parseOnePlasmid :: Parser Text
parseOnePlasmid = do
        Text -> Parser Text
string Text
"Plasmid "
        String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
parsePlasmidName

    parsePlasmidName :: Parser String
    parsePlasmidName :: Parser Text String
parsePlasmidName = do
        let p :: Parser Text String
p = Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool -> Bool)
-> (Char -> Bool) -> (Char -> Bool) -> Char -> Bool
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (String -> Char -> Bool
notInClass String
",{") (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine))
        String
part <- Parser Text String
p
        Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
        String
plasmid <- case Maybe Char
nextChar of
          Just Char
'{' -> Parser Text
parseEvidence Parser Text -> Parser Text String -> Parser Text String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text Char -> Parser Text (Maybe Char)
forall a. Parser a -> Parser (Maybe a)
optional (Char -> Parser Text Char
char Char
'.') Parser Text (Maybe Char) -> String -> Parser Text String
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ShowS
forall a. [a] -> [a]
P.init String
part
          Maybe Char
_        -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
part
        String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Parser Text String) -> String -> Parser Text String
forall a b. (a -> b) -> a -> b
$ if String -> Char
forall a. [a] -> a
P.last String
plasmid Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' then ShowS
forall a. [a] -> [a]
P.init String
plasmid else String
plasmid

    countElem :: Eq a => [a] -> a -> Int
    countElem :: [a] -> a -> Int
countElem []     a
_             = Int
0
    countElem (a
x:[a]
xs) a
y | a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y    = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [a] -> a -> Int
forall a. Eq a => [a] -> a -> Int
countElem [a]
xs a
y
                       | Bool
otherwise = [a] -> a -> Int
forall a. Eq a => [a] -> a -> Int
countElem [a]
xs a
y

-- | Parser OC line of UniProt-KB text file.
parseOC :: Parser OC
parseOC :: Parser OC
parseOC = [Text] -> OC
OC ([Text] -> OC) -> Parser Text [Text] -> Parser OC
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Char -> Char -> Parser Text [Text]
parseNodes Text
"OC" Char
';' Char
'.'

-- | Parses OX lines of UniProt-KB text file.
parseOX :: Parser OX
parseOX :: Parser OX
parseOX = do
    Text -> Parser Text
string Text
"OX   "
    Text
databaseQualifier <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
notChar Char
'=')
    Char -> Parser Text Char
char Char
'='
    Text
taxonomicCode <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
notChar Char
';')
    Char -> Parser Text Char
char Char
';'
    OX -> Parser OX
forall (f :: * -> *) a. Applicative f => a -> f a
pure OX :: Text -> Text -> OX
OX{Text
taxonomicCode :: Text
databaseQualifier :: Text
taxonomicCode :: Text
databaseQualifier :: Text
..}

-- | Parses OH line of UniProt-KB text file.
parseOH :: Parser OH
parseOH :: Parser OH
parseOH = do
    Text -> Parser Text
string Text
"OH   NCBI_TaxID="
    Text
taxId <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
notChar Char
';')
    Char -> Parser Text Char
char Char
';'
    String
hostName' <- Parser Text Char -> Parser Text String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine)
    let hostName :: Text
hostName = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
P.null String
hostName'
                            then String
""
                            else ShowS
forall a. [a] -> [a]
P.tail ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String
hostName'
    OH -> Parser OH
forall (f :: * -> *) a. Applicative f => a -> f a
pure OH :: Text -> Text -> OH
OH{Text
hostName :: Text
taxId :: Text
hostName :: Text
taxId :: Text
..}

-- | Parses RN, RP, RC, RX, RG, RA, RT and RL lines of UniProt-KB text file.
parseRef :: Parser Reference
parseRef :: Parser Reference
parseRef = do
    Int
rn <- Parser Int
parseRN
    Parser ()
endOfLine
    Text
rp <- Parser Text
parseRP
    Parser ()
endOfLine
    [(Token, Text)]
rc <- [(Token, Text)]
-> Parser Text [(Token, Text)] -> Parser Text [(Token, Text)]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Token -> Text -> Parser Text [(Token, Text)]
forall a. (Enum a, Show a) => a -> Text -> Parser [(a, Text)]
parseRCX Token
STRAIN Text
"RC" Parser Text [(Token, Text)]
-> Parser () -> Parser Text [(Token, Text)]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
    [(BibliographicDB, Text)]
rx <- [(BibliographicDB, Text)]
-> Parser Text [(BibliographicDB, Text)]
-> Parser Text [(BibliographicDB, Text)]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (BibliographicDB -> Text -> Parser Text [(BibliographicDB, Text)]
forall a. (Enum a, Show a) => a -> Text -> Parser [(a, Text)]
parseRCX BibliographicDB
MEDLINE Text
"RX" Parser Text [(BibliographicDB, Text)]
-> Parser () -> Parser Text [(BibliographicDB, Text)]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
    [Text]
rg <- [Text] -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text -> Parser Text [Text])
-> Parser Text -> Parser Text [Text]
forall a b. (a -> b) -> a -> b
$ Parser Text
parseRG Parser Text -> Parser () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
    [Text]
ra <- [Text] -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Text -> Char -> Char -> Parser Text [Text]
parseNodes Text
"RA" Char
',' Char
';' Parser Text [Text] -> Parser () -> Parser Text [Text]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
    Maybe Text
rt <- Parser Text -> Parser (Maybe Text)
forall a. Parser a -> Parser (Maybe a)
optional  (Parser Text
parseRT Parser Text -> Parser () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
    Text
rl <- Parser Text
parseRL
    Reference -> Parser Reference
forall (f :: * -> *) a. Applicative f => a -> f a
pure Reference :: Int
-> Text
-> [(Token, Text)]
-> [(BibliographicDB, Text)]
-> [Text]
-> [Text]
-> Maybe Text
-> Text
-> Reference
Reference{Int
[(BibliographicDB, Text)]
[(Token, Text)]
[Text]
Maybe Text
Text
rl :: Text
rt :: Maybe Text
ra :: [Text]
rg :: [Text]
rx :: [(BibliographicDB, Text)]
rc :: [(Token, Text)]
rp :: Text
rn :: Int
rl :: Text
rt :: Maybe Text
ra :: [Text]
rg :: [Text]
rx :: [(BibliographicDB, Text)]
rc :: [(Token, Text)]
rp :: Text
rn :: Int
..}
  where
    parseRN :: Parser Int
    parseRN :: Parser Int
parseRN = do
        Int
number <- (Text -> Parser Text
string Text
"RN   [" Parser Text -> Parser Int -> Parser Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Int
forall a. Integral a => Parser a
decimal) Parser Int -> Parser Text Char -> Parser Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Text Char
char Char
']'
        -- Despite the specification, edivence may be presented here
        [Text]
_ <- Parser Text -> Parser Text [Text]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Char -> Parser Text Char
char Char
' ' Parser Text Char -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text
parseEvidence)
        Int -> Parser Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
number

    parseRP :: Parser Text
    parseRP :: Parser Text
parseRP = do
        Text -> Parser Text
string Text
"RP   "
        String -> Text
pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Int -> Parser Text String
parseMultiLineComment Text
"RP" Int
3

    parseRCX :: (Enum a, Show a) => a -> Text -> Parser [(a, Text)]
    parseRCX :: a -> Text -> Parser [(a, Text)]
parseRCX a
start Text
name = do
       Text -> Parser Text
string Text
name Parser Text -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"   "
       (:) ((a, Text) -> [(a, Text)] -> [(a, Text)])
-> Parser Text (a, Text)
-> Parser Text ([(a, Text)] -> [(a, Text)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Parser Text (a, Text)
forall a. (Enum a, Show a) => a -> Parser (a, Text)
parseTokPair a
start
           Parser Text ([(a, Text)] -> [(a, Text)])
-> Parser [(a, Text)] -> Parser [(a, Text)]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text (a, Text) -> Parser [(a, Text)]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Text -> Parser ()
parseBreak Text
name Parser () -> Parser Text (a, Text) -> Parser Text (a, Text)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> a -> Parser Text (a, Text)
forall a. (Enum a, Show a) => a -> Parser (a, Text)
parseTokPair a
start)
     where
       parseTokPair :: (Enum a, Show a) => a -> Parser (a, Text)
       parseTokPair :: a -> Parser (a, Text)
parseTokPair a
x = (Parser (a, Text) -> Parser (a, Text) -> Parser (a, Text))
-> [Parser (a, Text)] -> Parser (a, Text)
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Parser (a, Text) -> Parser (a, Text) -> Parser (a, Text)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) ([Parser (a, Text)] -> Parser (a, Text))
-> [Parser (a, Text)] -> Parser (a, Text)
forall a b. (a -> b) -> a -> b
$
                          (\a
x -> (a
x,) (Text -> (a, Text)) -> Parser Text -> Parser (a, Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Text
parseDefItem (String -> Text
pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show (a -> Text) -> a -> Text
forall a b. (a -> b) -> a -> b
$ a
x)) (a -> Parser (a, Text)) -> [a] -> [Parser (a, Text)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a
x..]

    parseRG :: Parser Text
    parseRG :: Parser Text
parseRG = String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> Parser Text
string Text
"RG   " Parser Text -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine))

    parseRT :: Parser Text
    parseRT :: Parser Text
parseRT = do
        Text -> Parser Text
string Text
"RT   \""
        let p :: Parser Text String
p = Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Parser Text Char -> Parser Text String)
-> Parser Text Char -> Parser Text String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool -> Bool)
-> (Char -> Bool) -> (Char -> Bool) -> Char -> Bool
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine) (String -> Char -> Bool
notInClass String
"\"")
        [String]
referenceTitle <- (:) (String -> [String] -> [String])
-> Parser Text String -> Parser Text ([String] -> [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
p Parser Text ([String] -> [String])
-> Parser Text [String] -> Parser Text [String]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text String -> Parser Text [String]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Text -> Parser Text
string Text
"RT  " Parser Text -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text String
p)
        Text -> Parser Text
string Text
"\";"
        Text -> Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Parser Text) -> Text -> Parser Text
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (String -> Text) -> ([String] -> String) -> [String] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
hyphenConcat ([String] -> Text) -> [String] -> Text
forall a b. (a -> b) -> a -> b
$ [String]
referenceTitle

    parseRL :: Parser Text
    parseRL :: Parser Text
parseRL = do
        Text -> Parser Text
string Text
"RL   "
        String -> Text
pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Int -> Parser Text String
parseMultiLineComment Text
"RL" Int
3

-- | Parses CC lines of UniProt-KB text file.
parseCC :: Parser CC
parseCC :: Parser CC
parseCC = do
    Text -> Parser Text
string Text
"CC   -!- "
    Text
topic <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
notChar Char
':')
    Char -> Parser Text Char
char Char
':'
    (Char -> Parser Text Char
char Char
' ' Parser Text Char -> () -> Parser ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()) Parser () -> Parser () -> Parser ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"CC" Parser Text -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
7 Parser Text Char
space Parser Text String -> () -> Parser ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ())
    Text
comment <- [Text] -> Text
forall a. [a] -> a
head ([Text] -> Text) -> (String -> [Text]) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
" {ECO" Text -> Text -> [Text]
`splitOn`) (Text -> [Text]) -> (String -> Text) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Int -> Parser Text String
parseMultiLineComment Text
"CC" Int
7
    CC -> Parser CC
forall (f :: * -> *) a. Applicative f => a -> f a
pure CC :: Text -> Text -> CC
CC{Text
comment :: Text
topic :: Text
comment :: Text
topic :: Text
..}

-- | UniProt-KB copyright comment
copyrightCC :: Text
copyrightCC :: Text
copyrightCC = Text
"CC   -----------------------------------------------------------------------\nCC   Copyrighted by the UniProt Consortium, see https://www.uniprot.org/terms\nCC   Distributed under the Creative Commons Attribution (CC BY 4.0) License\nCC   -----------------------------------------------------------------------"


-- | Parses DR lines of UniProt-KB text file.
parseDR :: Parser DR
parseDR :: Parser DR
parseDR = do
    Text -> Parser Text
string Text
"DR   "
    Text
resourceAbbr <- Parser Text
parseToken
    Char -> Parser Text Char
char Char
' '
    Text
resourceId <- Parser Text
parseToken
    [Text]
optionalInfo <- Parser Text -> Parser Text [Text]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
char Char
' ' Parser Text Char -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text
parseToken)
    DR -> Parser DR
forall (f :: * -> *) a. Applicative f => a -> f a
pure DR :: Text -> Text -> [Text] -> DR
DR{[Text]
Text
optionalInfo :: [Text]
resourceId :: Text
resourceAbbr :: Text
optionalInfo :: [Text]
resourceId :: Text
resourceAbbr :: Text
..}
  where
    parseToken :: Parser Text
    parseToken :: Parser Text
parseToken = String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
parseTokenStr

    parseTokenStr :: Parser String
    parseTokenStr :: Parser Text String
parseTokenStr = do
        String
part <- Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool -> Bool)
-> (Char -> Bool) -> (Char -> Bool) -> Char -> Bool
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=Char
';') (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine))
        Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
        case Maybe Char
nextChar of
          Maybe Char
Nothing  -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Parser Text String)
-> ShowS -> String -> Parser Text String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> Parser Text String) -> String -> Parser Text String
forall a b. (a -> b) -> a -> b
$ String
part
          Just Char
';' -> do
              Char -> Parser Text Char
char Char
';'
              Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
              case Maybe Char
nextChar of
                Maybe Char
Nothing -> String -> Parser Text String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"You cannot be here"
                Just Char
c  | Char -> Bool
isSpace Char
c -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
part
                Just Char
c  -> (String
part String -> ShowS
forall a. Semigroup a => a -> a -> a
<>) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char
';'Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
parseTokenStr
          Just Char
c  -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Parser Text String)
-> ShowS -> String -> Parser Text String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. [a] -> [a]
P.init (String -> Parser Text String) -> String -> Parser Text String
forall a b. (a -> b) -> a -> b
$ String
part

-- | Parses PE line of UniProt-KB text file.
parsePE :: Parser PE
parsePE :: Parser PE
parsePE = (Text -> Parser Text
string Text
"PE   1: Evidence at protein level;" Parser Text -> PE -> Parser PE
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> PE
EvidenceAtProteinLevel) Parser PE -> Parser PE -> Parser PE
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
          (Text -> Parser Text
string Text
"PE   2: Evidence at transcript level;" Parser Text -> PE -> Parser PE
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> PE
EvidenceAtTranscriptLevel) Parser PE -> Parser PE -> Parser PE
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
          (Text -> Parser Text
string Text
"PE   3: Inferred from homology;" Parser Text -> PE -> Parser PE
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> PE
InferredFromHomology) Parser PE -> Parser PE -> Parser PE
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
          (Text -> Parser Text
string Text
"PE   4: Predicted;" Parser Text -> PE -> Parser PE
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> PE
Predicted) Parser PE -> Parser PE -> Parser PE
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
          (Text -> Parser Text
string Text
"PE   5: Uncertain;" Parser Text -> PE -> Parser PE
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> PE
Uncertain)

-- | Parses KW lines of UniProt-KB text file.
parseKW :: Parser KW
parseKW :: Parser KW
parseKW = [Text] -> KW
KW ([Text] -> KW) -> Parser Text [Text] -> Parser KW
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Char -> Char -> Parser Text [Text]
parseNodes Text
"KW" Char
';' Char
'.'

-- | Parses FT lines of UniProt-KB text file. One FT section is parsed.
parseFT :: Parser FT
parseFT :: Parser FT
parseFT = do
    Text -> Parser Text
string Text
"FT   "
    Text
keyName <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Z_")
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Endpoint
fromEP <- Parser Endpoint
parseFTEndpoint
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Endpoint
toEP <- Parser Endpoint
parseFTEndpoint
    [Text]
description <- (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"{ECO" Text -> Text -> Bool
`isPrefixOf`)) ([Text] -> [Text]) -> (String -> [Text]) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [Text]
splitByMagic (String -> [Text]) -> Parser Text String -> Parser Text [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
                     ((Parser Text Char -> Parser Text String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Char -> Parser Text Char
char Char
' ') Parser Text String -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Text -> Int -> Parser Text String
parseMultiLineComment Text
"FT" Int
32) Parser Text String -> Parser Text String -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      ([String] -> String
hyphenConcat ([String] -> String) -> Parser Text [String] -> Parser Text String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Int -> Parser Text [String]
parseMultiLine Text
"FT" Int
32))
    FT -> Parser FT
forall (f :: * -> *) a. Applicative f => a -> f a
pure FT :: Text -> Endpoint -> Endpoint -> [Text] -> FT
FT{[Text]
Text
Endpoint
description :: [Text]
toEP :: Endpoint
fromEP :: Endpoint
keyName :: Text
description :: [Text]
toEP :: Endpoint
fromEP :: Endpoint
keyName :: Text
..}
  where
    -- | Parse FT endpoint
    parseFTEndpoint :: Parser Endpoint
    parseFTEndpoint :: Parser Endpoint
parseFTEndpoint = (Int -> Endpoint
UncertainEP (Int -> Endpoint) -> Parser Int -> Parser Endpoint
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'?' Parser Text Char -> Parser Int -> Parser Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Int
forall a. Integral a => Parser a
decimal)) Parser Endpoint -> Parser Endpoint -> Parser Endpoint
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      (Int -> Endpoint
NTerminalEP (Int -> Endpoint) -> Parser Int -> Parser Endpoint
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'<' Parser Text Char -> Parser Int -> Parser Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Int
forall a. Integral a => Parser a
decimal)) Parser Endpoint -> Parser Endpoint -> Parser Endpoint
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      (Int -> Endpoint
CTerminalEP (Int -> Endpoint) -> Parser Int -> Parser Endpoint
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'>' Parser Text Char -> Parser Int -> Parser Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Int
forall a. Integral a => Parser a
decimal)) Parser Endpoint -> Parser Endpoint -> Parser Endpoint
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      (Int -> Endpoint
ExactEP     (Int -> Endpoint) -> Parser Int -> Parser Endpoint
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Int
forall a. Integral a => Parser a
decimal) Parser Endpoint -> Parser Endpoint -> Parser Endpoint
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
                      (Char -> Parser Text Char
char Char
'?' Parser Text Char -> Endpoint -> Parser Endpoint
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Endpoint
UnknownEP)

    -- | Split string to tokens by periods outside brackets.
    splitByMagic :: String -> [Text]
    splitByMagic :: String -> [Text]
splitByMagic String
txt = String -> Text
pack (String -> Text) -> [String] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> String -> String -> [String]
splitStr Int
0 [] String
txt
      where
        splitStr :: Int -> String -> String -> [String]
        splitStr :: Int -> String -> String -> [String]
splitStr Int
_ String
_   []           = []
        splitStr Int
0 String
acc [Char
'.']        = [ShowS
forall a. [a] -> [a]
reverse String
acc]
        splitStr Int
0 String
acc (Char
'.':Char
' ':String
xs) = ShowS
forall a. [a] -> [a]
reverse String
acc String -> [String] -> [String]
forall a. a -> [a] -> [a]
: Int -> String -> String -> [String]
splitStr Int
0 [] String
xs
        splitStr Int
0 String
acc (Char
'.':String
xs)     = ShowS
forall a. [a] -> [a]
reverse String
acc String -> [String] -> [String]
forall a. a -> [a] -> [a]
: Int -> String -> String -> [String]
splitStr Int
0 [] String
xs
        splitStr Int
n String
acc (Char
'(':String
xs)     = Int -> String -> String -> [String]
splitStr (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Char
'('Char -> ShowS
forall a. a -> [a] -> [a]
:String
acc) String
xs
        splitStr Int
n String
acc (Char
')':String
xs)     = Int -> String -> String -> [String]
splitStr (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Char
')'Char -> ShowS
forall a. a -> [a] -> [a]
:String
acc) String
xs
        splitStr Int
n String
acc (Char
x:String
xs)       = Int -> String -> String -> [String]
splitStr Int
n (Char
xChar -> ShowS
forall a. a -> [a] -> [a]
:String
acc) String
xs

-- | Parses SQ lines of UniProt-KB text file.
parseSQ :: Parser SQ
parseSQ :: Parser SQ
parseSQ = do
    Text -> Parser Text
string Text
"SQ   SEQUENCE"
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Int
len <- Parser Int
forall a. Integral a => Parser a
decimal
    Parser Text Char
space Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"AA;"
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Int
molWeight <- Parser Int
forall a. Integral a => Parser a
decimal
    Parser Text Char
space Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"MW;"
    Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 Parser Text Char
space
    Text
crc64 <- String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-F0-9")
    Parser Text Char
space Parser Text Char -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"CRC64;"
    Parser ()
endOfLine
    Text
sequ <- String -> Text
pack (String -> Text) -> ([String] -> String) -> [String] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
P.concat ([String] -> Text) -> Parser Text [String] -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Parser Text String -> Parser Text [String]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Parser ()
skipSpace Parser () -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ String -> Char -> Bool
inClass String
"A-Z"))
    SQ -> Parser SQ
forall (f :: * -> *) a. Applicative f => a -> f a
pure SQ :: Int -> Int -> Text -> Text -> SQ
SQ{Int
Text
sequ :: Text
crc64 :: Text
molWeight :: Int
len :: Int
sequ :: Text
crc64 :: Text
molWeight :: Int
len :: Int
..}

-- | Parses end of one UniProt record.
parseEnd :: Parser ()
parseEnd :: Parser ()
parseEnd = Text -> Parser Text
string Text
"//" Parser Text -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- | Parses whole UniProt-KB record.
parseRecord :: Parser Record
parseRecord :: Parser Record
parseRecord = ID
-> AC
-> DT
-> DE
-> [GN]
-> OS
-> [OG]
-> OC
-> OX
-> [OH]
-> [Reference]
-> [CC]
-> [DR]
-> PE
-> Maybe KW
-> [FT]
-> SQ
-> Record
Record (ID
 -> AC
 -> DT
 -> DE
 -> [GN]
 -> OS
 -> [OG]
 -> OC
 -> OX
 -> [OH]
 -> [Reference]
 -> [CC]
 -> [DR]
 -> PE
 -> Maybe KW
 -> [FT]
 -> SQ
 -> Record)
-> Parser ID
-> Parser
     Text
     (AC
      -> DT
      -> DE
      -> [GN]
      -> OS
      -> [OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>           (Parser ID
parseID  Parser ID -> Parser () -> Parser ID
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (AC
   -> DT
   -> DE
   -> [GN]
   -> OS
   -> [OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser AC
-> Parser
     Text
     (DT
      -> DE
      -> [GN]
      -> OS
      -> [OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser AC
parseAC  Parser AC -> Parser () -> Parser AC
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (DT
   -> DE
   -> [GN]
   -> OS
   -> [OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser DT
-> Parser
     Text
     (DE
      -> [GN]
      -> OS
      -> [OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser DT
parseDT  Parser DT -> Parser () -> Parser DT
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (DE
   -> [GN]
   -> OS
   -> [OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser DE
-> Parser
     Text
     ([GN]
      -> OS
      -> [OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser DE
parseDE  Parser DE -> Parser () -> Parser DE
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  ([GN]
   -> OS
   -> [OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser [GN]
-> Parser
     Text
     (OS
      -> [OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [GN] -> Parser [GN] -> Parser [GN]
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option [] (Parser [GN]
parseGN  Parser [GN] -> Parser () -> Parser [GN]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (OS
   -> [OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser OS
-> Parser
     Text
     ([OG]
      -> OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser OS
parseOS  Parser OS -> Parser () -> Parser OS
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  ([OG]
   -> OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser Text [OG]
-> Parser
     Text
     (OC
      -> OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser OG -> Parser Text [OG]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser OG
parseOG  Parser OG -> Parser () -> Parser OG
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (OC
   -> OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser OC
-> Parser
     Text
     (OX
      -> [OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser OC
parseOC  Parser OC -> Parser () -> Parser OC
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  (OX
   -> [OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser OX
-> Parser
     Text
     ([OH]
      -> [Reference]
      -> [CC]
      -> [DR]
      -> PE
      -> Maybe KW
      -> [FT]
      -> SQ
      -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser OX
parseOX  Parser OX -> Parser () -> Parser OX
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  ([OH]
   -> [Reference]
   -> [CC]
   -> [DR]
   -> PE
   -> Maybe KW
   -> [FT]
   -> SQ
   -> Record)
-> Parser Text [OH]
-> Parser
     Text
     ([Reference]
      -> [CC] -> [DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser OH -> Parser Text [OH]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser OH
parseOH  Parser OH -> Parser () -> Parser OH
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text
  ([Reference]
   -> [CC] -> [DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
-> Parser Text [Reference]
-> Parser
     Text ([CC] -> [DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Reference -> Parser Text [Reference]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser Reference
parseRef Parser Reference -> Parser () -> Parser Reference
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser
  Text ([CC] -> [DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
-> Parser Text [CC]
-> Parser Text ([DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser CC -> Parser Text [CC]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser CC
parseCC  Parser CC -> Parser () -> Parser CC
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine) Parser Text ([DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
-> Parser Text
-> Parser Text ([DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Text
"" (Text -> Parser Text
string Text
copyrightCC Parser Text -> Parser () -> Parser Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Text ([DR] -> PE -> Maybe KW -> [FT] -> SQ -> Record)
-> Parser Text [DR]
-> Parser Text (PE -> Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser DR -> Parser Text [DR]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser DR
parseDR  Parser DR -> Parser () -> Parser DR
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Text (PE -> Maybe KW -> [FT] -> SQ -> Record)
-> Parser PE -> Parser Text (Maybe KW -> [FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser PE
parsePE  Parser PE -> Parser () -> Parser PE
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Text (Maybe KW -> [FT] -> SQ -> Record)
-> Parser Text (Maybe KW) -> Parser Text ([FT] -> SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser KW -> Parser Text (Maybe KW)
forall a. Parser a -> Parser (Maybe a)
optional  (Parser KW
parseKW  Parser KW -> Parser () -> Parser KW
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Text ([FT] -> SQ -> Record)
-> Parser Text [FT] -> Parser Text (SQ -> Record)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FT -> Parser Text [FT]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many'     (Parser FT
parseFT  Parser FT -> Parser () -> Parser FT
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Text (SQ -> Record) -> Parser SQ -> Parser Record
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>           (Parser SQ
parseSQ  Parser SQ -> Parser () -> Parser SQ
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ()
endOfLine)
                     Parser Record -> Parser () -> Parser Record
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*            Parser ()
parseEnd

parseEvidence :: Parser Text
parseEvidence :: Parser Text
parseEvidence = (\Text
x Text
y Text
z -> Text
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
y Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
z) (Text -> Text -> Text -> Text)
-> Parser Text -> Parser Text (Text -> Text -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
                  Text -> Parser Text
string Text
"{" Parser Text (Text -> Text -> Text)
-> Parser Text -> Parser Text (Text -> Text)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Char -> Parser Text Char
notChar Char
'}')) Parser Text (Text -> Text) -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Parser Text
string Text
"}"

-- = Helper parsers

-- | Transforms any parser to a parser of maybe value.
--
-- >>> parseOnly (optional digit) "1"
-- Right (Just 1)
--
-- >>> parseOnly (optional digit) ""
-- Right Nothing
optional :: Parser a -> Parser (Maybe a)
optional :: Parser a -> Parser (Maybe a)
optional Parser a
par = Maybe a -> Parser (Maybe a) -> Parser (Maybe a)
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> Parser a -> Parser (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser a
par)

-- | Parses lines, that contain nodes splitted by `del` and ended by `end`.
parseNodes :: Text          -- ^Start 2-letter mark.
           -> Char          -- ^Delimeter char, that splits the nodes.
           -> Char          -- ^Terminal char, that ends the node list.
           -> Parser [Text]
parseNodes :: Text -> Char -> Char -> Parser Text [Text]
parseNodes Text
start Char
del Char
end = do
    Text -> Parser Text
string Text
start Parser Text -> Parser Text String -> Parser Text String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
3 (Char -> Parser Text Char
char Char
' ')
    Parser Text [Text]
parseNodesNoStart
  where
    parseNodesNoStart :: Parser [Text]
    parseNodesNoStart :: Parser Text [Text]
parseNodesNoStart = do
        Text
part <- Parser Text
parseNode
        Char
c <- Char -> Parser Text Char
char Char
del Parser Text Char -> Parser Text Char -> Parser Text Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Text Char
char Char
end
        if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
del
          then do (Char -> Parser Text Char
char Char
' ' Parser Text Char -> () -> Parser ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()) Parser () -> Parser () -> Parser ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
start Parser Text -> Parser () -> Parser ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
3 (Char -> Parser Text Char
char Char
' ') Parser Text String -> () -> Parser ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ())
                  (Text
part Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:) ([Text] -> [Text]) -> Parser Text [Text] -> Parser Text [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text [Text]
parseNodesNoStart
          else do Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
                  case Maybe Char
nextChar of
                    Maybe Char
Nothing                -> [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text
part]
                    Just Char
c | Char -> Bool
isEndOfLine Char
c -> [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text
part]
                    Just Char
c                 -> do (Text
x:[Text]
xs) <- Parser Text [Text]
parseNodesNoStart
                                                 [Text] -> Parser Text [Text]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
part Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
x Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
xs)

    parseNode :: Parser Text
    parseNode :: Parser Text
parseNode = String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 ((Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool -> Bool)
-> (Char -> Bool) -> (Char -> Bool) -> Char -> Bool
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (String -> Char -> Bool
notInClass [Char
del,Char
end]) (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine))

-- | Parses line till the end.
parseTillEnd :: Parser String
parseTillEnd :: Parser Text String
parseTillEnd = Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Parser Text Char -> Parser Text String)
-> Parser Text Char -> Parser Text String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Parser Text Char
satisfy (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine)

-- | Parses multiline comment as one string.
parseMultiLineComment :: Text -> Int -> Parser String
parseMultiLineComment :: Text -> Int -> Parser Text String
parseMultiLineComment Text
start Int
skip = [String] -> String
hyphenConcat ([String] -> String) -> Parser Text [String] -> Parser Text String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
                                     ((:) (String -> [String] -> [String])
-> Parser Text String -> Parser Text ([String] -> [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
parseTillEnd
                                          Parser Text ([String] -> [String])
-> Parser Text [String] -> Parser Text [String]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> Int -> Parser Text [String]
parseMultiLine Text
start Int
skip)

-- | Parses multiline comment from new line.
parseMultiLine :: Text -> Int -> Parser [String]
parseMultiLine :: Text -> Int -> Parser Text [String]
parseMultiLine Text
start Int
skip = Parser Text String -> Parser Text [String]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (Parser Text String -> Parser Text [String])
-> Parser Text String -> Parser Text [String]
forall a b. (a -> b) -> a -> b
$ do
    Parser ()
endOfLine
    Text -> Parser Text
string Text
start
    Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count (Int
skip Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Char -> Parser Text Char
char Char
' ') -- leave one space to separate words
    Parser Text String
parseTillEnd

-- | Parses line break for multiline section.
parseBreak :: Text -> Parser ()
parseBreak :: Text -> Parser ()
parseBreak Text
txt = ((Parser ()
endOfLine Parser () -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
txt Parser Text -> Parser Text -> Parser Text
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Text -> Parser Text
string Text
"   ") Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Parser Text
string Text
" ") Parser Text -> () -> Parser ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()

-- | Parses one item like "Something=Something else;"
parseDefItem :: Text -> Parser Text
parseDefItem :: Text -> Parser Text
parseDefItem Text
name = do
    Text -> Parser Text
string Text
name Parser Text -> Parser Text Char -> Parser Text Char
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> Parser Text Char
char Char
'='
    [Text] -> Text
forall a. [a] -> a
head ([Text] -> Text) -> (String -> [Text]) -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
" {" Text -> Text -> [Text]
`splitOn`) (Text -> [Text]) -> (String -> Text) -> String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Parser Text String
parseTillChar Char
';'

-- | Parses line till specific char (e.g. semicolon or dot) before space/endOfLine/endOfInput.
parseTillChar :: Char -> Parser String
parseTillChar :: Char -> Parser Text String
parseTillChar Char
c = do
    String
part <- Parser Text Char -> Parser Text String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (Parser Text Char -> Parser Text String)
-> Parser Text Char -> Parser Text String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Parser Text Char
satisfy ((Char -> Bool) -> Parser Text Char)
-> (Char -> Bool) -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool -> Bool)
-> (Char -> Bool) -> (Char -> Bool) -> Char -> Bool
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=Char
c) (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine)
    Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
    case Maybe Char
nextChar of
      Maybe Char
Nothing                -> String -> Parser Text String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"You cannot be here!"
      Just Char
d | Char
d Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c        -> do
          Char -> Parser Text Char
char Char
c
          Maybe Char
nextChar <- Parser Text (Maybe Char)
peekChar
          case Maybe Char
nextChar of
            Maybe Char
Nothing -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
part
            Just Char
d  | Char -> Bool
isSpace Char
d -> String -> Parser Text String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
part
            Just Char
d  -> (String
part String -> ShowS
forall a. Semigroup a => a -> a -> a
<>) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char
dChar -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Parser Text String
parseTillChar Char
c
      Just Char
d | Char -> Bool
isEndOfLine Char
d -> do
          Parser ()
endOfLine
          Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
2 Parser Text Char
anyChar
          Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Monad m => Int -> m a -> m [a]
count Int
2 (Char -> Parser Text Char
char Char
' ')
          (String
part String -> ShowS
forall a. Semigroup a => a -> a -> a
<>) ShowS -> Parser Text String -> Parser Text String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Parser Text String
parseTillChar Char
c
      Just Char
_                 -> String -> Parser Text String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"You cannot be here!"

-- | Delete needless space after hyphen on concat.
hyphenConcat :: [String] -> String
hyphenConcat :: [String] -> String
hyphenConcat []       = []
hyphenConcat [String
x]      = String
x
hyphenConcat (String
x:String
y:[String]
ys) = String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ [String] -> String
hyphenConcat (String
syString -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ys)
  where
    sy :: String
    sy :: String
sy | String -> Char
forall a. [a] -> a
last String
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'                  = ShowS
forall a. [a] -> [a]
tail String
y
       | Char -> Bool
isAA (String -> Char
forall a. [a] -> a
last String
x) Bool -> Bool -> Bool
&& Char -> Bool
isAA (String
y String -> Int -> Char
forall a. [a] -> Int -> a
!! Int
1) = ShowS
forall a. [a] -> [a]
tail String
y
       | Bool
otherwise                      = String
y

    isAA :: Char -> Bool
    isAA :: Char -> Bool
isAA = String -> Char -> Bool
inClass String
"A-Z"