tlex-0.4.0.1: src/Language/Lexer/Tlex/Syntax.hs
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 unit action = Scanner
{ scannerRules :: [ScanRule unit action]
}
deriving (Eq, Show, Functor)
data ScanRule unit action = ScanRule
{ scanRuleStartStates :: [Pattern.StartState]
, scanRulePattern :: Pattern.Pattern unit
, scanRuleSemanticAction :: action
}
deriving (Eq, Show, Functor)
buildScanner :: Enum unit
=> ScannerBuilder state unit action () -> Scanner unit action
buildScanner builder = Scanner
{ scannerRules = unScannerBuilderContext
do execState builder do ScannerBuilderContext []
}
newtype ScannerBuilderContext state unit action = ScannerBuilderContext
{ unScannerBuilderContext :: [ScanRule unit action]
}
deriving (Eq, Show, Functor)
type ScannerBuilder state unit action = State (ScannerBuilderContext state unit action)
lexRule :: Enum state => Enum unit
=> [state] -> Pattern.Pattern unit -> action -> ScannerBuilder state unit action ()
lexRule ss p act = modify' \(ScannerBuilderContext rs0) ->
ScannerBuilderContext
do ScanRule [Pattern.startStateFromEnum s | s <- ss] p act:rs0
-- | Wildcard pattern which accepts an any unit.
anyoneP :: Enum unit => Pattern.Pattern unit
anyoneP = Pattern.Range SymEnumSet.full
-- | Maybe pattern which accepts given pattern or nothing.
maybeP :: Enum unit => Pattern.Pattern unit -> Pattern.Pattern unit
maybeP x = orP [x, Pattern.Epsilon]
-- | Some pattern which accepts one given pattern or more times.
someP :: Enum unit => Pattern.Pattern unit -> Pattern.Pattern unit
someP x = x <> Pattern.Many x
-- | Many pattern which accepts nothing or given pattern more times.
manyP :: Enum unit => Pattern.Pattern unit -> Pattern.Pattern unit
manyP x = Pattern.Many x
-- | Or pattern which accepts one of given patterns.
orP :: Enum unit => [Pattern.Pattern unit] -> Pattern.Pattern unit
orP = \case
[] -> Pattern.Epsilon
p:ps -> foldr (Pattern.:|:) p ps
{-# INLINE orP #-}