diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.1.0.0 -- 2021-01-XX
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,5 @@
+Apache-2.0 OR MPL-2.0
+
+---
+
+See https://github.com/mizunashi-mana/tlex/blob/master/LICENSE
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+See https://hackage.haskell.org/package/tlex
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import           Distribution.Extra.Doctest (defaultMainWithDoctests)
+
+main :: IO ()
+main = defaultMainWithDoctests "doctest"
diff --git a/src/Language/Lexer/Tlex/Data/Addr.hs b/src/Language/Lexer/Tlex/Data/Addr.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Lexer/Tlex/Data/Addr.hs
@@ -0,0 +1,23 @@
+module Language.Lexer.Tlex.Data.Addr (
+    addrCodeUnitsLE,
+) where
+
+import           Language.Lexer.Tlex.Prelude
+
+import qualified Data.Bits                   as Bits
+
+
+addrCodeUnitsLE :: Bits.Bits a => Integral a => Int -> a -> [Word8]
+addrCodeUnitsLE us n
+    | n >= 0    = take us
+        do map
+            do \m -> fromInteger do fromIntegral do mod8bit m
+            do iterate (`Bits.shiftR` 8) n
+    | n == -1   = replicate us 0xFF
+    | otherwise = error "unsupported"
+    where
+        mod8bit = case Bits.bitSizeMaybe n of
+            Nothing -> \x -> x `mod` 256
+            Just bs
+                | bs <= 8   -> \x -> x
+                | otherwise -> \x -> x `mod` 256
diff --git a/src/Language/Lexer/Tlex/Data/Bits.hs b/src/Language/Lexer/Tlex/Data/Bits.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Lexer/Tlex/Data/Bits.hs
@@ -0,0 +1,17 @@
+module Language.Lexer.Tlex.Data.Bits (
+    maxBitSize,
+) where
+
+import           Language.Lexer.Tlex.Prelude
+
+import qualified Data.Bits                   as Bits
+
+
+maxBitSize :: Bits.FiniteBits a => Ord a => Num a => a -> Int
+maxBitSize n = go 1 2 where
+    go i m
+        | n < m                     = i
+        | i >= Bits.finiteBitSize n = i
+        | otherwise                 = go
+            do i + 1
+            do m * 2
diff --git a/src/Language/Lexer/Tlex/Data/TypeableTH.hs b/src/Language/Lexer/Tlex/Data/TypeableTH.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Lexer/Tlex/Data/TypeableTH.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Language.Lexer.Tlex.Data.TypeableTH (
+    liftTypeFromTypeable,
+    tyConToType,
+) where
+
+import           Prelude
+
+import           Data.Foldable       (foldl')
+import qualified Data.Typeable       as Typeable
+import qualified Language.Haskell.TH as TH
+
+liftTypeFromTypeable :: Typeable.Typeable a => Typeable.Proxy a -> TH.Q TH.Type
+liftTypeFromTypeable p = go do Typeable.typeRep p where
+    go r0 =
+        let (tyCon, rs) = Typeable.splitTyConApp r0
+        in foldl'
+            do \tq1 tq2 -> [t|$(tq1) $(tq2)|]
+            do tyConToType tyCon
+            do [ go r | r <- rs ]
+
+-- |
+--
+-- TODO: correct reifying
+-- NOTICE: introduce @reifyType@ by GHC 8.10
+--
+tyConToType :: Typeable.TyCon -> TH.Q TH.Type
+tyConToType tyCon = do
+    mn <- TH.lookupTypeName tyConQualifiedName
+    case mn of
+        Just n  -> pure do TH.ConT n
+        Nothing -> case tyConQualifiedName of
+            "GHC.Tuple.()" ->
+                pure do TH.TupleT 0
+            _  ->
+                fail do "Missing type: " ++ tyConQualifiedName
+    where
+        tyConQualifiedName = Typeable.tyConModule tyCon ++ "." ++ Typeable.tyConName tyCon
diff --git a/src/Language/Lexer/Tlex/Output/TH.hs b/src/Language/Lexer/Tlex/Output/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Lexer/Tlex/Output/TH.hs
@@ -0,0 +1,300 @@
+{-# LANGUAGE MagicHash       #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Language.Lexer.Tlex.Output.TH (
+    TlexContext (..),
+    TlexResult (..),
+    Runner (..),
+    runRunner,
+    TlexTransStateSize (..),
+    tlexLookupTlexTransTable,
+    TlexArray,
+    tlexArray,
+    tlexArrayIndex,
+    OutputContext (..),
+    outputDfa,
+) where
+
+import           Language.Lexer.Tlex.Prelude
+
+import qualified Data.Array                        as Array
+import qualified Data.Bits                         as Bits
+import qualified Data.IntMap.Strict                as IntMap
+import qualified GHC.Prim                          as Prim
+import qualified GHC.ST                            as ST
+import qualified GHC.Types                         as Types
+import qualified Language.Haskell.TH               as TH
+import qualified Language.Haskell.TH.Syntax        as TH
+import qualified Language.Lexer.Tlex.Data.Addr     as Addr
+import qualified Language.Lexer.Tlex.Data.Bits     as Bits
+import qualified Language.Lexer.Tlex.Data.EnumMap  as EnumMap
+import qualified Language.Lexer.Tlex.Machine.DFA   as DFA
+import qualified Language.Lexer.Tlex.Machine.State as MState
+import           Language.Lexer.Tlex.Runner
+import qualified Language.Lexer.Tlex.Syntax        as Tlex
+
+
+data TlexTransStateSize
+    = TlexTransStateSize8
+    | TlexTransStateSize16
+    | TlexTransStateSize32
+    deriving (Eq, Show, Enum, TH.Lift)
+
+{-# INLINE tlexLookupTlexTransTable #-}
+tlexLookupTlexTransTable :: Int -> TlexTransStateSize -> Prim.Addr#
+    -> Int -> Int -> Int
+tlexLookupTlexTransTable offset unitSize table# s c =
+    let !(Types.I# i#) = s `Bits.shiftL` offset + c
+    in ST.runST
+        do ST.ST \s0# ->
+            let !(# s1#, r# #) = case unitSize of
+                    TlexTransStateSize8  -> Prim.readInt8OffAddr#  table# i# s0#
+                    TlexTransStateSize16 -> Prim.readInt16OffAddr# table# i# s0#
+                    TlexTransStateSize32 -> Prim.readInt32OffAddr# table# i# s0#
+            in (# s1#, Types.I# r# #)
+
+type TlexArray = Array.Array Int
+
+{-# INLINE tlexArray #-}
+tlexArray :: Int -> [a] -> TlexArray a
+tlexArray l xs = Array.listArray (0,l) xs
+
+{-# INLINE tlexArrayIndex #-}
+tlexArrayIndex :: TlexArray a -> Int -> a
+tlexArrayIndex arr i = arr Array.! i
+
+{-
+type TlexStartState = ...
+type TlexSemanticAction = ...
+type TlexCodeUnit = ...
+
+tlexScan :: TlexContext s TlexCodeUnit m => TlexStartState -> m (TlexResult s TlexSemanticAction)
+tlexScan s0 = runRunner runner s0
+    where
+        runner = Runner
+            { tlexInitial = thTlexInitial
+            , tlexAccept = thTlexAccept
+            , tlexTrans = thTlexTrans
+            }
+
+thTlexInitial :: Int -> Int
+thTlexInitial = \x -> tlexArrayIndex tlexInitialTable x
+    where
+        table :: TlexArray Int
+        table = tlexArray 10 [10,...]
+
+thTlexTrans :: Int -> Int -> Int
+thTlexTrans = \s c -> tlexLookupTlexTransTable
+    8
+    TlexTransTableStateSize8
+    "\x02\x00\x00\x00..."#
+    s (c - 0)
+
+thTlexAccept :: Int -> Maybe TlexSemanticAction
+thTlexAccept = \x -> if x >= 120
+        then Nothing
+        else tlexArrayIndex table x
+    where
+        table :: TlexArray (Maybe TlexSemanticAction)
+        table = tlexArray 120 [Nothing,...]
+-}
+data OutputContext = OutputContext
+    { outputCtxStartStateTy     :: TH.Type
+    , outputCtxCodeUnitTy       :: TH.Type
+    , outputCtxCodeUnitBounds   :: (Int, Int)
+    , outputCtxSemanticActionTy :: TH.Type
+    }
+    deriving (Eq, Show)
+
+outputDfa :: OutputContext -> DFA.DFA (TH.Q TH.Exp) -> TH.Q [TH.Dec]
+outputDfa ctx dfa = do
+    let startStateTyName = TH.mkName "TlexStartState"
+        codeUnitTyName = TH.mkName "TlexCodeUnit"
+        semanticActionTyName = TH.mkName "TlexSemanticAction"
+        tlexScanFnName = TH.mkName "tlexScan"
+        thTlexInitialFnName = TH.mkName "thTlexInitial"
+        thTlexTransFnName = TH.mkName "thTlexTrans"
+        thTlexAcceptFnName = TH.mkName "thTlexAccept"
+
+    let startStateTy = pure @TH.Q do TH.ConT startStateTyName
+        codeUnitTy = pure @TH.Q do TH.ConT codeUnitTyName
+        semanticActionTy = pure @TH.Q do TH.ConT semanticActionTyName
+        thTlexInitialFn = pure @TH.Q do TH.VarE thTlexInitialFnName
+        thTlexTransFn = pure @TH.Q do TH.VarE thTlexTransFnName
+        thTlexAcceptFn = pure @TH.Q do TH.VarE thTlexAcceptFnName
+
+    sequence
+        [ pure do TH.TySynD startStateTyName [] do outputCtxStartStateTy ctx
+        , pure do TH.TySynD codeUnitTyName [] do outputCtxCodeUnitTy ctx
+        , pure do TH.TySynD semanticActionTyName [] do outputCtxSemanticActionTy ctx
+
+        , TH.SigD tlexScanFnName <$> [t|
+            forall s m. TlexContext s $(codeUnitTy) m
+                => $(startStateTy) -> m (TlexResult s $(semanticActionTy))
+        |]
+        , TH.ValD
+            do TH.VarP tlexScanFnName
+            <$> do TH.NormalB <$> [e|\s0 -> runRunner runner s0|]
+            <*> [d|
+                runner = Runner
+                    $(thTlexInitialFn)
+                    $(thTlexAcceptFn)
+                    $(thTlexTransFn)
+            |]
+
+        , TH.SigD thTlexInitialFnName <$>
+            [t|Int -> Int|]
+        , outputTlexInitialFn dfa thTlexInitialFnName
+
+        , TH.SigD thTlexTransFnName <$>
+            [t|Int -> Int -> Int|]
+        , outputTlexTransFn dfa
+            do outputCtxCodeUnitBounds ctx
+            thTlexTransFnName
+
+        , TH.SigD thTlexAcceptFnName <$>
+            [t|Int -> Maybe $(semanticActionTy)|]
+        , outputTlexAcceptFn dfa semanticActionTy thTlexAcceptFnName
+        ]
+
+outputTlexInitialFn :: DFA.DFA a -> TH.Name -> TH.Q TH.Dec
+outputTlexInitialFn DFA.DFA{ dfaInitials } fnName = do
+    tableValName <- TH.newName "table"
+    TH.ValD
+        do TH.VarP fnName
+        <$> do TH.NormalB <$>
+                [e|\x -> tlexArrayIndex $(pure do TH.VarE tableValName) x|]
+        <*> sequence
+                [ TH.SigD tableValName <$>
+                    [t|TlexArray Int|]
+                , tableDec tableValName
+                ]
+    where
+        tableDec :: TH.Name -> TH.Q TH.Dec
+        tableDec valName = TH.ValD
+            do TH.VarP valName
+            <$> do TH.NormalB <$> do
+                    (es, l) <- tableList
+                    outputTlexArrayLit l es
+            <*> pure []
+
+        tableList :: TH.Q ([TH.Exp], Int)
+        tableList =
+            let (es, l) = sequentialListFromAscList
+                    [e|-1|]
+                    [ (fromEnum ss, TH.lift do fromEnum sn)
+                    | (ss, sn) <- EnumMap.toAscList dfaInitials
+                    ]
+            in do
+                es' <- sequence es
+                pure (es', l)
+
+outputTlexTransFn :: DFA.DFA a -> (Int, Int) -> TH.Name -> TH.Q TH.Dec
+outputTlexTransFn DFA.DFA{ dfaTrans } (minUnitB, maxUnitB) fnName =
+    let ubs = Bits.maxBitSize do maxUnitB - minUnitB
+        um =
+            do 1 `Bits.shiftL` ubs
+            - 1
+        l = concatMap
+            do \dstState ->
+                let smDef = case DFA.dstOtherTrans dstState of
+                        Nothing -> -1
+                        Just sm -> fromEnum sm
+                    dstTrans = DFA.dstTrans dstState
+                in map
+                    do \i -> case IntMap.lookup i dstTrans of
+                        Just sm -> fromEnum sm
+                        Nothing -> smDef
+                    [0..um]
+            do toList dfaTrans
+        sbs = Bits.maxBitSize do length dfaTrans - 1
+        sbsEnum = if
+            | ubs + sbs > 29 -> error "exceed over bit size limited"
+            | otherwise      -> stateSize sbs
+    in TH.ValD
+        do TH.VarP fnName
+        <$> do TH.NormalB <$>
+                [e|\s c -> tlexLookupTlexTransTable
+                    $(unitBitSizeExp ubs)
+                    $(TH.lift sbsEnum)
+                    $(tableAddrExp sbsEnum l)
+                    s (c - $(TH.lift minUnitB))
+                |]
+        <*> pure []
+    where
+        unitBitSizeExp ubs = pure
+            do TH.LitE do TH.IntegerL do fromIntegral ubs
+
+        stateSize sbs
+            | sbs <= 8  = TlexTransStateSize8
+            | sbs <= 16 = TlexTransStateSize16
+            | otherwise = TlexTransStateSize32
+
+        tableAddrExp ss l =
+            let us = case ss of
+                    TlexTransStateSize8  -> 1
+                    TlexTransStateSize16 -> 2
+                    TlexTransStateSize32 -> 4
+            in pure
+                do TH.LitE
+                    do TH.StringPrimL
+                        do concatMap
+                            do \sn -> Addr.addrCodeUnitsLE us
+                                do fromEnum sn
+                            do l
+
+outputTlexAcceptFn
+    :: DFA.DFA (TH.Q TH.Exp) -> (TH.Q TH.Type) -> TH.Name -> TH.Q TH.Dec
+outputTlexAcceptFn DFA.DFA{ dfaTrans } semanticActionTy fnName = do
+    tableValName <- TH.newName "table"
+    (es, l) <- tableList
+    TH.ValD
+        do TH.VarP fnName
+        <$> do TH.NormalB <$>
+                [e|
+                    \x -> if x >= $(TH.lift l)
+                        then Nothing
+                        else tlexArrayIndex $(pure do TH.VarE tableValName) x
+                |]
+        <*> sequence
+                [ TH.SigD tableValName <$>
+                    [t|TlexArray (Maybe $(semanticActionTy))|]
+                , tableDec tableValName es l
+                ]
+    where
+        tableDec valName es l = TH.ValD
+            do TH.VarP valName
+            <$> do TH.NormalB <$> outputTlexArrayLit l es
+            <*> pure []
+
+        tableList :: TH.Q ([TH.Exp], Int)
+        tableList =
+            let (es, l) = sequentialListFromAscList
+                    [e|Nothing|]
+                    do
+                        (sn, dstSt) <- MState.arrayAssocs dfaTrans
+                        let accExp = case DFA.dstAccepts dstSt of
+                                []    -> [e|Nothing|]
+                                acc:_ -> [e|Just $(Tlex.accSemanticAction acc)|]
+                        pure (fromEnum sn, accExp)
+            in do
+                es' <- sequence es
+                pure (es', l)
+
+outputTlexArrayLit :: Int -> [TH.Exp] -> TH.Q TH.Exp
+outputTlexArrayLit l es =
+    [e|tlexArray $(TH.lift l) $(pure do TH.ListE es)|]
+
+sequentialListFromAscList :: a -> [(Int, a)] -> ([a], Int)
+sequentialListFromAscList v xs =
+    let (l0, m) = foldl'
+            do \(l, !pi) (i, x) -> (fillV i pi l . (x:), succ i)
+            do (id, 0)
+            do xs
+    in (l0 [], m)
+    where
+        fillV i !pi l
+            | pi == i   = l
+            | otherwise = fillV i
+                do succ pi
+                do l . (v:)
diff --git a/src/Language/Lexer/Tlex/Plugin/TH.hs b/src/Language/Lexer/Tlex/Plugin/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Lexer/Tlex/Plugin/TH.hs
@@ -0,0 +1,118 @@
+{-# LANGUAGE CPP #-}
+
+module Language.Lexer.Tlex.Plugin.TH (
+    TlexTH.TlexContext (..),
+    TlexTH.TlexResult (..),
+    TlexTH.Runner (..),
+    TlexTH.runRunner,
+    THScanner (..),
+    THScannerBuilderContext,
+    THScannerBuilder,
+    buildTHScanner,
+    buildTHScannerWithReify,
+    liftTlexScannerBuilder,
+    thLexRule,
+    outputScanner,
+) where
+
+import           Language.Lexer.Tlex.Prelude
+
+import qualified Language.Haskell.TH                      as TH
+import qualified Language.Lexer.Tlex.Data.TypeableTH      as TypeableTH
+import qualified Language.Lexer.Tlex.Machine.NFA          as NFA
+import qualified Language.Lexer.Tlex.Output.TH            as TlexTH
+import qualified Language.Lexer.Tlex.Pipeline.MinDfa      as TlexPipeline
+import qualified Language.Lexer.Tlex.Pipeline.Nfa2Dfa     as TlexPipeline
+import qualified Language.Lexer.Tlex.Pipeline.Scanner2Nfa as TlexPipeline
+import qualified Language.Lexer.Tlex.Syntax               as Tlex
+
+#ifdef DEBUG
+import qualified Debug.Trace                              as Debug
+#endif
+
+
+data THScanner e = THScanner
+    { thScannerOutputCtx   :: TlexTH.OutputContext
+    , thScannerTlexScanner :: Tlex.Scanner e (TH.Q TH.Exp)
+    }
+
+data THScannerBuilderContext s e a = THScannerBuilderContext
+    { thScannerBuilderCtxOutputCtx :: TlexTH.OutputContext
+    , thScannerBuilderCtxTlexScannerBuilderCtx :: Tlex.ScannerBuilderContext s e (TH.Q TH.Exp)
+    }
+
+type THScannerBuilder s e a = State (THScannerBuilderContext s e a)
+
+buildTHScanner :: forall e s a. Enum e => Bounded e
+    => TH.Type -> TH.Type -> TH.Type -> THScannerBuilder s e a ()
+    -> THScanner e
+buildTHScanner codeUnitTy startStateTy actionTy builder =
+    let outputCtx = TlexTH.OutputContext
+            { outputCtxStartStateTy = startStateTy
+            , outputCtxCodeUnitTy = codeUnitTy
+            , outputCtxCodeUnitBounds = (
+                fromEnum do minBound @e,
+                fromEnum do maxBound @e
+            )
+            , outputCtxSemanticActionTy = actionTy
+            }
+        tlexScanner = Tlex.buildScanner do
+            modify' \ctx0 -> thScannerBuilderCtxTlexScannerBuilderCtx
+                do execState builder do
+                    THScannerBuilderContext
+                        { thScannerBuilderCtxOutputCtx = outputCtx
+                        , thScannerBuilderCtxTlexScannerBuilderCtx = ctx0
+                        }
+    in THScanner
+        { thScannerOutputCtx = outputCtx
+        , thScannerTlexScanner = tlexScanner
+        }
+
+buildTHScannerWithReify :: forall s a e.
+    Enum e => Bounded e => Typeable e => Typeable s => Typeable a
+    => THScannerBuilder s e a () -> TH.Q (THScanner e)
+buildTHScannerWithReify builder = do
+    startStateTy <- TypeableTH.liftTypeFromTypeable do Proxy @s
+    codeUnitTy <- TypeableTH.liftTypeFromTypeable do Proxy @e
+    actionTy <- TypeableTH.liftTypeFromTypeable do Proxy @a
+    pure do buildTHScanner codeUnitTy startStateTy actionTy builder
+
+liftTlexScannerBuilder :: Enum e => Tlex.ScannerBuilder s e (TH.Q TH.Exp) a -> THScannerBuilder s e f a
+liftTlexScannerBuilder builder = do
+    ctx0 <- get
+    let (x, tlexCtx1) = runState
+            do builder
+            do thScannerBuilderCtxTlexScannerBuilderCtx ctx0
+    put do ctx0
+            { thScannerBuilderCtxTlexScannerBuilderCtx = tlexCtx1
+            }
+    pure x
+
+thLexRule :: Enum e => Enum s => [s] -> Tlex.Pattern e -> TH.Q (TH.TExp a) -> THScannerBuilder s e a ()
+thLexRule ss p act = liftTlexScannerBuilder do Tlex.lexRule ss p do TH.unType <$> act
+
+
+outputScanner :: Enum e => THScanner e -> TH.Q [TH.Dec]
+outputScanner scanner =
+    let outputCtx = thScannerOutputCtx scanner
+        nfa =
+#ifdef DEBUG
+            Debug.trace "building NFA..." do
+#endif
+            NFA.buildNFA do
+                TlexPipeline.scanner2Nfa do thScannerTlexScanner scanner
+        dfa =
+#ifdef DEBUG
+            Debug.trace "building DFA..." do
+#endif
+            TlexPipeline.nfa2Dfa nfa
+        minDfa =
+#ifdef DEBUG
+            Debug.trace "minizing DFA..." do
+#endif
+            TlexPipeline.minDfa dfa
+    in
+#ifdef DEBUG
+        Debug.trace "outputing DFA..." do
+#endif
+        TlexTH.outputDfa outputCtx minDfa
diff --git a/test/doctest/Doctest.hs b/test/doctest/Doctest.hs
new file mode 100644
--- /dev/null
+++ b/test/doctest/Doctest.hs
@@ -0,0 +1,21 @@
+module Main where
+
+import           Prelude
+
+import qualified Build_doctests     as BuildF
+import           Control.Monad
+import qualified System.Environment as IO
+import qualified System.IO          as IO
+import           Test.DocTest       (doctest)
+
+main :: IO ()
+main = forM_ BuildF.components \(BuildF.Component name flags pkgs sources) -> do
+  putStrLn "============================================="
+  print name
+  putStrLn "---------------------------------------------"
+  IO.hFlush IO.stdout
+  let args = flags ++ pkgs ++ sources
+  IO.unsetEnv "GHC_ENVIRONMENT"
+  doctest args
+  putStrLn "============================================="
+  IO.hFlush IO.stdout
diff --git a/test/spec/HSpecDriver.hs b/test/spec/HSpecDriver.hs
new file mode 100644
--- /dev/null
+++ b/test/spec/HSpecDriver.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/tlex-th.cabal b/tlex-th.cabal
new file mode 100644
--- /dev/null
+++ b/tlex-th.cabal
@@ -0,0 +1,161 @@
+cabal-version:       3.0
+build-type:          Custom
+
+name:                tlex-th
+version:             0.1.0.0
+license:             Apache-2.0 OR MPL-2.0
+license-file:        LICENSE
+copyright:           (c) 2021 Mizunashi Mana
+author:              Mizunashi Mana
+maintainer:          mizunashi-mana@noreply.git
+
+category:            Parsing
+homepage:            https://github.com/mizunashi-mana/tlex
+bug-reports:         https://github.com/mizunashi-mana/tlex/issues
+synopsis:            TemplateHaskell plugin for Tlex
+description:
+    Tlex is haskell libraries and toolchains for generating lexical analyzer.
+    See also: https://github.com/mizunashi-mana/tlex
+
+extra-source-files:
+    README.md
+    CHANGELOG.md
+
+source-repository head
+  type:     git
+  location: https://github.com/mizunashi-mana/tlex.git
+
+flag develop
+    default:     False
+    manual:      True
+    description: Turn on some options for development
+
+common general
+    default-language:
+        Haskell2010
+    default-extensions:
+        NoImplicitPrelude
+        BangPatterns
+        BinaryLiterals
+        BlockArguments
+        ConstraintKinds
+        DataKinds
+        DefaultSignatures
+        DeriveFoldable
+        DeriveFunctor
+        DeriveGeneric
+        DeriveLift
+        DeriveTraversable
+        DerivingVia
+        DuplicateRecordFields
+        EmptyCase
+        FlexibleContexts
+        FlexibleInstances
+        FunctionalDependencies
+        GADTs
+        InstanceSigs
+        LambdaCase
+        MagicHash
+        MultiParamTypeClasses
+        MultiWayIf
+        NamedFieldPuns
+        NegativeLiterals
+        NumericUnderscores
+        OverloadedLabels
+        PackageImports
+        PatternSynonyms
+        PolyKinds
+        RankNTypes
+        ScopedTypeVariables
+        StandaloneDeriving
+        Strict
+        TypeApplications
+        TypeFamilies
+        TypeOperators
+        UnboxedSums
+        UnboxedTuples
+
+    if flag(develop)
+        ghc-options:
+            -Wall
+            -Wcompat
+            -Wincomplete-uni-patterns
+            -Wmonomorphism-restriction
+            -Wpartial-fields
+
+            -fprint-explicit-foralls
+            -frefinement-level-hole-fits=1
+
+            -dcore-lint
+
+    build-depends:
+        base                 >= 4.12.0 && < 4.15,
+
+        -- project depends
+        tlex-core            >= 0.1.0 && < 0.2,
+        tlex                 >= 0.1.0 && < 0.2,
+        ghc-prim             >= 0.5.3 && < 0.7,
+        template-haskell     >= 2.14.0 && < 2.17.0,
+        array                >= 0.5.3 && < 0.6,
+        containers           >= 0.6.0 && < 0.7,
+
+    autogen-modules:
+        Paths_tlex_th
+    other-modules:
+        Paths_tlex_th
+
+custom-setup
+    setup-depends:
+        base,
+        Cabal,
+        cabal-doctest,
+
+library
+    import:
+        general,
+    hs-source-dirs:
+        src
+    exposed-modules:
+        Language.Lexer.Tlex.Plugin.TH
+        Language.Lexer.Tlex.Data.TypeableTH
+
+        -- internals
+        Language.Lexer.Tlex.Output.TH
+        Language.Lexer.Tlex.Data.Addr
+        Language.Lexer.Tlex.Data.Bits
+
+test-suite doctest
+    import:
+        general,
+    type:
+        exitcode-stdio-1.0
+    hs-source-dirs:
+        test/doctest
+    main-is:
+        Doctest.hs
+    build-depends:
+        doctest,
+        QuickCheck,
+    autogen-modules:
+        Build_doctests
+    other-modules:
+        Build_doctests
+
+test-suite spec
+    import:
+        general,
+    type:
+        exitcode-stdio-1.0
+    hs-source-dirs:
+        test/spec
+    main-is:
+        HSpecDriver.hs
+    ghc-options:
+        -Wno-missing-home-modules
+    build-tool-depends:
+        hspec-discover:hspec-discover,
+    build-depends:
+        tlex-th,
+
+        hspec,
+        QuickCheck,
