module Data.Primitive.Internal.Read
  ( Tag(..)
  , lexTag
  ) where

import Data.Char (isDigit)
import Text.ParserCombinators.ReadP

data Tag = FromListTag | FromListNTag

-- Why don't we just use lexP? The general problem with lexP is that
-- it doesn't always fail as fast as we might like. It will
-- happily read to the end of an absurdly long lexeme (e.g., a 200MB string
-- literal) before returning, at which point we'll immediately discard
-- the result because it's not an identifier. Doing the job ourselves, we
-- can see very quickly when we've run into a problem. We should also get
-- a slight efficiency boost by going through the string just once.
lexTag :: ReadP Tag
lexTag :: ReadP Tag
lexTag = do
  String
_ <- String -> ReadP String
string String
"fromList"
  String
s <- ReadP String
look
  case String
s of
    Char
'N':Char
c:String
_
      | Char -> Bool
isDigit Char
c
      -> String -> ReadP Tag
forall a. String -> ReadP a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"" -- We have fromListN3 or similar
      | Bool
otherwise -> Tag
FromListNTag Tag -> ReadP Char -> ReadP Tag
forall a b. a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ReadP Char
get -- Skip the 'N'
    String
_ -> Tag -> ReadP Tag
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return Tag
FromListTag