module Debian.Relation.String
(
AndRelation
, OrRelation
, Relations
, Relation(..)
, ArchitectureReq(..)
, VersionReq(..)
, checkVersionReq
, RelParser
, ParseRelations(..)
, pRelations
) where
import "mtl" Control.Monad.Identity (Identity)
import Data.Set (fromList)
import Text.ParserCombinators.Parsec
import Text.Parsec.Prim (ParsecT)
import Debian.Arch (Arch, parseArch)
import Debian.Relation.Common
import Debian.Version
instance ParseRelations String where
parseRelations str =
let str' = scrub str in
case parse pRelations str' str' of
Right relations -> Right (filter (/= []) relations)
x -> x
where
scrub = unlines . filter (not . comment) . lines
comment s = case dropWhile (`elem` " \t") s of
('#' : _) -> True
_ -> False
type RelParser a = CharParser () a
pRelations :: RelParser Relations
pRelations = do
rel <- many pOrRelation
eof
return rel
pOrRelation :: RelParser OrRelation
pOrRelation = do skipMany (char ',' <|> whiteChar)
rel <- sepBy1 pRelation (char '|')
skipMany (char ',' <|> whiteChar)
return rel
whiteChar :: ParsecT String u Identity Char
whiteChar = oneOf [' ','\t','\n']
pRelation :: RelParser Relation
pRelation =
do skipMany whiteChar
pkgName <- many1 (noneOf [' ',',','|','\t','\n','('])
skipMany whiteChar
mVerReq <- pMaybeVerReq
skipMany whiteChar
mArch <- pMaybeArch
return $ Rel (BinPkgName pkgName) mVerReq mArch
pMaybeVerReq :: RelParser (Maybe VersionReq)
pMaybeVerReq =
do char '('
skipMany whiteChar
op <- pVerReq
skipMany whiteChar
ver <- many1 (noneOf [' ',')','\t','\n'])
skipMany whiteChar
char ')'
return $ Just (op (parseDebianVersion' ver))
<|>
do return $ Nothing
pVerReq :: ParsecT [Char] u Identity (DebianVersion -> VersionReq)
pVerReq =
do char '<'
(do char '<' <|> char ' ' <|> char '\t'
return $ SLT
<|>
do char '='
return $ LTE)
<|>
do string "="
return $ EEQ
<|>
do char '>'
(do char '='
return $ GRE
<|>
do char '>' <|> char ' ' <|> char '\t'
return $ SGR)
pMaybeArch :: RelParser (Maybe ArchitectureReq)
pMaybeArch =
do char '['
(do archs <- pArchExcept
char ']'
skipMany whiteChar
return (Just (ArchExcept (fromList . map parseArchExcept $ archs)))
<|>
do archs <- pArchOnly
char ']'
skipMany whiteChar
return (Just (ArchOnly (fromList . map parseArch $ archs)))
)
<|>
return Nothing
pArchExcept :: RelParser [String]
pArchExcept = sepBy (char '!' >> many1 (noneOf [']',' '])) (skipMany1 whiteChar)
pArchOnly :: RelParser [String]
pArchOnly = sepBy (many1 (noneOf [']',' '])) (skipMany1 whiteChar)
parseArchExcept :: String -> Arch
parseArchExcept ('!' : s) = parseArch s
parseArchExcept s = parseArch s