{- |
Module      : Control.Lens.Grammar.Boole
Description : Boolean algebras & token classes
Copyright   : (C) 2026 - Eitan Chatav
License     : BSD-style (see the file LICENSE)
Maintainer  : Eitan Chatav <eitan.chatav@gmail.com>
Stability   : provisional
Portability : non-portable

See Boole, [The Mathematical Analysis of Logic]
(https://www.gutenberg.org/files/36884/36884-pdf.pdf).
Categorized token classes form a Boolean algebra.
-}

module Control.Lens.Grammar.Boole
  ( -- * BooleanAlgebra
    BooleanAlgebra (..)
  , andB, orB, allB, anyB
    -- * TokenAlgebra
  , TokenAlgebra (..)
  , TokenTest (..)
  ) where

import Control.Applicative
import Control.Lens.Grammar.Kleene
import Control.Lens.Grammar.Token
import Data.Foldable
import Data.Monoid
import Data.Profunctor
import Data.Profunctor.Distributor
import qualified Data.Set as Set
import GHC.Generics

-- | A `BooleanAlgebra`, like `Bool`, supporting classical logical operations.
class BooleanAlgebra b where

  -- | conjunction
  (>&&<) :: b -> b -> b
  default (>&&<)
    :: (b ~ f bool, BooleanAlgebra bool, Applicative f) => b -> b -> b
  (>&&<) = (bool -> bool -> bool) -> f bool -> f bool -> f bool
forall a b c. (a -> b -> c) -> f a -> f b -> f c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 bool -> bool -> bool
forall b. BooleanAlgebra b => b -> b -> b
(>&&<)

  -- | disjunction
  (>||<) :: b -> b -> b
  default (>||<)
    :: (b ~ f bool, BooleanAlgebra bool, Applicative f) => b -> b -> b
  (>||<) = (bool -> bool -> bool) -> f bool -> f bool -> f bool
forall a b c. (a -> b -> c) -> f a -> f b -> f c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 bool -> bool -> bool
forall b. BooleanAlgebra b => b -> b -> b
(>||<)

  -- | negation
  notB :: b -> b
  default notB
    :: (b ~ f bool, BooleanAlgebra bool, Functor f) => b -> b
  notB = (bool -> bool) -> f bool -> f bool
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap bool -> bool
forall b. BooleanAlgebra b => b -> b
notB

  -- | inclusion
  fromBool :: Bool -> b
  default fromBool
    :: (b ~ f bool, BooleanAlgebra bool, Applicative f) => Bool -> b
  fromBool = bool -> f bool
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (bool -> f bool) -> (Bool -> bool) -> Bool -> f bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> bool
forall b. BooleanAlgebra b => Bool -> b
fromBool

-- | cumulative conjunction
andB :: (Foldable f, BooleanAlgebra b) => f b -> b
andB :: forall (f :: * -> *) b. (Foldable f, BooleanAlgebra b) => f b -> b
andB = (b -> b -> b) -> b -> f b -> b
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' b -> b -> b
forall b. BooleanAlgebra b => b -> b -> b
(>&&<) (Bool -> b
forall b. BooleanAlgebra b => Bool -> b
fromBool Bool
True)

-- | cumulative disjunction
orB :: (Foldable f, BooleanAlgebra b) => f b -> b
orB :: forall (f :: * -> *) b. (Foldable f, BooleanAlgebra b) => f b -> b
orB = (b -> b -> b) -> b -> f b -> b
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' b -> b -> b
forall b. BooleanAlgebra b => b -> b -> b
(>||<) (Bool -> b
forall b. BooleanAlgebra b => Bool -> b
fromBool Bool
False)

-- | universal
allB :: (Foldable f, BooleanAlgebra b) => (a -> b) -> f a -> b
allB :: forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
allB a -> b
f = (b -> a -> b) -> b -> f a -> b
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\b
b a
a -> b
b b -> b -> b
forall b. BooleanAlgebra b => b -> b -> b
>&&< a -> b
f a
a) (Bool -> b
forall b. BooleanAlgebra b => Bool -> b
fromBool Bool
True)

-- | existential
anyB :: (Foldable f, BooleanAlgebra b) => (a -> b) -> f a -> b
anyB :: forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
anyB a -> b
f = (b -> a -> b) -> b -> f a -> b
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\b
b a
a -> b
b b -> b -> b
forall b. BooleanAlgebra b => b -> b -> b
>||< a -> b
f a
a) (Bool -> b
forall b. BooleanAlgebra b => Bool -> b
fromBool Bool
False)

-- | `TokenTest` forms a closed `Tokenized` `BooleanAlgebra`
-- of `Categorized` `tokenClass`es.
newtype TokenTest token = TokenTest (RegExam token (TokenTest token))

-- | `TokenAlgebra` extends `Tokenized` methods to support
-- `BooleanAlgebra` operations in a `tokenClass`
class Tokenized token p => TokenAlgebra token p where
  -- | Arguments of `tokenClass` can be constructed from
  -- `Tokenized` and `BooleanAlgebra` methods.
  tokenClass :: TokenTest token -> p
  default tokenClass
    :: (p ~ q token token, Alternator q, Cochoice q)
    => TokenTest token -> p
  tokenClass (TokenTest RegExam token (TokenTest token)
exam) = case RegExam token (TokenTest token)
exam of
    RegExam token (TokenTest token)
Fail -> p
q token token
forall a. q token a
forall (f :: * -> *) a. Alternative f => f a
empty
    RegExam token (TokenTest token)
Pass -> p
forall token p. Tokenized token p => p
anyToken
    OneOf Set token
chars -> Set token -> p
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> p
oneOf Set token
chars
    NotOneOf Set token
chars (AsIn Categorize token
cat) ->
      (token -> Bool) -> q token token
forall a (p :: * -> * -> *).
(Tokenized a (p a a), Choice p, Cochoice p) =>
(a -> Bool) -> p a a
satisfy (Set token -> token -> Bool
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> token -> Bool
notOneOf Set token
chars (token -> Bool) -> (token -> Bool) -> token -> Bool
forall b. BooleanAlgebra b => b -> b -> b
>&&< Categorize token -> token -> Bool
forall token p. Tokenized token p => Categorize token -> p
asIn Categorize token
cat)
    NotOneOf Set token
chars (NotAsIn Set (Categorize token)
cats) ->
      (token -> Bool) -> q token token
forall a (p :: * -> * -> *).
(Tokenized a (p a a), Choice p, Cochoice p) =>
(a -> Bool) -> p a a
satisfy (Set token -> token -> Bool
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> token -> Bool
notOneOf Set token
chars (token -> Bool) -> (token -> Bool) -> token -> Bool
forall b. BooleanAlgebra b => b -> b -> b
>&&< (Categorize token -> token -> Bool)
-> Set (Categorize token) -> token -> Bool
forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
allB Categorize token -> token -> Bool
forall token p. Tokenized token p => Categorize token -> p
notAsIn Set (Categorize token)
cats)
    Alternate TokenTest token
exam1 TokenTest token
exam2 -> TokenTest token -> q token token
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam1 q token token -> q token token -> q token token
forall a. q token a -> q token a -> q token a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> TokenTest token -> q token token
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam2

--instances
instance BooleanAlgebra (x -> Bool)
instance Categorized token => TokenAlgebra token (token -> Bool) where
  tokenClass :: TokenTest token -> token -> Bool
tokenClass (TokenTest RegExam token (TokenTest token)
exam) = case RegExam token (TokenTest token)
exam of
    RegExam token (TokenTest token)
Fail -> Bool -> token -> Bool
forall a b. a -> b -> a
const Bool
False
    RegExam token (TokenTest token)
Pass -> Bool -> token -> Bool
forall a b. a -> b -> a
const Bool
True
    OneOf Set token
chars -> Set token -> token -> Bool
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> token -> Bool
oneOf Set token
chars
    NotOneOf Set token
chars (AsIn Categorize token
cat) -> Set token -> token -> Bool
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> token -> Bool
notOneOf Set token
chars (token -> Bool) -> (token -> Bool) -> token -> Bool
forall b. BooleanAlgebra b => b -> b -> b
>&&< Categorize token -> token -> Bool
forall token p. Tokenized token p => Categorize token -> p
asIn Categorize token
cat
    NotOneOf Set token
chars (NotAsIn Set (Categorize token)
cats) -> Set token -> token -> Bool
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *). Foldable f => f token -> token -> Bool
notOneOf Set token
chars (token -> Bool) -> (token -> Bool) -> token -> Bool
forall b. BooleanAlgebra b => b -> b -> b
>&&< (Categorize token -> token -> Bool)
-> Set (Categorize token) -> token -> Bool
forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
allB Categorize token -> token -> Bool
forall token p. Tokenized token p => Categorize token -> p
notAsIn Set (Categorize token)
cats
    Alternate TokenTest token
exam1 TokenTest token
exam2 -> TokenTest token -> token -> Bool
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam1 (token -> Bool) -> (token -> Bool) -> token -> Bool
forall b. BooleanAlgebra b => b -> b -> b
>||< TokenTest token -> token -> Bool
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam2
instance (Applicative f, BooleanAlgebra bool)
  => BooleanAlgebra (Ap f bool)
deriving stock instance Generic (TokenTest token)
deriving stock instance
  (Categorized token, Read token, Read (Categorize token))
    => Read (TokenTest token)
deriving stock instance
  (Categorized token, Show token, Show (Categorize token))
    => Show (TokenTest token)
instance BooleanAlgebra Bool where
  fromBool :: Bool -> Bool
fromBool = Bool -> Bool
forall a. a -> a
id
  notB :: Bool -> Bool
notB = Bool -> Bool
not
  >&&< :: Bool -> Bool -> Bool
(>&&<) = Bool -> Bool -> Bool
(&&)
  >||< :: Bool -> Bool -> Bool
(>||<) = Bool -> Bool -> Bool
(||)
deriving newtype instance Categorized token
  => Eq (TokenTest token)
deriving newtype instance Categorized token
  => Ord (TokenTest token)
deriving newtype instance Categorized token
  => BooleanAlgebra (TokenTest token)
deriving newtype instance Categorized token
  => Tokenized token (TokenTest token)
instance Categorized token
  => TokenAlgebra token (RegEx token) where
  tokenClass :: TokenTest token -> RegEx token
tokenClass (TokenTest RegExam token (TokenTest token)
tokenExam) = case RegExam token (TokenTest token)
tokenExam of
    RegExam token (TokenTest token)
Fail -> RegExam token (RegEx token) -> RegEx token
forall token. RegExam token (RegEx token) -> RegEx token
RegExam RegExam token (RegEx token)
forall token alg. RegExam token alg
Fail
    RegExam token (TokenTest token)
Pass -> RegExam token (RegEx token) -> RegEx token
forall token. RegExam token (RegEx token) -> RegEx token
RegExam RegExam token (RegEx token)
forall token alg. RegExam token alg
Pass
    OneOf Set token
as -> RegExam token (RegEx token) -> RegEx token
forall token. RegExam token (RegEx token) -> RegEx token
RegExam (Set token -> RegExam token (RegEx token)
forall token alg. Set token -> RegExam token alg
OneOf Set token
as)
    NotOneOf Set token
as CategoryTest token
catTest -> RegExam token (RegEx token) -> RegEx token
forall token. RegExam token (RegEx token) -> RegEx token
RegExam (Set token -> CategoryTest token -> RegExam token (RegEx token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
as CategoryTest token
catTest)
    Alternate TokenTest token
exam1 TokenTest token
exam2 ->
      RegExam token (RegEx token) -> RegEx token
forall token. RegExam token (RegEx token) -> RegEx token
RegExam (RegEx token -> RegEx token -> RegExam token (RegEx token)
forall token alg. alg -> alg -> RegExam token alg
Alternate (TokenTest token -> RegEx token
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam1) (TokenTest token -> RegEx token
forall token p. TokenAlgebra token p => TokenTest token -> p
tokenClass TokenTest token
exam2))
instance Categorized token
  => BooleanAlgebra (RegExam token (TokenTest token)) where
  fromBool :: Bool -> RegExam token (TokenTest token)
fromBool = \case
    Bool
False -> RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail
    Bool
True -> RegExam token (TokenTest token)
forall token alg. RegExam token alg
Pass
  notB :: RegExam token (TokenTest token) -> RegExam token (TokenTest token)
notB RegExam token (TokenTest token)
Fail = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Pass
  notB RegExam token (TokenTest token)
Pass = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail
  notB (Alternate (TokenTest RegExam token (TokenTest token)
x) (TokenTest RegExam token (TokenTest token)
y)) = RegExam token (TokenTest token) -> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b
notB RegExam token (TokenTest token)
x RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< RegExam token (TokenTest token) -> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b
notB RegExam token (TokenTest token)
y
  notB (OneOf Set token
xs) = Set token -> RegExam token (TokenTest token)
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *).
Foldable f =>
f token -> RegExam token (TokenTest token)
notOneOf Set token
xs
  notB (NotOneOf Set token
xs (AsIn Categorize token
y)) = Set token -> RegExam token (TokenTest token)
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *).
Foldable f =>
f token -> RegExam token (TokenTest token)
oneOf Set token
xs RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>||< Categorize token -> RegExam token (TokenTest token)
forall token p. Tokenized token p => Categorize token -> p
notAsIn Categorize token
y
  notB (NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys)) = Set token -> RegExam token (TokenTest token)
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *).
Foldable f =>
f token -> RegExam token (TokenTest token)
oneOf Set token
xs RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>||< (Categorize token -> RegExam token (TokenTest token))
-> Set (Categorize token) -> RegExam token (TokenTest token)
forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
anyB Categorize token -> RegExam token (TokenTest token)
forall token p. Tokenized token p => Categorize token -> p
asIn Set (Categorize token)
ys
  RegExam token (TokenTest token)
_ >&&< :: RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
>&&< RegExam token (TokenTest token)
Fail = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail
  RegExam token (TokenTest token)
Fail >&&< RegExam token (TokenTest token)
_ = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail
  RegExam token (TokenTest token)
x >&&< RegExam token (TokenTest token)
Pass = RegExam token (TokenTest token)
x
  RegExam token (TokenTest token)
Pass >&&< RegExam token (TokenTest token)
y = RegExam token (TokenTest token)
y
  RegExam token (TokenTest token)
x >&&< Alternate (TokenTest RegExam token (TokenTest token)
y) (TokenTest RegExam token (TokenTest token)
z) = (RegExam token (TokenTest token)
x RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< RegExam token (TokenTest token)
y) RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>||< (RegExam token (TokenTest token)
x RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< RegExam token (TokenTest token)
z)
  Alternate (TokenTest RegExam token (TokenTest token)
x) (TokenTest RegExam token (TokenTest token)
y) >&&< RegExam token (TokenTest token)
z = (RegExam token (TokenTest token)
x RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< RegExam token (TokenTest token)
z) RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>||< (RegExam token (TokenTest token)
y RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< RegExam token (TokenTest token)
z)
  OneOf Set token
xs >&&< OneOf Set token
ys = Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set token
xs Set token
ys)
  OneOf Set token
xs >&&< NotOneOf Set token
ys (AsIn Categorize token
z) = Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf
    ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
z) (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.difference Set token
xs Set token
ys))
  NotOneOf Set token
xs (AsIn Categorize token
y) >&&< OneOf Set token
zs = Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf
    ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
z -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
z Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
y) (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.difference Set token
zs Set token
xs))
  OneOf Set token
xs >&&< NotOneOf Set token
ys (NotAsIn Set (Categorize token)
zs) = Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf
    ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Set (Categorize token) -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` Set (Categorize token)
zs) (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.difference Set token
xs Set token
ys))
  NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys) >&&< OneOf Set token
zs = Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf
    ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
z -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
z Categorize token -> Set (Categorize token) -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` Set (Categorize token)
ys) (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.difference Set token
zs Set token
xs))
  NotOneOf Set token
xs (AsIn Categorize token
y) >&&< NotOneOf Set token
ws (AsIn Categorize token
z) =
    if Categorize token
y Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
/= Categorize token
z then RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail else Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf
      ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
y)
      (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set token
xs Set token
ws)) (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
y)
  NotOneOf Set token
xs (AsIn Categorize token
y) >&&< NotOneOf Set token
ws (NotAsIn Set (Categorize token)
zs) =
    if Categorize token
y Categorize token -> Set (Categorize token) -> Bool
forall a. Eq a => a -> Set a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Set (Categorize token)
zs then RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail else Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf
      ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
y)
      (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set token
xs Set token
ws)) (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
y)
  NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys) >&&< NotOneOf Set token
ws (AsIn Categorize token
z) =
    if Categorize token
z Categorize token -> Set (Categorize token) -> Bool
forall a. Eq a => a -> Set a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Set (Categorize token)
ys then RegExam token (TokenTest token)
forall token alg. RegExam token alg
Fail else Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf
      ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
z) (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set token
xs Set token
ws))
      (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
z)
  NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys) >&&< NotOneOf Set token
ws (NotAsIn Set (Categorize token)
zs) =
    let
      xws :: Set token
xws = Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set token
xs Set token
ws
      yzs :: Set (Categorize token)
yzs = Set (Categorize token)
-> Set (Categorize token) -> Set (Categorize token)
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set (Categorize token)
ys Set (Categorize token)
zs
    in
      Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf
        ((token -> Bool) -> Set token -> Set token
forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\token
x -> token -> Categorize token
forall token. Categorized token => token -> Categorize token
categorize token
x Categorize token -> Set (Categorize token) -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` Set (Categorize token)
yzs) Set token
xws)
        (Set (Categorize token) -> CategoryTest token
forall token. Set (Categorize token) -> CategoryTest token
NotAsIn Set (Categorize token)
yzs)
  RegExam token (TokenTest token)
x >||< :: RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
>||< RegExam token (TokenTest token)
Fail = RegExam token (TokenTest token)
x
  RegExam token (TokenTest token)
Fail >||< RegExam token (TokenTest token)
y = RegExam token (TokenTest token)
y
  RegExam token (TokenTest token)
_ >||< RegExam token (TokenTest token)
Pass = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Pass
  RegExam token (TokenTest token)
Pass >||< RegExam token (TokenTest token)
_ = RegExam token (TokenTest token)
forall token alg. RegExam token alg
Pass
  RegExam token (TokenTest token)
x >||< Alternate TokenTest token
y TokenTest token
z = TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest RegExam token (TokenTest token)
x) (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate TokenTest token
y TokenTest token
z))
  Alternate TokenTest token
x TokenTest token
y >||< RegExam token (TokenTest token)
z = TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate TokenTest token
x TokenTest token
y)) (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest RegExam token (TokenTest token)
z)
  OneOf Set token
xs >||< OneOf Set token
ys = Set token -> RegExam token (TokenTest token)
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *).
Foldable f =>
f token -> RegExam token (TokenTest token)
oneOf (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set token
xs Set token
ys)
  OneOf Set token
xs >||< NotOneOf Set token
ys CategoryTest token
z =
    TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf Set token
xs)) (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
ys CategoryTest token
z))
  NotOneOf Set token
xs CategoryTest token
y >||< OneOf Set token
zs =
    TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
xs CategoryTest token
y)) (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> RegExam token (TokenTest token)
forall token alg. Set token -> RegExam token alg
OneOf Set token
zs))
  NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys) >||< NotOneOf Set token
ws (NotAsIn Set (Categorize token)
zs) =
    Set token -> RegExam token (TokenTest token)
forall token p (f :: * -> *).
(Tokenized token p, Foldable f) =>
f token -> p
forall (f :: * -> *).
Foldable f =>
f token -> RegExam token (TokenTest token)
notOneOf (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set token
xs Set token
ws) RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
-> RegExam token (TokenTest token)
forall b. BooleanAlgebra b => b -> b -> b
>&&< (Categorize token -> RegExam token (TokenTest token))
-> Set (Categorize token) -> RegExam token (TokenTest token)
forall (f :: * -> *) b a.
(Foldable f, BooleanAlgebra b) =>
(a -> b) -> f a -> b
allB Categorize token -> RegExam token (TokenTest token)
forall token p. Tokenized token p => Categorize token -> p
notAsIn (Set (Categorize token)
-> Set (Categorize token) -> Set (Categorize token)
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set (Categorize token)
ys Set (Categorize token)
zs)
  NotOneOf Set token
xs (AsIn Categorize token
y) >||< NotOneOf Set token
ws (AsIn Categorize token
z) =
    if Categorize token
y Categorize token -> Categorize token -> Bool
forall a. Eq a => a -> a -> Bool
== Categorize token
z then Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf (Set token -> Set token -> Set token
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set token
xs Set token
ws) (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
y)
    else TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate
      (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
xs (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
y)))
      (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
ws (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
z)))
  NotOneOf Set token
xs (NotAsIn Set (Categorize token)
ys) >||< NotOneOf Set token
ws (AsIn Categorize token
z) = TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate
    (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
xs (Set (Categorize token) -> CategoryTest token
forall token. Set (Categorize token) -> CategoryTest token
NotAsIn Set (Categorize token)
ys)))
    (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
ws (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
z)))
  NotOneOf Set token
xs (AsIn Categorize token
y) >||< NotOneOf Set token
ws (NotAsIn Set (Categorize token)
zs) = TokenTest token
-> TokenTest token -> RegExam token (TokenTest token)
forall token alg. alg -> alg -> RegExam token alg
Alternate
    (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
xs (Categorize token -> CategoryTest token
forall token. Categorize token -> CategoryTest token
AsIn Categorize token
y)))
    (RegExam token (TokenTest token) -> TokenTest token
forall token. RegExam token (TokenTest token) -> TokenTest token
TokenTest (Set token -> CategoryTest token -> RegExam token (TokenTest token)
forall token alg.
Set token -> CategoryTest token -> RegExam token alg
NotOneOf Set token
ws (Set (Categorize token) -> CategoryTest token
forall token. Set (Categorize token) -> CategoryTest token
NotAsIn Set (Categorize token)
zs)))