{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE LambdaCase #-}

module Data.SemanticVersion.NumericIdentifier where

import Control.Applicative
import Control.Lens
import Data.Digit
import Text.Parser.Char

-- $setup
-- >>> import Text.Parsec(parse)
-- >>> import Data.Either(isLeft)

-- <numeric identifier> ::= "0"
--                        | <positive digit>
--                        | <positive digit> <digits>
data NumericIdentifier =
  NumericIdentifierZero
  | NumericIdentifierDigits DecDigitNoZero [DecDigit]
  deriving (NumericIdentifier -> NumericIdentifier -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NumericIdentifier -> NumericIdentifier -> Bool
$c/= :: NumericIdentifier -> NumericIdentifier -> Bool
== :: NumericIdentifier -> NumericIdentifier -> Bool
$c== :: NumericIdentifier -> NumericIdentifier -> Bool
Eq, Int -> NumericIdentifier -> ShowS
[NumericIdentifier] -> ShowS
NumericIdentifier -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NumericIdentifier] -> ShowS
$cshowList :: [NumericIdentifier] -> ShowS
show :: NumericIdentifier -> String
$cshow :: NumericIdentifier -> String
showsPrec :: Int -> NumericIdentifier -> ShowS
$cshowsPrec :: Int -> NumericIdentifier -> ShowS
Show)

class HasNumericIdentifier a where
  numericIdentifier ::
    Lens' a NumericIdentifier

instance HasNumericIdentifier NumericIdentifier where
  numericIdentifier :: Lens' NumericIdentifier NumericIdentifier
numericIdentifier =
    forall a. a -> a
id

class AsNumericIdentifier a where
  _NumericIdentifier ::
    Prism' a NumericIdentifier
  _NumericIdentifierZero ::
    Prism' a ()
  _NumericIdentifierZero =
    forall a. AsNumericIdentifier a => Prism' a NumericIdentifier
_NumericIdentifier forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (\() -> NumericIdentifier
NumericIdentifierZero)
      (\case
        NumericIdentifier
NumericIdentifierZero ->
          forall a. a -> Maybe a
Just ()
        NumericIdentifier
_ ->
          forall a. Maybe a
Nothing)
  _NumericIdentifierDigits ::
    Prism' a (DecDigitNoZero, [DecDigit])
  _NumericIdentifierDigits =
    forall a. AsNumericIdentifier a => Prism' a NumericIdentifier
_NumericIdentifier forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry DecDigitNoZero -> [DecDigit] -> NumericIdentifier
NumericIdentifierDigits)
      (\case
        NumericIdentifierDigits DecDigitNoZero
d [DecDigit]
ds ->
          forall a. a -> Maybe a
Just (DecDigitNoZero
d, [DecDigit]
ds)
        NumericIdentifier
_ ->
          forall a. Maybe a
Nothing)

instance AsNumericIdentifier NumericIdentifier where
  _NumericIdentifier :: Prism' NumericIdentifier NumericIdentifier
_NumericIdentifier =
    forall a. a -> a
id

-- |
--
-- >>> parse (parseNumericIdentifier <* eof) "parseNumericIdentifier" "0"
-- Right NumericIdentifierZero
--
-- >>> isLeft (parse parseNumericIdentifier "parseNumericIdentifier" "")
-- True
--
-- >>> parse parseNumericIdentifier "parseNumericIdentifier" "01"
-- Right NumericIdentifierZero
--
-- >>> parse parseNumericIdentifier "parseNumericIdentifier" "10"
-- Right (NumericIdentifierDigits DecDigitNoZero1 [DecDigit0])
--
-- >>> parse parseNumericIdentifier "parseNumericIdentifier" "38012"
-- Right (NumericIdentifierDigits DecDigitNoZero3 [DecDigit8,DecDigit0,DecDigit1,DecDigit2])
--
-- >>> isLeft (parse parseNumericIdentifier "parseNumericIdentifier" "a")
-- True
--
-- >>> isLeft (parse parseNumericIdentifier "parseNumericIdentifier" "-")
-- True
parseNumericIdentifier ::
  CharParsing p =>
  p NumericIdentifier
parseNumericIdentifier :: forall (p :: * -> *). CharParsing p => p NumericIdentifier
parseNumericIdentifier =
  NumericIdentifier
NumericIdentifierZero forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'0' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  DecDigitNoZero -> [DecDigit] -> NumericIdentifier
NumericIdentifierDigits forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall d (p :: * -> *). (DecimalNoZero d, CharParsing p) => p d
parseDecimalNoZero forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Alternative f => f a -> f [a]
many forall d (p :: * -> *). (Decimal d, CharParsing p) => p d
parseDecimal