{-# LANGUAGE FlexibleContexts #-}

module Saturn.Unstable.Extra.ParsecSpec where

import qualified Data.Either as Either
import qualified Data.List.NonEmpty as NonEmpty
import qualified Saturn.Unstable.Extra.Parsec as Parsec
import qualified Test.Hspec as Hspec
import qualified Text.Parsec as Parsec

spec :: Hspec.Spec
spec :: Spec
spec = String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe String
"Saturn.Unstable.Extra.Parsec" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe String
"either" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    let parsec :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m (Either Char Char)
        parsec :: forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (Either Char Char)
parsec = ParsecT s u m Char
-> ParsecT s u m Char -> ParsecT s u m (Either Char Char)
forall s u (m :: * -> *) a b.
ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m (Either a b)
Parsec.either (Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
Parsec.char Char
'a') (Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
Parsec.char Char
'b')

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"succeeds with left" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (Either Char Char)
-> String -> String -> Either ParseError (Either Char Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (Either Char Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (Either Char Char)
parsec String
"" String
"a" Either ParseError (Either Char Char)
-> Either ParseError (Either Char Char) -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` Either Char Char -> Either ParseError (Either Char Char)
forall a b. b -> Either a b
Right (Char -> Either Char Char
forall a b. a -> Either a b
Left Char
'a')

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"succeeds with right" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (Either Char Char)
-> String -> String -> Either ParseError (Either Char Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (Either Char Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (Either Char Char)
parsec String
"" String
"b" Either ParseError (Either Char Char)
-> Either ParseError (Either Char Char) -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` Either Char Char -> Either ParseError (Either Char Char)
forall a b. b -> Either a b
Right (Char -> Either Char Char
forall a b. b -> Either a b
Right Char
'b')

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"fails with neither" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (Either Char Char)
-> String -> String -> Either ParseError (Either Char Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (Either Char Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (Either Char Char)
parsec String
"" String
"c" Either ParseError (Either Char Char)
-> (Either ParseError (Either Char Char) -> Bool) -> Expectation
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation
`Hspec.shouldSatisfy` Either ParseError (Either Char Char) -> Bool
forall a b. Either a b -> Bool
Either.isLeft

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe String
"sepByNE" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    let parsec :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m (NonEmpty.NonEmpty Char)
        parsec :: forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (NonEmpty Char)
parsec = ParsecT s u m Char
-> ParsecT s u m Char -> ParsecT s u m (NonEmpty Char)
forall s u (m :: * -> *) a sep.
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m (NonEmpty a)
Parsec.sepByNE (Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
Parsec.char Char
'a') (Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
Parsec.char Char
' ')

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"succeeds with one" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (NonEmpty Char)
-> String -> String -> Either ParseError (NonEmpty Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (NonEmpty Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (NonEmpty Char)
parsec String
"" String
"a" Either ParseError (NonEmpty Char)
-> Either ParseError (NonEmpty Char) -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` NonEmpty Char -> Either ParseError (NonEmpty Char)
forall a b. b -> Either a b
Right (Char
'a' Char -> String -> NonEmpty Char
forall a. a -> [a] -> NonEmpty a
NonEmpty.:| [])

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"succeeds with many" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (NonEmpty Char)
-> String -> String -> Either ParseError (NonEmpty Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (NonEmpty Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (NonEmpty Char)
parsec String
"" String
"a a" Either ParseError (NonEmpty Char)
-> Either ParseError (NonEmpty Char) -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` NonEmpty Char -> Either ParseError (NonEmpty Char)
forall a b. b -> Either a b
Right (Char
'a' Char -> String -> NonEmpty Char
forall a. a -> [a] -> NonEmpty a
NonEmpty.:| String
"a")

    String -> Expectation -> SpecWith (Arg Expectation)
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"fails with none" (Expectation -> SpecWith (Arg Expectation))
-> Expectation -> SpecWith (Arg Expectation)
forall a b. (a -> b) -> a -> b
$ do
      Parsec String () (NonEmpty Char)
-> String -> String -> Either ParseError (NonEmpty Char)
forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse Parsec String () (NonEmpty Char)
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (NonEmpty Char)
parsec String
"" String
"" Either ParseError (NonEmpty Char)
-> (Either ParseError (NonEmpty Char) -> Bool) -> Expectation
forall a. (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation
`Hspec.shouldSatisfy` Either ParseError (NonEmpty Char) -> Bool
forall a b. Either a b -> Bool
Either.isLeft