content: {-# LANGUAGE OverloadedStrings #-}
  
  module Main
  ( main
  ) where
  
  import Control.Applicative
  
  import Data.Either
  
  import qualified Test.QuickCheck as Q
  
  import Text.Parser.Char
  import Text.Parser.Combinators
  
  import Text.Trifecta.Parser
  import Text.Trifecta.Result
  
  import System.Exit
  
  -- -------------------------------------------------------------------------- --
  -- Main
  
  main :: IO ()
  main = mapM Q.quickCheckResult tests >>= \x -> case filter (not . passed) x of
      [] -> exitSuccess
      _ -> exitFailure
    where
      passed Q.Success{} = True
      passed _ = False
  
  -- -------------------------------------------------------------------------- --
  -- Tests
  
  tests :: [Q.Property]
  tests =
      [ Q.property prop_fail
      , Q.property prop_succeed
      , Q.property prop_notFollowedBy0
      , Q.property prop_notFollowedBy1
      , Q.property prop_notFollowedBy2
      , Q.property prop_notFollowedBy3
      ]
  
  -- -------------------------------------------------------------------------- --
  -- Properties
  
  prop_fail :: String -> Bool
  prop_fail = isLeft . parse (fail "fail" :: Parser ())
  
  prop_succeed :: String -> Bool
  prop_succeed = isRight . parse (mempty :: Parser ())
  
  prop_notFollowedBy0 :: Char -> Char -> Bool
  prop_notFollowedBy0 x y = either (\_ -> x == y) (/= y)
      $ parse (notFollowedBy (char y) *> anyChar) [x]
  
  prop_notFollowedBy1 :: Char -> Bool
  prop_notFollowedBy1 x = either (\_ -> x == x) (/= x)
      $ parse (notFollowedBy (char x) *> anyChar) [x]
  
  prop_notFollowedBy2 :: String -> Char -> Bool
  prop_notFollowedBy2 x y = isLeft
      $ parse (anyChar *> notFollowedBy (char y) *> char y) x
  
  prop_notFollowedBy3 :: Char -> Bool
  prop_notFollowedBy3 x = isRight
      $ parse (notFollowedBy (char x) <|> char x *> pure ()) [x]
  
  -- -------------------------------------------------------------------------- --
  -- Utils
  
  parse :: Parser a -> String -> Either String a
  parse p s = case parseString p mempty s of
      Failure e -> Left (show e)
      Success a -> Right a
  