-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.ReadE
-- Copyright   :  Jose Iborra 2008
-- License     :  BSD3
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- Simple parsing with failure

module Distribution.ReadE (
   -- * ReadE
   ReadE(..), succeedReadE, failReadE,
   -- * Projections
   readEOrFail,
   parsecToReadE,
  ) where

import Distribution.Compat.Prelude
import Prelude ()

import Distribution.Parsec
import Distribution.Parsec.FieldLineStream

-- | Parser with simple error reporting
newtype ReadE a = ReadE {ReadE a -> String -> Either String a
runReadE :: String -> Either ErrorMsg a}
type ErrorMsg   = String

instance Functor ReadE where
  fmap :: (a -> b) -> ReadE a -> ReadE b
fmap a -> b
f (ReadE String -> Either String a
p) = (String -> Either String b) -> ReadE b
forall a. (String -> Either String a) -> ReadE a
ReadE ((String -> Either String b) -> ReadE b)
-> (String -> Either String b) -> ReadE b
forall a b. (a -> b) -> a -> b
$ \String
txt -> case String -> Either String a
p String
txt of
                                       Right a
a  -> b -> Either String b
forall a b. b -> Either a b
Right (a -> b
f a
a)
                                       Left String
err -> String -> Either String b
forall a b. a -> Either a b
Left String
err

succeedReadE :: (String -> a) -> ReadE a
succeedReadE :: (String -> a) -> ReadE a
succeedReadE String -> a
f = (String -> Either String a) -> ReadE a
forall a. (String -> Either String a) -> ReadE a
ReadE (a -> Either String a
forall a b. b -> Either a b
Right (a -> Either String a)
-> (String -> a) -> String -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> a
f)

failReadE :: ErrorMsg -> ReadE a
failReadE :: String -> ReadE a
failReadE = (String -> Either String a) -> ReadE a
forall a. (String -> Either String a) -> ReadE a
ReadE ((String -> Either String a) -> ReadE a)
-> (String -> String -> Either String a) -> String -> ReadE a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String a -> String -> Either String a
forall a b. a -> b -> a
const (Either String a -> String -> Either String a)
-> (String -> Either String a)
-> String
-> String
-> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Either String a
forall a b. a -> Either a b
Left

readEOrFail :: ReadE a -> String -> a
readEOrFail :: ReadE a -> String -> a
readEOrFail ReadE a
r = (String -> a) -> (a -> a) -> Either String a -> a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> a
forall a. HasCallStack => String -> a
error a -> a
forall a. a -> a
id (Either String a -> a)
-> (String -> Either String a) -> String -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReadE a -> String -> Either String a
forall a. ReadE a -> String -> Either String a
runReadE ReadE a
r

parsecToReadE :: (String -> ErrorMsg) -> ParsecParser a -> ReadE a
parsecToReadE :: (String -> String) -> ParsecParser a -> ReadE a
parsecToReadE String -> String
err ParsecParser a
p = (String -> Either String a) -> ReadE a
forall a. (String -> Either String a) -> ReadE a
ReadE ((String -> Either String a) -> ReadE a)
-> (String -> Either String a) -> ReadE a
forall a b. (a -> b) -> a -> b
$ \String
txt ->
    case ParsecParser a -> String -> FieldLineStream -> Either ParseError a
forall a.
ParsecParser a -> String -> FieldLineStream -> Either ParseError a
runParsecParser ParsecParser a
p String
"<parsecToReadE>" (String -> FieldLineStream
fieldLineStreamFromString String
txt) of
        Right a
x -> a -> Either String a
forall a b. b -> Either a b
Right a
x
        Left ParseError
_e -> String -> Either String a
forall a b. a -> Either a b
Left (String -> String
err String
txt)
-- TODO: use parsec error to make 'ErrorMsg'.