module Language.Lexer.Tlex.Syntax (
    Scanner (..),
    ScanRule (..),
    ScannerBuilder,
    ScannerBuilderContext,
    buildScanner,
    lexRule,
    Pattern.Pattern,
    Pattern.enumsP,
    Pattern.straightEnumSetP,
    anyoneP,
    maybeP,
    someP,
    manyP,
    orP,
    Pattern.StartState,
    Pattern.Accept (..),
    Pattern.AcceptPriority,
) where

import           Language.Lexer.Tlex.Prelude

import qualified Language.Lexer.Tlex.Data.SymEnumSet as SymEnumSet
import qualified Language.Lexer.Tlex.Machine.Pattern as Pattern


newtype Scanner e a = Scanner
    { Scanner e a -> [ScanRule e a]
scannerRules :: [ScanRule e a]
    }
    deriving (Scanner e a -> Scanner e a -> Bool
(Scanner e a -> Scanner e a -> Bool)
-> (Scanner e a -> Scanner e a -> Bool) -> Eq (Scanner e a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e a. Eq a => Scanner e a -> Scanner e a -> Bool
/= :: Scanner e a -> Scanner e a -> Bool
$c/= :: forall e a. Eq a => Scanner e a -> Scanner e a -> Bool
== :: Scanner e a -> Scanner e a -> Bool
$c== :: forall e a. Eq a => Scanner e a -> Scanner e a -> Bool
Eq, Int -> Scanner e a -> ShowS
[Scanner e a] -> ShowS
Scanner e a -> String
(Int -> Scanner e a -> ShowS)
-> (Scanner e a -> String)
-> ([Scanner e a] -> ShowS)
-> Show (Scanner e a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e a. (Enum e, Show e, Show a) => Int -> Scanner e a -> ShowS
forall e a. (Enum e, Show e, Show a) => [Scanner e a] -> ShowS
forall e a. (Enum e, Show e, Show a) => Scanner e a -> String
showList :: [Scanner e a] -> ShowS
$cshowList :: forall e a. (Enum e, Show e, Show a) => [Scanner e a] -> ShowS
show :: Scanner e a -> String
$cshow :: forall e a. (Enum e, Show e, Show a) => Scanner e a -> String
showsPrec :: Int -> Scanner e a -> ShowS
$cshowsPrec :: forall e a. (Enum e, Show e, Show a) => Int -> Scanner e a -> ShowS
Show, a -> Scanner e b -> Scanner e a
(a -> b) -> Scanner e a -> Scanner e b
(forall a b. (a -> b) -> Scanner e a -> Scanner e b)
-> (forall a b. a -> Scanner e b -> Scanner e a)
-> Functor (Scanner e)
forall a b. a -> Scanner e b -> Scanner e a
forall a b. (a -> b) -> Scanner e a -> Scanner e b
forall e a b. a -> Scanner e b -> Scanner e a
forall e a b. (a -> b) -> Scanner e a -> Scanner e b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Scanner e b -> Scanner e a
$c<$ :: forall e a b. a -> Scanner e b -> Scanner e a
fmap :: (a -> b) -> Scanner e a -> Scanner e b
$cfmap :: forall e a b. (a -> b) -> Scanner e a -> Scanner e b
Functor)

data ScanRule e a = ScanRule
    { ScanRule e a -> [StartState]
scanRuleStartStates    :: [Pattern.StartState]
    , ScanRule e a -> Pattern e
scanRulePattern        :: Pattern.Pattern e
    , ScanRule e a -> a
scanRuleSemanticAction :: a
    }
    deriving (ScanRule e a -> ScanRule e a -> Bool
(ScanRule e a -> ScanRule e a -> Bool)
-> (ScanRule e a -> ScanRule e a -> Bool) -> Eq (ScanRule e a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall e a. Eq a => ScanRule e a -> ScanRule e a -> Bool
/= :: ScanRule e a -> ScanRule e a -> Bool
$c/= :: forall e a. Eq a => ScanRule e a -> ScanRule e a -> Bool
== :: ScanRule e a -> ScanRule e a -> Bool
$c== :: forall e a. Eq a => ScanRule e a -> ScanRule e a -> Bool
Eq, Int -> ScanRule e a -> ShowS
[ScanRule e a] -> ShowS
ScanRule e a -> String
(Int -> ScanRule e a -> ShowS)
-> (ScanRule e a -> String)
-> ([ScanRule e a] -> ShowS)
-> Show (ScanRule e a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e a.
(Enum e, Show e, Show a) =>
Int -> ScanRule e a -> ShowS
forall e a. (Enum e, Show e, Show a) => [ScanRule e a] -> ShowS
forall e a. (Enum e, Show e, Show a) => ScanRule e a -> String
showList :: [ScanRule e a] -> ShowS
$cshowList :: forall e a. (Enum e, Show e, Show a) => [ScanRule e a] -> ShowS
show :: ScanRule e a -> String
$cshow :: forall e a. (Enum e, Show e, Show a) => ScanRule e a -> String
showsPrec :: Int -> ScanRule e a -> ShowS
$cshowsPrec :: forall e a.
(Enum e, Show e, Show a) =>
Int -> ScanRule e a -> ShowS
Show, a -> ScanRule e b -> ScanRule e a
(a -> b) -> ScanRule e a -> ScanRule e b
(forall a b. (a -> b) -> ScanRule e a -> ScanRule e b)
-> (forall a b. a -> ScanRule e b -> ScanRule e a)
-> Functor (ScanRule e)
forall a b. a -> ScanRule e b -> ScanRule e a
forall a b. (a -> b) -> ScanRule e a -> ScanRule e b
forall e a b. a -> ScanRule e b -> ScanRule e a
forall e a b. (a -> b) -> ScanRule e a -> ScanRule e b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> ScanRule e b -> ScanRule e a
$c<$ :: forall e a b. a -> ScanRule e b -> ScanRule e a
fmap :: (a -> b) -> ScanRule e a -> ScanRule e b
$cfmap :: forall e a b. (a -> b) -> ScanRule e a -> ScanRule e b
Functor)


buildScanner :: Enum e => ScannerBuilder s e f () -> Scanner e f
buildScanner :: ScannerBuilder s e f () -> Scanner e f
buildScanner ScannerBuilder s e f ()
builder = Scanner :: forall e a. [ScanRule e a] -> Scanner e a
Scanner
    { $sel:scannerRules:Scanner :: [ScanRule e f]
scannerRules = ScannerBuilderContext s e f -> [ScanRule e f]
forall k (s :: k) e f.
ScannerBuilderContext s e f -> [ScanRule e f]
unScannerBuilderContext
        do ScannerBuilder s e f ()
-> ScannerBuilderContext s e f -> ScannerBuilderContext s e f
forall s a. State s a -> s -> s
execState ScannerBuilder s e f ()
builder do [ScanRule e f] -> ScannerBuilderContext s e f
forall k (s :: k) e f.
[ScanRule e f] -> ScannerBuilderContext s e f
ScannerBuilderContext []
    }

newtype ScannerBuilderContext s e f = ScannerBuilderContext
    { ScannerBuilderContext s e f -> [ScanRule e f]
unScannerBuilderContext :: [ScanRule e f]
    }
    deriving (ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
(ScannerBuilderContext s e f
 -> ScannerBuilderContext s e f -> Bool)
-> (ScannerBuilderContext s e f
    -> ScannerBuilderContext s e f -> Bool)
-> Eq (ScannerBuilderContext s e f)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (s :: k) e f.
Eq f =>
ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
/= :: ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
$c/= :: forall k (s :: k) e f.
Eq f =>
ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
== :: ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
$c== :: forall k (s :: k) e f.
Eq f =>
ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
Eq, Int -> ScannerBuilderContext s e f -> ShowS
[ScannerBuilderContext s e f] -> ShowS
ScannerBuilderContext s e f -> String
(Int -> ScannerBuilderContext s e f -> ShowS)
-> (ScannerBuilderContext s e f -> String)
-> ([ScannerBuilderContext s e f] -> ShowS)
-> Show (ScannerBuilderContext s e f)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
Int -> ScannerBuilderContext s e f -> ShowS
forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
[ScannerBuilderContext s e f] -> ShowS
forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
ScannerBuilderContext s e f -> String
showList :: [ScannerBuilderContext s e f] -> ShowS
$cshowList :: forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
[ScannerBuilderContext s e f] -> ShowS
show :: ScannerBuilderContext s e f -> String
$cshow :: forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
ScannerBuilderContext s e f -> String
showsPrec :: Int -> ScannerBuilderContext s e f -> ShowS
$cshowsPrec :: forall k (s :: k) e f.
(Enum e, Show e, Show f) =>
Int -> ScannerBuilderContext s e f -> ShowS
Show, a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a
(a -> b)
-> ScannerBuilderContext s e a -> ScannerBuilderContext s e b
(forall a b.
 (a -> b)
 -> ScannerBuilderContext s e a -> ScannerBuilderContext s e b)
-> (forall a b.
    a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a)
-> Functor (ScannerBuilderContext s e)
forall k (s :: k) e a b.
a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a
forall k (s :: k) e a b.
(a -> b)
-> ScannerBuilderContext s e a -> ScannerBuilderContext s e b
forall a b.
a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a
forall a b.
(a -> b)
-> ScannerBuilderContext s e a -> ScannerBuilderContext s e b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a
$c<$ :: forall k (s :: k) e a b.
a -> ScannerBuilderContext s e b -> ScannerBuilderContext s e a
fmap :: (a -> b)
-> ScannerBuilderContext s e a -> ScannerBuilderContext s e b
$cfmap :: forall k (s :: k) e a b.
(a -> b)
-> ScannerBuilderContext s e a -> ScannerBuilderContext s e b
Functor)

type ScannerBuilder s e f = State (ScannerBuilderContext s e f)

lexRule :: Enum s => Enum e
    => [s] -> Pattern.Pattern e -> f -> ScannerBuilder s e f ()
lexRule :: [s] -> Pattern e -> f -> ScannerBuilder s e f ()
lexRule [s]
ss Pattern e
p f
act = (ScannerBuilderContext s e f -> ScannerBuilderContext s e f)
-> ScannerBuilder s e f ()
forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' \(ScannerBuilderContext [ScanRule e f]
rs0) ->
    [ScanRule e f] -> ScannerBuilderContext s e f
forall k (s :: k) e f.
[ScanRule e f] -> ScannerBuilderContext s e f
ScannerBuilderContext
        do [StartState] -> Pattern e -> f -> ScanRule e f
forall e a. [StartState] -> Pattern e -> a -> ScanRule e a
ScanRule [s -> StartState
forall s. Enum s => s -> StartState
Pattern.startStateFromEnum s
s | s
s <- [s]
ss] Pattern e
p f
actScanRule e f -> [ScanRule e f] -> [ScanRule e f]
forall a. a -> [a] -> [a]
:[ScanRule e f]
rs0


anyoneP :: Enum e => Pattern.Pattern e
anyoneP :: Pattern e
anyoneP = SymEnumSet e -> Pattern e
forall e. SymEnumSet e -> Pattern e
Pattern.Range SymEnumSet e
forall a. Enum a => SymEnumSet a
SymEnumSet.full

maybeP :: Enum e => Pattern.Pattern e -> Pattern.Pattern e
maybeP :: Pattern e -> Pattern e
maybeP Pattern e
x = [Pattern e] -> Pattern e
forall e. Enum e => [Pattern e] -> Pattern e
orP [Pattern e
x, Pattern e
forall e. Pattern e
Pattern.Epsilon]

someP :: Enum e => Pattern.Pattern e -> Pattern.Pattern e
someP :: Pattern e -> Pattern e
someP Pattern e
x = Pattern e
x Pattern e -> Pattern e -> Pattern e
forall a. Semigroup a => a -> a -> a
<> Pattern e -> Pattern e
forall e. Pattern e -> Pattern e
Pattern.Many Pattern e
x

manyP :: Enum e => Pattern.Pattern e -> Pattern.Pattern e
manyP :: Pattern e -> Pattern e
manyP Pattern e
x = Pattern e -> Pattern e
forall e. Pattern e -> Pattern e
Pattern.Many Pattern e
x

{-# INLINE orP #-}
orP :: Enum e => [Pattern.Pattern e] -> Pattern.Pattern e
orP :: [Pattern e] -> Pattern e
orP = \case
  []   -> Pattern e
forall e. Pattern e
Pattern.Epsilon
  Pattern e
p:[Pattern e]
ps -> (Pattern e -> Pattern e -> Pattern e)
-> Pattern e -> [Pattern e] -> Pattern e
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Pattern e -> Pattern e -> Pattern e
forall e. Pattern e -> Pattern e -> Pattern e
(Pattern.:|:) Pattern e
p [Pattern e]
ps