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
    { forall e a. Scanner e a -> [ScanRule e a]
scannerRules :: [ScanRule e a]
    }
    deriving (Scanner e a -> Scanner e a -> Bool
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
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, 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
<$ :: forall a b. a -> Scanner e b -> Scanner e a
$c<$ :: forall e a b. a -> Scanner e b -> Scanner e a
fmap :: forall a b. (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
    { forall e a. ScanRule e a -> [StartState]
scanRuleStartStates    :: [Pattern.StartState]
    , forall e a. ScanRule e a -> Pattern e
scanRulePattern        :: Pattern.Pattern e
    , forall e a. ScanRule e a -> a
scanRuleSemanticAction :: a
    }
    deriving (ScanRule e a -> ScanRule e a -> Bool
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
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, 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
<$ :: forall a b. a -> ScanRule e b -> ScanRule e a
$c<$ :: forall e a b. a -> ScanRule e b -> ScanRule e a
fmap :: forall a b. (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 :: forall {k} e (s :: k) f.
Enum e =>
ScannerBuilder s e f () -> Scanner e f
buildScanner ScannerBuilder s e f ()
builder = Scanner
    { $sel:scannerRules:Scanner :: [ScanRule e f]
scannerRules = forall {k} (s :: k) e f.
ScannerBuilderContext s e f -> [ScanRule e f]
unScannerBuilderContext
        do forall s a. State s a -> s -> s
execState ScannerBuilder s e f ()
builder do forall {k} (s :: k) e f.
[ScanRule e f] -> ScannerBuilderContext s e f
ScannerBuilderContext []
    }

newtype ScannerBuilderContext s e f = ScannerBuilderContext
    { forall {k} (s :: k) e f.
ScannerBuilderContext s e f -> [ScanRule e f]
unScannerBuilderContext :: [ScanRule e f]
    }
    deriving (ScannerBuilderContext s e f -> ScannerBuilderContext s e f -> Bool
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
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, 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
<$ :: forall a b.
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 :: forall a b.
(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 :: forall s e f.
(Enum s, Enum e) =>
[s] -> Pattern e -> f -> ScannerBuilder s e f ()
lexRule [s]
ss Pattern e
p f
act = forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' \(ScannerBuilderContext [ScanRule e f]
rs0) ->
    forall {k} (s :: k) e f.
[ScanRule e f] -> ScannerBuilderContext s e f
ScannerBuilderContext
        do forall e a. [StartState] -> Pattern e -> a -> ScanRule e a
ScanRule [forall s. Enum s => s -> StartState
Pattern.startStateFromEnum s
s | s
s <- [s]
ss] Pattern e
p f
actforall a. a -> [a] -> [a]
:[ScanRule e f]
rs0


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

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

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

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

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