{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Regex.KDE.Regex
 ( Direction(..)
 , Regex(..)
 , isWordChar
 ) where

import Data.Char
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup ((<>), Semigroup)
#endif

data Direction = Forward | Backward
  deriving (Int -> Direction -> ShowS
[Direction] -> ShowS
Direction -> String
(Int -> Direction -> ShowS)
-> (Direction -> String)
-> ([Direction] -> ShowS)
-> Show Direction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Direction] -> ShowS
$cshowList :: [Direction] -> ShowS
show :: Direction -> String
$cshow :: Direction -> String
showsPrec :: Int -> Direction -> ShowS
$cshowsPrec :: Int -> Direction -> ShowS
Show, Direction -> Direction -> Bool
(Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool) -> Eq Direction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c== :: Direction -> Direction -> Bool
Eq)

data Regex =
  MatchAnyChar |
  MatchDynamic !Int |
  MatchChar (Char -> Bool) |
  MatchSome !Regex |
  MatchAlt !Regex !Regex |
  MatchConcat !Regex !Regex |
  MatchCapture !Int !Regex |
  MatchCaptured !Int |
  AssertWordBoundary |
  AssertBeginning |
  AssertEnd |
  AssertPositive !Direction !Regex |
  AssertNegative !Direction !Regex |
  Possessive !Regex |
  Lazy !Regex |
  Subroutine !Int |
  MatchNull

instance Show Regex where
  show :: Regex -> String
show MatchAnyChar = "MatchAnyChar"
  show (MatchDynamic i :: Int
i) = "MatchDynamic " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i
  show (MatchChar _) = "(MatchChar <fn>)"
  show (MatchSome re :: Regex
re) = "(MatchSome " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (MatchAlt r1 :: Regex
r1 r2 :: Regex
r2) = "(MatchAlt " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
r1 String -> ShowS
forall a. Semigroup a => a -> a -> a
<> " " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
r2 String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (MatchConcat r1 :: Regex
r1 r2 :: Regex
r2) = "(MatchConcat " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
r1 String -> ShowS
forall a. Semigroup a => a -> a -> a
<> " " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
r2 String -> ShowS
forall a. Semigroup a => a -> a -> a
<>
            ")"
  show (MatchCapture i :: Int
i re :: Regex
re) = "(MatchCapture " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> ShowS
forall a. Semigroup a => a -> a -> a
<> " " String -> ShowS
forall a. Semigroup a => a -> a -> a
<>
                Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (MatchCaptured n :: Int
n) = "(MatchCaptured " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show AssertWordBoundary = "AssertWordBoundary"
  show AssertBeginning = "AssertBeginning"
  show AssertEnd = "AssertEnd"
  show (AssertPositive dir :: Direction
dir re :: Regex
re) = "(AssertPositive " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Direction -> String
forall a. Show a => a -> String
show Direction
dir String -> ShowS
forall a. Semigroup a => a -> a -> a
<> " " String -> ShowS
forall a. Semigroup a => a -> a -> a
<>
                  Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (AssertNegative dir :: Direction
dir re :: Regex
re) = "(AssertNegativeLookahead " String -> ShowS
forall a. Semigroup a => a -> a -> a
<>
                  Direction -> String
forall a. Show a => a -> String
show Direction
dir String -> ShowS
forall a. Semigroup a => a -> a -> a
<> " " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (Possessive re :: Regex
re) = "(Possessive " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (Lazy re :: Regex
re) = "(Lazy " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Regex -> String
forall a. Show a => a -> String
show Regex
re String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show (Subroutine i :: Int
i) = "(Subroutine " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ")"
  show MatchNull = "MatchNull"

instance Semigroup Regex where
  <> :: Regex -> Regex -> Regex
(<>) = Regex -> Regex -> Regex
MatchConcat

instance Monoid Regex where
  mempty :: Regex
mempty = Regex
MatchNull
  mappend :: Regex -> Regex -> Regex
mappend = Regex -> Regex -> Regex
forall a. Semigroup a => a -> a -> a
(<>)

isWordChar :: Char -> Bool
isWordChar :: Char -> Bool
isWordChar c :: Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char -> GeneralCategory
generalCategory Char
c GeneralCategory -> GeneralCategory -> Bool
forall a. Eq a => a -> a -> Bool
== GeneralCategory
ConnectorPunctuation