{-# LANGUAGE UndecidableInstances #-}
module Symparsec.Parser.Natural
( type NatBase, type NatBase1
, type NatDec
, type NatHex
, type NatBin
, type NatOct
, type NatBaseWhile
) where
import Symparsec.Parser.Common
import Symparsec.Parser.Natural.Digits
type NatBin = NatBase 2 ParseDigitBinSym
type NatOct = NatBase 8 ParseDigitOctSym
type NatDec = NatBase 10 ParseDigitDecSym
type NatHex = NatBase 16 ParseDigitHexSym
type NatBase :: Natural -> (Char ~> Maybe Natural) -> PParser Natural
data NatBase base parseDigit s
type instance App (NatBase base parseDigit) s =
NatBaseStart base parseDigit s (UnconsState s)
type family NatBaseStart base parseDigit sCh s where
NatBaseStart base parseDigit sCh '(Just ch, s) =
NatBaseLoop base parseDigit sCh s 0 ch (parseDigit @@ ch) (UnconsState s)
NatBaseStart base parseDigit sCh '(Nothing, s) = 'Reply (Err EEmpty) sCh
type NatBase1 :: Natural -> (Char ~> Maybe Natural) -> Natural -> PParser Natural
data NatBase1 base parseDigit digit s
type instance App (NatBase1 base parseDigit digit) s =
NatBase1' base parseDigit s digit (UnconsState s)
type family NatBase1' base parseDigit sCh digit s where
NatBase1' base parseDigit sCh digit '(Just ch, s) =
NatBaseLoop base parseDigit sCh s digit ch (parseDigit @@ ch) (UnconsState s)
NatBase1' base parseDigit sCh digit '(Nothing, s) =
'Reply (OK digit) s
type EEmpty = Error1 "no digits parsed"
type EInvalidDigit ch base =
Error1 ( "not a base " ++ ShowNatDec base ++ " digit: " ++ ShowChar ch)
type NatBaseLoop
:: Natural
-> (Char ~> Maybe Natural)
-> PState
-> PState
-> Natural
-> Char
-> Maybe Natural
-> (Maybe Char, PState)
-> PReply Natural
type family NatBaseLoop base parseDigit sCh s n chCur mDigit ms where
NatBaseLoop base parseDigit sCh s n chCur (Just digit) '(Just ch, sNext) =
NatBaseLoop base parseDigit s sNext (n * base + digit) ch (parseDigit @@ ch) (UnconsState sNext)
NatBaseLoop base parseDigit sCh s n chCur (Just digit) '(Nothing, sNext) =
'Reply (OK (n * base + digit)) sNext
NatBaseLoop base parseDigit sCh s n chCur Nothing '(_, sNext) =
'Reply (Err (EInvalidDigit chCur base)) sCh
type NatBaseWhile :: Natural -> (Char ~> Maybe Natural) -> PParser Natural
data NatBaseWhile base parseDigit s
type instance App (NatBaseWhile base parseDigit) s =
NatBaseWhileStart base parseDigit s (UnconsState s)
type family NatBaseWhileStart base parseDigit sCh s where
NatBaseWhileStart base parseDigit sCh '(Just ch, s) =
NatBaseWhileStart2 base parseDigit sCh s ch (parseDigit @@ ch) (UnconsState s)
NatBaseWhileStart base parseDigit sCh '(Nothing, s) = 'Reply (Err EEmpty) sCh
type family NatBaseWhileStart2 base parseDigit sCh s chChur mDigit ms where
NatBaseWhileStart2 base parseDigit sCh s chCur (Just digit) '(Just ch, sNext) =
NatBaseWhileLoop base parseDigit s sNext digit ch (parseDigit @@ ch) (UnconsState sNext)
NatBaseWhileStart2 base parseDigit sCh s chCur (Just digit) '(Nothing, sNext) =
'Reply (OK digit) sNext
NatBaseWhileStart2 base parseDigit sCh s chCur Nothing _ =
'Reply (Err (EInvalidDigit chCur base)) sCh
type NatBaseWhileLoop
:: Natural
-> (Char ~> Maybe Natural)
-> PState
-> PState
-> Natural
-> Char
-> Maybe Natural
-> (Maybe Char, PState)
-> PReply Natural
type family NatBaseWhileLoop base parseDigit sCh s n chCur mDigit ms where
NatBaseWhileLoop base parseDigit sCh s n chCur (Just digit) '(Just ch, sNext) =
NatBaseWhileLoop base parseDigit s sNext (n * base + digit) ch (parseDigit @@ ch) (UnconsState sNext)
NatBaseWhileLoop base parseDigit sCh s n chCur (Just digit) '(Nothing, sNext) =
'Reply (OK (n * base + digit)) sNext
NatBaseWhileLoop base parseDigit sCh s n chCur Nothing _ =
'Reply (OK n) sCh