{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module GHC.TypeLits.Printf.Internal.Parser where
import Data.Kind
import Data.Type.Bool
import Data.Type.Equality
import GHC.TypeLits
type SChar = Symbol
type Parser a = a -> Type
type family RunParser (p :: Parser a) (str :: [SChar]) :: Maybe (a, [SChar])
data Pure :: a -> Parser a
type instance RunParser (Pure x) str = 'Just '(x, str)
data Sym :: SChar -> Parser SChar
type instance RunParser (Sym c) (d ': cs) = If (c == d) ('Just '(c, cs)) 'Nothing
type instance RunParser (Sym c) '[] = 'Nothing
data NotSym :: SChar -> Parser SChar
type instance RunParser (NotSym c) (d ': cs) = If (c == d) 'Nothing ('Just '(c, cs))
type instance RunParser (NotSym c) '[] = 'Nothing
data AnySym :: Parser SChar
type instance RunParser AnySym (c ': cs) = 'Just '(c, cs)
type instance RunParser AnySym '[] = 'Nothing
data Alpha :: Parser SChar
type instance RunParser Alpha (c ': cs) = If (IsAlpha c) ('Just '(c, cs)) 'Nothing
type instance RunParser Alpha '[] = 'Nothing
data (<$) :: b -> Parser a -> Parser b
type family RepHelp (x :: b) (r :: Maybe (a, [SChar])) :: Maybe (b, [SChar]) where
RepHelp x 'Nothing = 'Nothing
RepHelp x ('Just '(y, s)) = 'Just '(x, s)
type instance RunParser (x <$ p) str = RepHelp x (RunParser p str)
data (<|>) :: Parser a -> Parser a -> Parser a
type family ChoiceMaybe (x :: Maybe a) (y :: Maybe a) :: Maybe a where
ChoiceMaybe ('Just x) y = 'Just x
ChoiceMaybe 'Nothing y = y
type instance RunParser (x <|> y) str = ChoiceMaybe (RunParser x str) (RunParser y str)
type Optional p = ('Just <$> p) <|> Pure 'Nothing
data (*>) :: Parser a -> Parser b -> Parser b
type family SeqHelp (p :: Parser b) (r :: Maybe (a, [SChar])) :: Maybe (b, [SChar]) where
SeqHelp p 'Nothing = 'Nothing
SeqHelp p ('Just '(x, str)) = RunParser p str
type instance RunParser (x *> y) str = SeqHelp y (RunParser x str)
data Digit :: Parser Nat
type family DigitHelp (d :: Maybe Nat) (cs :: [SChar]) :: Maybe (Nat, [SChar]) where
DigitHelp 'Nothing cs = 'Nothing
DigitHelp ('Just d) cs = 'Just '(d, cs)
type instance RunParser Digit '[] = 'Nothing
type instance RunParser Digit (c ': cs) = DigitHelp (CharDigit c) cs
data (<$>) :: (a -> b) -> Parser a -> Parser b
type family MapConHelp (f :: a -> b) (r :: Maybe (a, [SChar])) :: Maybe (b, [SChar]) where
MapConHelp f 'Nothing = 'Nothing
MapConHelp f ('Just '(x, str)) = 'Just '(f x, str)
type instance RunParser (f <$> p) str = MapConHelp f (RunParser p str)
data (<*>) :: Parser (a -> b) -> Parser a -> Parser b
type family ApHelp (r :: Maybe (a -> b, [SChar])) (q :: Parser a) :: Maybe (b, [SChar]) where
ApHelp 'Nothing q = 'Nothing
ApHelp ('Just '(f, str)) q = RunParser (f <$> q) str
type instance RunParser (p <*> q) str = ApHelp (RunParser p str) q
data Many :: Parser a -> Parser [a]
type instance RunParser (Many p) str = RunParser (Some p <|> Pure '[]) str
data Some :: Parser a -> Parser [a]
type instance RunParser (Some p) str = RunParser ('(:) <$> p <*> Many p) str
data Number :: Parser Nat
type family NumberHelp (xs :: Maybe ([Nat], [SChar])) :: Maybe (Nat, [SChar]) where
NumberHelp 'Nothing = 'Nothing
NumberHelp ('Just '(ns, str)) = 'Just '(FromDigits ns 0, str)
type instance RunParser Number str = NumberHelp (RunParser (Some Digit) str)
data Cat :: Parser [SChar] -> Parser Symbol
type family CatHelp (xs :: Maybe ([SChar], [SChar])) :: Maybe (Symbol, [SChar]) where
CatHelp 'Nothing = 'Nothing
CatHelp ('Just '(cs, str)) = 'Just '(CatChars cs, str)
type instance RunParser (Cat p) str = CatHelp (RunParser p str)
type family EvalHelp (r :: Maybe (a, [SChar])) :: Maybe a where
EvalHelp 'Nothing = 'Nothing
EvalHelp ('Just '(x, str)) = 'Just x
type EvalParser (p :: Parser a) str = EvalHelp (RunParser p str) :: Maybe a
type family EvalHelp_ (r :: Maybe (a, [SChar])) :: a where
EvalHelp_ ('Just '(x, str)) = x
EvalHelp_ 'Nothing = TypeError ('Text "Parse failed")
type EvalParser_ (p :: Parser a) str = EvalHelp_ (RunParser p str) :: a
type family CharDigit (c :: SChar) :: Maybe Nat where
CharDigit "0" = 'Just 0
CharDigit "1" = 'Just 1
CharDigit "2" = 'Just 2
CharDigit "3" = 'Just 3
CharDigit "4" = 'Just 4
CharDigit "5" = 'Just 5
CharDigit "6" = 'Just 6
CharDigit "7" = 'Just 7
CharDigit "8" = 'Just 8
CharDigit "9" = 'Just 9
CharDigit c = 'Nothing
type family FromDigits (xs :: [Nat]) (n :: Nat) :: Nat where
FromDigits '[] n = n
FromDigits (a ': bs) n = FromDigits bs (n * 10 + a)
type family CatChars (cs :: [SChar]) :: Symbol where
CatChars '[] = ""
CatChars (c ': cs) = AppendSymbol c (CatChars cs)
type family IsAlpha (c :: SChar) :: Bool where
IsAlpha "a" = 'True
IsAlpha "b" = 'True
IsAlpha "c" = 'True
IsAlpha "d" = 'True
IsAlpha "e" = 'True
IsAlpha "f" = 'True
IsAlpha "g" = 'True
IsAlpha "h" = 'True
IsAlpha "i" = 'True
IsAlpha "j" = 'True
IsAlpha "k" = 'True
IsAlpha "l" = 'True
IsAlpha "m" = 'True
IsAlpha "n" = 'True
IsAlpha "o" = 'True
IsAlpha "p" = 'True
IsAlpha "q" = 'True
IsAlpha "r" = 'True
IsAlpha "s" = 'True
IsAlpha "t" = 'True
IsAlpha "u" = 'True
IsAlpha "v" = 'True
IsAlpha "w" = 'True
IsAlpha "x" = 'True
IsAlpha "y" = 'True
IsAlpha "z" = 'True
IsAlpha "A" = 'True
IsAlpha "B" = 'True
IsAlpha "C" = 'True
IsAlpha "D" = 'True
IsAlpha "E" = 'True
IsAlpha "F" = 'True
IsAlpha "G" = 'True
IsAlpha "H" = 'True
IsAlpha "I" = 'True
IsAlpha "J" = 'True
IsAlpha "K" = 'True
IsAlpha "L" = 'True
IsAlpha "M" = 'True
IsAlpha "N" = 'True
IsAlpha "O" = 'True
IsAlpha "P" = 'True
IsAlpha "Q" = 'True
IsAlpha "R" = 'True
IsAlpha "S" = 'True
IsAlpha "T" = 'True
IsAlpha "U" = 'True
IsAlpha "V" = 'True
IsAlpha "W" = 'True
IsAlpha "X" = 'True
IsAlpha "Y" = 'True
IsAlpha "Z" = 'True
IsAlpha a = 'False