{-# LANGUAGE UndecidableInstances #-}

module Data.Type.Symbol.Parser.Parser.Literal ( Literal ) where

import Data.Type.Symbol.Parser.Types
import Data.Type.Symbol.Parser.Common
import GHC.TypeLits
import DeFun.Core ( type (~>), type App )

type Literal :: Symbol -> Parser (Char, Maybe (Char, Symbol)) ()
type Literal sym = Literal' (UnconsSymbol sym)

type EEmptyLit = ErrParserLimitation "cannot parse empty literal"

type family Literal' msym where
    Literal' Nothing           =
        '( FailChSym "Literal" EEmptyLit
         , FailEndSym "Literal" EEmptyLit, '( '\0', Nothing))
    Literal' (Just '(ch, sym)) =
        '(LiteralChSym, LiteralEndSym, '(ch, UnconsSymbol sym))

type family LiteralCh ch s where
    LiteralCh ch0 '(ch0, Just '(ch1, sym)) = Cont '(ch1, UnconsSymbol sym)
    LiteralCh ch0 '(ch0, Nothing)          = Done '()
    LiteralCh ch  '(ch0, msym)             = Err (EBase "Literal"
        (      Text "expected " :<>: ShowType ch0
          :<>: Text ", got " :<>: ShowType ch))

type LiteralEnd :: ParserEnd (Char, Maybe (Char, Symbol)) ()
type family LiteralEnd s where
    LiteralEnd '(ch0, msym) = Left (EBase "Literal"
      (      Text "still parsing literal: "
        :<>: Text (ConsSymbol ch0 (ReconsSymbol msym))))

type family ReconsSymbol msym where
    ReconsSymbol Nothing           = ""
    ReconsSymbol (Just '(ch, sym)) = ConsSymbol ch sym

type LiteralChSym :: ParserChSym (Char, Maybe (Char, Symbol)) ()
data LiteralChSym f
type instance App LiteralChSym f = LiteralChSym1 f

type LiteralChSym1
    :: Char
    -> (Char, Maybe (Char, Symbol))
    ~> Result (Char, Maybe (Char, Symbol)) ()
data LiteralChSym1 ch s
type instance App (LiteralChSym1 ch) s = LiteralCh ch s

type LiteralEndSym :: ParserEndSym (Char, Maybe (Char, Symbol)) ()
data LiteralEndSym s
type instance App LiteralEndSym s = LiteralEnd s