packages feed

hackport-0.2.1: Package.hs

{-|
    Maintainer  :  Andres Loeh <kosmikus@gentoo.org>
    Stability   :  provisional
    Portability :  haskell98

    Parser for categories and packages.

    Shamelessly borrowed from exi, somewhat modified
-}

module Package
  where

import Control.Monad
import Text.ParserCombinators.Parsec

import Version

type Category  =  String
type Package   =  String
type Slot      =  String

getPV :: String -> (Category, Package, Version)
getPV xs      =  case parsePV xs of
                   Left   e  ->
                     error $ "getPV: cat/pkg-ver parse error '" ++ xs ++ "'\n" ++ show e
                   Right  x  ->  x

getP :: String -> (Category, Package)
getP xs       =  case parseP xs of
                   Left   e  ->
                     error $ "getCatPkg: cat/pkg parse error '" ++ xs ++ "'\n" ++ show e
                   Right  x  ->  x

parsePV :: String -> Either ParseError (Category, Package, Version)
parsePV       =  parse (readPV >>= \x -> eof >> return x) "<cat/pkg-ver>"

readPV :: GenParser Char st (Category, Package, Version)
readPV        =  do  cat         <-  readCat
                     char '/'
                     (pkg,mver)  <-  readPkgAndVer
                     case mver of
                       Nothing   ->  fail "readPV: version expected"
                       Just ver  ->  return (cat, pkg, ver)

parseP :: String -> Either ParseError (Category, Package)
parseP        =  parse (readP >>= \x -> eof >> return x) "<cat/pkg>"

readP :: GenParser Char st (Category, Package)
readP         =  do  cat         <-  readCat
                     char '/'
                     (pkg,mver)  <-  readPkgAndVer
                     case mver of
                       Nothing   ->  return (cat, pkg)
                       Just _    ->  error "readCatPkg: unexpected version"

readCat        ::  CharParser st Category
readPkgAndVer  ::  CharParser st (Package,Maybe Version)

readCat        =   many1 (letter <|> digit <|> oneOf "_-")
readPkgAndVer  =   do  pre    <-  many1 (letter <|> digit <|> oneOf "_+")
                       (p,v)  <-  option ("",Nothing)
                                            (do  char '-'
                                                 liftM (\v -> ("",Just v)) readVerOrFail
                                                   <|> liftM (\(p,v) -> ('-':p,v)) readPkgAndVer
                                            )
                       return (pre ++ p,v)

readVerOrFail  ::  CharParser st Version
readVerOrFail  =   try $
                   do  ver    <-  many1 (letter <|> digit <|> oneOf "_+.-")
                       case parseVersion ver of
                           Left   _  -> 
                             fail $ "version parse error"
                           Right  x  -> return x