{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE NoStarIsType #-}
module GHC.TypeLits.Printf.Internal.Parser where
import Data.Kind
import Data.Type.Bool
import Data.Type.Equality
import GHC.TypeLits
type Parser a = a -> Type
type family RunParser (p :: Parser a) (uncons :: Maybe (Char, Symbol)) :: Maybe (a, Symbol)
data Pure :: a -> Parser a
type instance RunParser (Pure x) (Just '(c, cs)) = Just '(x, ConsSymbol c cs)
type instance RunParser (Pure x) Nothing = Just '(x, "")
data AsChar :: Char -> Parser Char
type instance RunParser (AsChar c) (Just '(d, cs)) = If (c == d) (Just '(c, cs)) Nothing
type instance RunParser (AsChar c) Nothing = Nothing
data NotChar :: Char -> Parser Char
type instance RunParser (NotChar c) (Just '(d, cs)) = If (c == d) Nothing (Just '(d, cs))
type instance RunParser (NotChar c) Nothing = Nothing
data AnyChar :: Parser Char
type instance RunParser AnyChar (Just '(c, cs)) = Just '(c, cs)
type instance RunParser AnyChar Nothing = Nothing
data Alpha :: Parser Char
type instance RunParser Alpha (Just '(c, cs)) = If (IsAlpha c) (Just '(c, cs)) Nothing
type instance RunParser Alpha Nothing = Nothing
data (<$) :: b -> Parser a -> Parser b
type family RepHelp (x :: b) (r :: Maybe (a, Symbol)) :: Maybe (b, Symbol) 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, Symbol)) :: Maybe (b, Symbol) where
SeqHelp p Nothing = Nothing
SeqHelp p (Just '(x, str)) = RunParser p (UnconsSymbol str)
type instance RunParser (x *> y) str = SeqHelp y (RunParser x str)
data Digit :: Parser Nat
type family DigitHelp (d :: Maybe Nat) (cs :: Symbol) :: Maybe (Nat, Symbol) where
DigitHelp Nothing cs = Nothing
DigitHelp (Just d) cs = Just '(d, cs)
type instance RunParser Digit (Just '(c, cs)) = DigitHelp (CharDigit c) cs
type instance RunParser Digit Nothing = Nothing
data (<$>) :: (a -> b) -> Parser a -> Parser b
type family MapConHelp (f :: a -> b) (r :: Maybe (a, Symbol)) :: Maybe (b, Symbol) 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, Symbol)) (q :: Parser a) :: Maybe (b, Symbol) where
ApHelp Nothing q = Nothing
ApHelp (Just '(f, str)) q = RunParser (f <$> q) (UnconsSymbol 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], Symbol)) :: Maybe (Nat, Symbol) where
NumberHelp (Just '(ns, str)) = Just '(FromDigits ns 0, str)
NumberHelp Nothing = Nothing
type instance RunParser Number str = NumberHelp (RunParser (Some Digit) str)
data Cat :: Parser [Char] -> Parser Symbol
type family CatHelp (xs :: Maybe ([Char], Symbol)) :: Maybe (Symbol, Symbol) 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, Symbol)) :: Maybe a where
EvalHelp (Just '(x, str)) = Just x
EvalHelp Nothing = Nothing
type EvalParser (p :: Parser a) (str :: Symbol) =
EvalHelp (RunParser p (UnconsSymbol str)) :: Maybe a
type family EvalHelp_ (r :: Maybe (a, Symbol)) :: a where
EvalHelp_ (Just '(x, str)) = x
EvalHelp_ Nothing = TypeError ('Text "Parse failed")
type EvalParser_ (p :: Parser a) (str :: Symbol) = EvalHelp_ (RunParser p (UnconsSymbol str)) :: a
type family CharDigit (c :: Char) :: 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 :: [Char]) :: Symbol where
CatChars '[] = ""
CatChars (c ': cs) = ConsSymbol c (CatChars cs)
type family IsAlpha (c :: Char) :: 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