{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternGuards #-}
module BNFC.Types.Regex where
import BNFC.Prelude
import qualified Data.List        as List
import qualified BNFC.Utils.List2 as List2
import qualified Data.Set         as Set
data Regex
  = RChar  CharClass
      
  | RAlts  (List2 Regex)
      
      
      
      
  | RMinus Regex Regex
      
      
      
      
  | REps
      
  | RSeqs  (List2 Regex)
      
      
  | RStar  Regex
      
      
  | RPlus  Regex
      
      
  | ROpt   Regex
      
      
  deriving (Regex -> Regex -> Bool
(Regex -> Regex -> Bool) -> (Regex -> Regex -> Bool) -> Eq Regex
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Regex -> Regex -> Bool
$c/= :: Regex -> Regex -> Bool
== :: Regex -> Regex -> Bool
$c== :: Regex -> Regex -> Bool
Eq, Eq Regex
Eq Regex
-> (Regex -> Regex -> Ordering)
-> (Regex -> Regex -> Bool)
-> (Regex -> Regex -> Bool)
-> (Regex -> Regex -> Bool)
-> (Regex -> Regex -> Bool)
-> (Regex -> Regex -> Regex)
-> (Regex -> Regex -> Regex)
-> Ord Regex
Regex -> Regex -> Bool
Regex -> Regex -> Ordering
Regex -> Regex -> Regex
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Regex -> Regex -> Regex
$cmin :: Regex -> Regex -> Regex
max :: Regex -> Regex -> Regex
$cmax :: Regex -> Regex -> Regex
>= :: Regex -> Regex -> Bool
$c>= :: Regex -> Regex -> Bool
> :: Regex -> Regex -> Bool
$c> :: Regex -> Regex -> Bool
<= :: Regex -> Regex -> Bool
$c<= :: Regex -> Regex -> Bool
< :: Regex -> Regex -> Bool
$c< :: Regex -> Regex -> Bool
compare :: Regex -> Regex -> Ordering
$ccompare :: Regex -> Regex -> Ordering
$cp1Ord :: Eq Regex
Ord, Int -> Regex -> ShowS
[Regex] -> ShowS
Regex -> String
(Int -> Regex -> ShowS)
-> (Regex -> String) -> ([Regex] -> ShowS) -> Show Regex
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Regex] -> ShowS
$cshowList :: [Regex] -> ShowS
show :: Regex -> String
$cshow :: Regex -> String
showsPrec :: Int -> Regex -> ShowS
$cshowsPrec :: Int -> Regex -> ShowS
Show)
pattern REmpty :: Regex
pattern $bREmpty :: Regex
$mREmpty :: forall r. Regex -> (Void# -> r) -> (Void# -> r) -> r
REmpty = RChar CEmpty
pattern RAlt :: Regex -> Regex -> Regex
pattern $bRAlt :: Regex -> Regex -> Regex
$mRAlt :: forall r. Regex -> (Regex -> Regex -> r) -> (Void# -> r) -> r
RAlt r1 r2 = RAlts (List2 r1 r2 [])
pattern RSeq :: Regex -> Regex -> Regex
pattern $bRSeq :: Regex -> Regex -> Regex
$mRSeq :: forall r. Regex -> (Regex -> Regex -> r) -> (Void# -> r) -> r
RSeq r1 r2 = RSeqs (List2 r1 r2 [])
nullable :: Regex -> Bool
nullable :: Regex -> Bool
nullable = \case
  RChar CharClass
_      -> Bool
False
  RMinus Regex
r1 Regex
r2 -> Regex -> Bool
nullable Regex
r1 Bool -> Bool -> Bool
&& Bool -> Bool
not (Regex -> Bool
nullable Regex
r2)
  RAlts List2 Regex
rs     -> (Regex -> Bool) -> List2 Regex -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Regex -> Bool
nullable List2 Regex
rs
  RSeqs List2 Regex
rs     -> (Regex -> Bool) -> List2 Regex -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Regex -> Bool
nullable List2 Regex
rs
  Regex
REps         -> Bool
True
  RStar Regex
_      -> Bool
True
  RPlus Regex
r      -> Regex -> Bool
nullable Regex
r
  ROpt Regex
_       -> Bool
True
class Satisfiable a where
  satisfiable :: a -> Bool
instance Satisfiable Regex where
  satisfiable :: Regex -> Bool
satisfiable = \case
    RChar CharClass
c      -> CharClass -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable CharClass
c
    RMinus Regex
r Regex
_   -> Regex -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable Regex
r            
    RAlts List2 Regex
rs     -> (Regex -> Bool) -> List2 Regex -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Regex -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable List2 Regex
rs
    RSeqs List2 Regex
rs     -> (Regex -> Bool) -> List2 Regex -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Regex -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable List2 Regex
rs
    Regex
REps         -> Bool
True
    RStar Regex
_      -> Bool
True
    RPlus Regex
r      -> Regex -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable Regex
r
    ROpt Regex
_       -> Bool
True
instance Satisfiable CharClass where
  satisfiable :: CharClass -> Bool
satisfiable (CMinus CharClassUnion
c CharClassUnion
_) = CharClassUnion -> Bool
forall a. Satisfiable a => a -> Bool
satisfiable CharClassUnion
c   
instance Satisfiable CharClassUnion where
  satisfiable :: CharClassUnion -> Bool
satisfiable = \case
    CharClassUnion
CAny    -> Bool
True
    CAlt [CharClassAtom]
cs -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CharClassAtom]
cs
data CharClass = CMinus
  { CharClass -> CharClassUnion
ccYes :: CharClassUnion
      
  , CharClass -> CharClassUnion
ccNo  :: CharClassUnion
      
      
  }
  deriving (CharClass -> CharClass -> Bool
(CharClass -> CharClass -> Bool)
-> (CharClass -> CharClass -> Bool) -> Eq CharClass
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CharClass -> CharClass -> Bool
$c/= :: CharClass -> CharClass -> Bool
== :: CharClass -> CharClass -> Bool
$c== :: CharClass -> CharClass -> Bool
Eq, Eq CharClass
Eq CharClass
-> (CharClass -> CharClass -> Ordering)
-> (CharClass -> CharClass -> Bool)
-> (CharClass -> CharClass -> Bool)
-> (CharClass -> CharClass -> Bool)
-> (CharClass -> CharClass -> Bool)
-> (CharClass -> CharClass -> CharClass)
-> (CharClass -> CharClass -> CharClass)
-> Ord CharClass
CharClass -> CharClass -> Bool
CharClass -> CharClass -> Ordering
CharClass -> CharClass -> CharClass
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CharClass -> CharClass -> CharClass
$cmin :: CharClass -> CharClass -> CharClass
max :: CharClass -> CharClass -> CharClass
$cmax :: CharClass -> CharClass -> CharClass
>= :: CharClass -> CharClass -> Bool
$c>= :: CharClass -> CharClass -> Bool
> :: CharClass -> CharClass -> Bool
$c> :: CharClass -> CharClass -> Bool
<= :: CharClass -> CharClass -> Bool
$c<= :: CharClass -> CharClass -> Bool
< :: CharClass -> CharClass -> Bool
$c< :: CharClass -> CharClass -> Bool
compare :: CharClass -> CharClass -> Ordering
$ccompare :: CharClass -> CharClass -> Ordering
$cp1Ord :: Eq CharClass
Ord, Int -> CharClass -> ShowS
[CharClass] -> ShowS
CharClass -> String
(Int -> CharClass -> ShowS)
-> (CharClass -> String)
-> ([CharClass] -> ShowS)
-> Show CharClass
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CharClass] -> ShowS
$cshowList :: [CharClass] -> ShowS
show :: CharClass -> String
$cshow :: CharClass -> String
showsPrec :: Int -> CharClass -> ShowS
$cshowsPrec :: Int -> CharClass -> ShowS
Show)
pattern CEmpty :: CharClass
pattern $bCEmpty :: CharClass
$mCEmpty :: forall r. CharClass -> (Void# -> r) -> (Void# -> r) -> r
CEmpty = CC CCEmpty
pattern CC :: CharClassUnion -> CharClass
pattern $bCC :: CharClassUnion -> CharClass
$mCC :: forall r. CharClass -> (CharClassUnion -> r) -> (Void# -> r) -> r
CC c = c `CMinus` CCEmpty
data CharClassUnion
  = CAny
      
  | CAlt [CharClassAtom]
      
  deriving (Eq CharClassUnion
Eq CharClassUnion
-> (CharClassUnion -> CharClassUnion -> Ordering)
-> (CharClassUnion -> CharClassUnion -> Bool)
-> (CharClassUnion -> CharClassUnion -> Bool)
-> (CharClassUnion -> CharClassUnion -> Bool)
-> (CharClassUnion -> CharClassUnion -> Bool)
-> (CharClassUnion -> CharClassUnion -> CharClassUnion)
-> (CharClassUnion -> CharClassUnion -> CharClassUnion)
-> Ord CharClassUnion
CharClassUnion -> CharClassUnion -> Bool
CharClassUnion -> CharClassUnion -> Ordering
CharClassUnion -> CharClassUnion -> CharClassUnion
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CharClassUnion -> CharClassUnion -> CharClassUnion
$cmin :: CharClassUnion -> CharClassUnion -> CharClassUnion
max :: CharClassUnion -> CharClassUnion -> CharClassUnion
$cmax :: CharClassUnion -> CharClassUnion -> CharClassUnion
>= :: CharClassUnion -> CharClassUnion -> Bool
$c>= :: CharClassUnion -> CharClassUnion -> Bool
> :: CharClassUnion -> CharClassUnion -> Bool
$c> :: CharClassUnion -> CharClassUnion -> Bool
<= :: CharClassUnion -> CharClassUnion -> Bool
$c<= :: CharClassUnion -> CharClassUnion -> Bool
< :: CharClassUnion -> CharClassUnion -> Bool
$c< :: CharClassUnion -> CharClassUnion -> Bool
compare :: CharClassUnion -> CharClassUnion -> Ordering
$ccompare :: CharClassUnion -> CharClassUnion -> Ordering
$cp1Ord :: Eq CharClassUnion
Ord, Int -> CharClassUnion -> ShowS
[CharClassUnion] -> ShowS
CharClassUnion -> String
(Int -> CharClassUnion -> ShowS)
-> (CharClassUnion -> String)
-> ([CharClassUnion] -> ShowS)
-> Show CharClassUnion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CharClassUnion] -> ShowS
$cshowList :: [CharClassUnion] -> ShowS
show :: CharClassUnion -> String
$cshow :: CharClassUnion -> String
showsPrec :: Int -> CharClassUnion -> ShowS
$cshowsPrec :: Int -> CharClassUnion -> ShowS
Show)
instance Eq CharClassUnion where
  CharClassUnion
CAny     == :: CharClassUnion -> CharClassUnion -> Bool
== CharClassUnion
CAny     = Bool
True
  CAlt [CharClassAtom]
cc1 == CAlt [CharClassAtom]
cc2 = [CharClassAtom] -> Set CharClassAtom
forall a. Ord a => [a] -> Set a
Set.fromList [CharClassAtom]
cc1 Set CharClassAtom -> Set CharClassAtom -> Bool
forall a. Eq a => a -> a -> Bool
== [CharClassAtom] -> Set CharClassAtom
forall a. Ord a => [a] -> Set a
Set.fromList [CharClassAtom]
cc2
  CharClassUnion
CAny     == CAlt{}   = Bool
False
  CAlt{}   == CharClassUnion
CAny     = Bool
False
pattern CCEmpty :: CharClassUnion
pattern $bCCEmpty :: CharClassUnion
$mCCEmpty :: forall r. CharClassUnion -> (Void# -> r) -> (Void# -> r) -> r
CCEmpty = CAlt []
data CharClassAtom
  = CChar Char  
  | CDigit      
  | CLower      
  | CUpper      
  deriving (CharClassAtom -> CharClassAtom -> Bool
(CharClassAtom -> CharClassAtom -> Bool)
-> (CharClassAtom -> CharClassAtom -> Bool) -> Eq CharClassAtom
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CharClassAtom -> CharClassAtom -> Bool
$c/= :: CharClassAtom -> CharClassAtom -> Bool
== :: CharClassAtom -> CharClassAtom -> Bool
$c== :: CharClassAtom -> CharClassAtom -> Bool
Eq, Eq CharClassAtom
Eq CharClassAtom
-> (CharClassAtom -> CharClassAtom -> Ordering)
-> (CharClassAtom -> CharClassAtom -> Bool)
-> (CharClassAtom -> CharClassAtom -> Bool)
-> (CharClassAtom -> CharClassAtom -> Bool)
-> (CharClassAtom -> CharClassAtom -> Bool)
-> (CharClassAtom -> CharClassAtom -> CharClassAtom)
-> (CharClassAtom -> CharClassAtom -> CharClassAtom)
-> Ord CharClassAtom
CharClassAtom -> CharClassAtom -> Bool
CharClassAtom -> CharClassAtom -> Ordering
CharClassAtom -> CharClassAtom -> CharClassAtom
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CharClassAtom -> CharClassAtom -> CharClassAtom
$cmin :: CharClassAtom -> CharClassAtom -> CharClassAtom
max :: CharClassAtom -> CharClassAtom -> CharClassAtom
$cmax :: CharClassAtom -> CharClassAtom -> CharClassAtom
>= :: CharClassAtom -> CharClassAtom -> Bool
$c>= :: CharClassAtom -> CharClassAtom -> Bool
> :: CharClassAtom -> CharClassAtom -> Bool
$c> :: CharClassAtom -> CharClassAtom -> Bool
<= :: CharClassAtom -> CharClassAtom -> Bool
$c<= :: CharClassAtom -> CharClassAtom -> Bool
< :: CharClassAtom -> CharClassAtom -> Bool
$c< :: CharClassAtom -> CharClassAtom -> Bool
compare :: CharClassAtom -> CharClassAtom -> Ordering
$ccompare :: CharClassAtom -> CharClassAtom -> Ordering
$cp1Ord :: Eq CharClassAtom
Ord, Int -> CharClassAtom -> ShowS
[CharClassAtom] -> ShowS
CharClassAtom -> String
(Int -> CharClassAtom -> ShowS)
-> (CharClassAtom -> String)
-> ([CharClassAtom] -> ShowS)
-> Show CharClassAtom
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CharClassAtom] -> ShowS
$cshowList :: [CharClassAtom] -> ShowS
show :: CharClassAtom -> String
$cshow :: CharClassAtom -> String
showsPrec :: Int -> CharClassAtom -> ShowS
$cshowsPrec :: Int -> CharClassAtom -> ShowS
Show)
instance Semigroup CharClassUnion where
  CharClassUnion
CAny    <> :: CharClassUnion -> CharClassUnion -> CharClassUnion
<> CharClassUnion
_        = CharClassUnion
CAny
  CharClassUnion
_       <> CharClassUnion
CAny     = CharClassUnion
CAny
  CAlt [CharClassAtom]
cs <> CAlt [CharClassAtom]
cs' = [CharClassAtom] -> CharClassUnion
CAlt ([CharClassAtom]
cs [CharClassAtom] -> [CharClassAtom] -> [CharClassAtom]
forall a. Semigroup a => a -> a -> a
<> [CharClassAtom]
cs')
instance Monoid CharClassUnion where
  mempty :: CharClassUnion
mempty  = [CharClassAtom] -> CharClassUnion
CAlt []
  mappend :: CharClassUnion -> CharClassUnion -> CharClassUnion
mappend = CharClassUnion -> CharClassUnion -> CharClassUnion
forall a. Semigroup a => a -> a -> a
(<>)
rChar :: Char -> Regex
rChar :: Char -> Regex
rChar = CharClass -> Regex
RChar (CharClass -> Regex) -> (Char -> CharClass) -> Char -> Regex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> CharClass
cChar
rSeq :: Regex -> Regex -> Regex
rSeq :: Regex -> Regex -> Regex
rSeq = ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex)
-> ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b. (a -> b) -> a -> b
$ \case
  
  (Regex
REmpty , Regex
_       ) -> Regex
REmpty
  (Regex
_       , Regex
REmpty ) -> Regex
REmpty
  
  (Regex
REps    , Regex
r      ) -> Regex
r
  (Regex
r       , Regex
REps   ) -> Regex
r
  
  (RStar Regex
r1, RStar Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RStar Regex
r1
  
  (ROpt  Regex
r1, RStar Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RStar Regex
r2
  (RStar Regex
r1, ROpt  Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RStar Regex
r1
  
  (RPlus Regex
r1, RStar Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r1
  (RStar Regex
r1, RPlus Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r2
  
  (RPlus Regex
r1, ROpt  Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r1
  (ROpt  Regex
r1, RPlus Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r2
  
  (Regex
r1      , RStar Regex
r2) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r2
  (RStar Regex
r1, Regex
r2      ) | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2 -> Regex -> Regex
RPlus Regex
r1
  
  (RSeqs List2 Regex
r1, RSeqs List2 Regex
r2) -> List2 Regex -> Regex
RSeqs (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ List2 Regex
r1 List2 Regex -> List2 Regex -> List2 Regex
forall a. Semigroup a => a -> a -> a
<> List2 Regex
r2
  (Regex
r       , RSeqs List2 Regex
rs) -> List2 Regex -> Regex
RSeqs (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ Regex -> List2 Regex -> List2 Regex
forall a. a -> List2 a -> List2 a
List2.cons Regex
r List2 Regex
rs
  (RSeqs List2 Regex
rs, Regex
r       ) -> List2 Regex -> Regex
RSeqs (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ List2 Regex -> Regex -> List2 Regex
forall a. List2 a -> a -> List2 a
List2.snoc List2 Regex
rs Regex
r
  
  (Regex
r1      , Regex
r2      ) -> Regex
r1 Regex -> Regex -> Regex
`RSeq` Regex
r2
rSeqs :: [Regex] -> Regex
rSeqs :: [Regex] -> Regex
rSeqs = (Regex -> Regex -> Regex) -> Regex -> [Regex] -> Regex
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Regex -> Regex -> Regex
rSeq Regex
REps
rAlt :: Regex -> Regex -> Regex
rAlt :: Regex -> Regex -> Regex
rAlt = ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex)
-> ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b. (a -> b) -> a -> b
$ \case
  
  (Regex
REmpty  , Regex
r     ) -> Regex
r
  (Regex
r       , Regex
REmpty) -> Regex
r
  
  (RChar CharClass
c1, RChar CharClass
c2) -> CharClass -> CharClass -> Regex
cAlt CharClass
c1 CharClass
c2
  
  (RAlts List2 Regex
r1, RAlts List2 Regex
r2) -> List2 Regex -> Regex
RAlts (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ [Regex] -> List2 Regex
forall a. [a] -> List2 a
List2.fromList ([Regex] -> List2 Regex) -> [Regex] -> List2 Regex
forall a b. (a -> b) -> a -> b
$ [Regex] -> [Regex]
forall a. Ord a => [a] -> [a]
nubOrd ([Regex] -> [Regex]) -> [Regex] -> [Regex]
forall a b. (a -> b) -> a -> b
$ List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
r1 [Regex] -> [Regex] -> [Regex]
forall a. Semigroup a => a -> a -> a
<> List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
r2
  (Regex
r       , RAlts List2 Regex
rs)
     | Regex
r Regex -> List2 Regex -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` List2 Regex
rs -> List2 Regex -> Regex
RAlts List2 Regex
rs
     | Bool
otherwise   -> List2 Regex -> Regex
RAlts (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ Regex -> List2 Regex -> List2 Regex
forall a. a -> List2 a -> List2 a
List2.cons Regex
r List2 Regex
rs
  (RAlts List2 Regex
rs, Regex
r       )
     | Regex
r Regex -> List2 Regex -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` List2 Regex
rs -> List2 Regex -> Regex
RAlts List2 Regex
rs
     | Bool
otherwise   -> List2 Regex -> Regex
RAlts (List2 Regex -> Regex) -> List2 Regex -> Regex
forall a b. (a -> b) -> a -> b
$ List2 Regex -> Regex -> List2 Regex
forall a. List2 a -> a -> List2 a
List2.snoc List2 Regex
rs Regex
r
  
  (Regex
r1, Regex
r2)
     | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2  -> Regex
r1  
     | Bool
otherwise -> Regex
r1 Regex -> Regex -> Regex
`RAlt` Regex
r2
rAlts :: [Regex] -> Regex
rAlts :: [Regex] -> Regex
rAlts = (Regex -> Regex -> Regex) -> Regex -> [Regex] -> Regex
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Regex -> Regex -> Regex
rAlt Regex
REmpty
rMinus :: Regex -> Regex -> Regex
rMinus :: Regex -> Regex -> Regex
rMinus = ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex)
-> ((Regex, Regex) -> Regex) -> Regex -> Regex -> Regex
forall a b. (a -> b) -> a -> b
$ \case
  
  (Regex
REmpty  , Regex
_     ) -> Regex
REmpty
  
  (Regex
r       , Regex
REmpty) -> Regex
r
  
  (RChar CharClass
c1, RChar CharClass
c2) -> CharClass -> CharClass -> Regex
cMinus CharClass
c1 CharClass
c2
  
  (RAlts List2 Regex
rs, RAlts List2 Regex
ss) ->
    case List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
rs [Regex] -> [Regex] -> [Regex]
forall a. Eq a => [a] -> [a] -> [a]
List.\\ List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
ss of
      []  -> Regex
REmpty
      [Regex]
rs' -> [Regex] -> Regex
rAlts [Regex]
rs' Regex -> Regex -> Regex
`RMinus` List2 Regex -> Regex
RAlts List2 Regex
ss
  (Regex
r       , RAlts List2 Regex
rs)
    | Regex
r Regex -> List2 Regex -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` List2 Regex
rs -> Regex
REmpty
    | Bool
otherwise   -> Regex
r Regex -> Regex -> Regex
`RMinus` List2 Regex -> Regex
RAlts List2 Regex
rs
  
  (Regex
r1, Regex
r2)
     | Regex
r1 Regex -> Regex -> Bool
forall a. Eq a => a -> a -> Bool
== Regex
r2  -> Regex
REmpty
     | Bool
otherwise -> Regex
r1 Regex -> Regex -> Regex
`RMinus` Regex
r2
rStar :: Regex -> Regex
rStar :: Regex -> Regex
rStar = \case
  Regex
REmpty   -> Regex
REps
  Regex
REps     -> Regex
REps
  ROpt  Regex
r  -> Regex -> Regex
RStar Regex
r
  RStar Regex
r  -> Regex -> Regex
RStar Regex
r
  RPlus Regex
r  -> Regex -> Regex
RStar Regex
r
  Regex
r        -> Regex -> Regex
RStar Regex
r
rPlus :: Regex -> Regex
rPlus :: Regex -> Regex
rPlus = \case
  Regex
REmpty   -> Regex
REmpty
  Regex
REps     -> Regex
REps
  ROpt  Regex
r  -> Regex -> Regex
RStar Regex
r
  RStar Regex
r  -> Regex -> Regex
RStar Regex
r
  RPlus Regex
r  -> Regex -> Regex
RPlus Regex
r
  Regex
r        -> Regex -> Regex
RPlus Regex
r
rOpt :: Regex -> Regex
rOpt :: Regex -> Regex
rOpt = \case
  Regex
REmpty   -> Regex
REps
  Regex
REps     -> Regex
REps
  RStar Regex
r  -> Regex -> Regex
RStar Regex
r
  RPlus Regex
r  -> Regex -> Regex
RStar Regex
r
  ROpt  Regex
r  -> Regex -> Regex
ROpt  Regex
r
  Regex
r        -> Regex -> Regex
ROpt  Regex
r
cAlt :: CharClass -> CharClass -> Regex
cAlt :: CharClass -> CharClass -> Regex
cAlt c1 :: CharClass
c1@(CMinus CharClassUnion
p1 CharClassUnion
m1) c2 :: CharClass
c2@(CMinus CharClassUnion
p2 CharClassUnion
m2)
  | CharClass
c1 CharClass -> CharClass -> Bool
forall a. Eq a => a -> a -> Bool
== CharClass
cAny Bool -> Bool -> Bool
|| CharClass
c2 CharClass -> CharClass -> Bool
forall a. Eq a => a -> a -> Bool
== CharClass
cAny     = CharClass -> Regex
RChar CharClass
cAny
  | CharClassUnion
p1 CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
`ccuMinus` CharClassUnion
m2 Either CharClass CharClassUnion
-> Either CharClass CharClassUnion -> Bool
forall a. Eq a => a -> a -> Bool
== CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right CharClassUnion
p1,
    CharClassUnion
p2 CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
`ccuMinus` CharClassUnion
m1 Either CharClass CharClassUnion
-> Either CharClass CharClassUnion -> Bool
forall a. Eq a => a -> a -> Bool
== CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right CharClassUnion
p2 = CharClass -> Regex
RChar (CharClass -> Regex) -> CharClass -> Regex
forall a b. (a -> b) -> a -> b
$ (CharClass -> CharClass)
-> (CharClassUnion -> CharClass)
-> Either CharClass CharClassUnion
-> CharClass
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either CharClass -> CharClass
forall a. a -> a
id CharClassUnion -> CharClass
CC (Either CharClass CharClassUnion -> CharClass)
-> Either CharClass CharClassUnion -> CharClass
forall a b. (a -> b) -> a -> b
$ (CharClassUnion
p1 CharClassUnion -> CharClassUnion -> CharClassUnion
forall a. Semigroup a => a -> a -> a
<> CharClassUnion
p2) CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
`ccuMinus` (CharClassUnion
m1 CharClassUnion -> CharClassUnion -> CharClassUnion
forall a. Semigroup a => a -> a -> a
<> CharClassUnion
m2)
  | Bool
otherwise                    = CharClass -> Regex
RChar CharClass
c1 Regex -> Regex -> Regex
`RAlt` CharClass -> Regex
RChar CharClass
c2
cMinus :: CharClass -> CharClass -> Regex
cMinus :: CharClass -> CharClass -> Regex
cMinus c1 :: CharClass
c1@(CMinus CharClassUnion
p1 CharClassUnion
m1) c2 :: CharClass
c2@(CMinus CharClassUnion
p2 CharClassUnion
m2)
  | CharClassUnion
p2 CharClassUnion -> CharClassUnion -> Bool
forall a. Eq a => a -> a -> Bool
== CharClassUnion
forall a. Monoid a => a
mempty                 = CharClass -> Regex
RChar CharClass
c1
  | CharClassUnion
p1 CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
`ccuMinus` CharClassUnion
m2 Either CharClass CharClassUnion
-> Either CharClass CharClassUnion -> Bool
forall a. Eq a => a -> a -> Bool
== CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right CharClassUnion
p1 = CharClass -> Regex
RChar (CharClass -> Regex) -> CharClass -> Regex
forall a b. (a -> b) -> a -> b
$ (CharClass -> CharClass)
-> (CharClassUnion -> CharClass)
-> Either CharClass CharClassUnion
-> CharClass
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either CharClass -> CharClass
forall a. a -> a
id CharClassUnion -> CharClass
CC (Either CharClass CharClassUnion -> CharClass)
-> Either CharClass CharClassUnion -> CharClass
forall a b. (a -> b) -> a -> b
$ CharClassUnion
p1 CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
`ccuMinus` (CharClassUnion
m1 CharClassUnion -> CharClassUnion -> CharClassUnion
forall a. Semigroup a => a -> a -> a
<> CharClassUnion
p2)
  | Bool
otherwise                    = CharClass -> Regex
RChar CharClass
c1 Regex -> Regex -> Regex
`RMinus` CharClass -> Regex
RChar CharClass
c2
cChar :: Char -> CharClass
cChar :: Char -> CharClass
cChar Char
c = CharClassUnion -> CharClass
CC (CharClassUnion -> CharClass) -> CharClassUnion -> CharClass
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> CharClassUnion
CAlt [Char -> CharClassAtom
CChar Char
c]
cAlts :: [Char] -> CharClass
cAlts :: String -> CharClass
cAlts String
cs = CharClassUnion -> CharClass
CC (CharClassUnion -> CharClass) -> CharClassUnion -> CharClass
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> CharClassUnion
CAlt ([CharClassAtom] -> CharClassUnion)
-> [CharClassAtom] -> CharClassUnion
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> [CharClassAtom]
forall a. Ord a => [a] -> [a]
nubOrd ([CharClassAtom] -> [CharClassAtom])
-> [CharClassAtom] -> [CharClassAtom]
forall a b. (a -> b) -> a -> b
$ (Char -> CharClassAtom) -> String -> [CharClassAtom]
forall a b. (a -> b) -> [a] -> [b]
map Char -> CharClassAtom
CChar String
cs
cDigit, cLower, cUpper, cLetter, cAny :: CharClass
cDigit :: CharClass
cDigit  = CharClassAtom -> CharClass
cAtom CharClassAtom
CDigit
cLower :: CharClass
cLower  = CharClassAtom -> CharClass
cAtom CharClassAtom
CLower
cUpper :: CharClass
cUpper  = CharClassAtom -> CharClass
cAtom CharClassAtom
CUpper
cLetter :: CharClass
cLetter = CharClassUnion -> CharClass
CC (CharClassUnion -> CharClass) -> CharClassUnion -> CharClass
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> CharClassUnion
CAlt [ CharClassAtom
CLower, CharClassAtom
CUpper ]
cAny :: CharClass
cAny    = CharClassUnion -> CharClass
CC CharClassUnion
CAny
cAtom :: CharClassAtom -> CharClass
cAtom :: CharClassAtom -> CharClass
cAtom = CharClassUnion -> CharClass
CC (CharClassUnion -> CharClass)
-> (CharClassAtom -> CharClassUnion) -> CharClassAtom -> CharClass
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CharClassAtom] -> CharClassUnion
CAlt ([CharClassAtom] -> CharClassUnion)
-> (CharClassAtom -> [CharClassAtom])
-> CharClassAtom
-> CharClassUnion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharClassAtom -> [CharClassAtom]
forall el coll. Singleton el coll => el -> coll
singleton
ccuMinus :: CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
ccuMinus :: CharClassUnion -> CharClassUnion -> Either CharClass CharClassUnion
ccuMinus = ((CharClassUnion, CharClassUnion)
 -> Either CharClass CharClassUnion)
-> CharClassUnion
-> CharClassUnion
-> Either CharClass CharClassUnion
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (((CharClassUnion, CharClassUnion)
  -> Either CharClass CharClassUnion)
 -> CharClassUnion
 -> CharClassUnion
 -> Either CharClass CharClassUnion)
-> ((CharClassUnion, CharClassUnion)
    -> Either CharClass CharClassUnion)
-> CharClassUnion
-> CharClassUnion
-> Either CharClass CharClassUnion
forall a b. (a -> b) -> a -> b
$ \case
  (CharClassUnion
_      , CharClassUnion
CAny)   -> CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right CharClassUnion
forall a. Monoid a => a
mempty
  (c1 :: CharClassUnion
c1@CharClassUnion
CAny, CharClassUnion
c2  )
    | CharClassUnion
c2 CharClassUnion -> CharClassUnion -> Bool
forall a. Eq a => a -> a -> Bool
== CharClassUnion
forall a. Monoid a => a
mempty  -> CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right CharClassUnion
c1
    | Bool
otherwise     -> CharClass -> Either CharClass CharClassUnion
forall a b. a -> Either a b
Left  (CharClass -> Either CharClass CharClassUnion)
-> CharClass -> Either CharClass CharClassUnion
forall a b. (a -> b) -> a -> b
$ CharClassUnion
c1 CharClassUnion -> CharClassUnion -> CharClass
`CMinus` CharClassUnion
c2
  (CAlt [CharClassAtom]
cs1, CAlt [CharClassAtom]
cs2)
    | [CharClassAtom] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CharClassAtom]
cs1' Bool -> Bool -> Bool
||
      [CharClassAtom] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CharClassAtom]
cs2' -> CharClassUnion -> Either CharClass CharClassUnion
forall a b. b -> Either a b
Right (CharClassUnion -> Either CharClass CharClassUnion)
-> CharClassUnion -> Either CharClass CharClassUnion
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> CharClassUnion
CAlt [CharClassAtom]
cs1'
    | Bool
otherwise -> CharClass -> Either CharClass CharClassUnion
forall a b. a -> Either a b
Left  (CharClass -> Either CharClass CharClassUnion)
-> CharClass -> Either CharClass CharClassUnion
forall a b. (a -> b) -> a -> b
$ [CharClassAtom] -> CharClassUnion
CAlt [CharClassAtom]
cs1' CharClassUnion -> CharClassUnion -> CharClass
`CMinus` [CharClassAtom] -> CharClassUnion
CAlt [CharClassAtom]
cs2'
    where
    cs1' :: [CharClassAtom]
cs1' = [CharClassAtom]
cs1 [CharClassAtom] -> [CharClassAtom] -> [CharClassAtom]
forall a. Eq a => [a] -> [a] -> [a]
List.\\ [CharClassAtom]
cs2
    cs2' :: [CharClassAtom]
cs2' = [CharClassAtom]
cs2 [CharClassAtom] -> [CharClassAtom] -> [CharClassAtom]
forall a. Eq a => [a] -> [a] -> [a]
List.\\ [CharClassAtom]
cs1
onlyOneChar :: CharClassUnion -> Bool
onlyOneChar :: CharClassUnion -> Bool
onlyOneChar CharClassUnion
CAny         = Bool
True
onlyOneChar (CAlt [CharClassAtom]
atoms) = [CharClassAtom] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CharClassAtom]
atoms Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
isEmpty :: CharClassUnion -> Bool
isEmpty :: CharClassUnion -> Bool
isEmpty CharClassUnion
CAny         = Bool
False
isEmpty (CAlt [CharClassAtom]
atoms) = [CharClassAtom] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CharClassAtom]
atoms