css-parser-0.0.1: src/CssParser/Rule/TypedNum.hs
module CssParser.Rule.TypedNum where
import CssParser.Parser.Monad
import CssParser.Prelude
import CssParser.Show
import Data.HashMap.Strict qualified as HM
import Data.Text qualified as C8
type NumberStr = String
data PropValType
= Cap
| Ch
| Cm
| Cqb
| Cqh
| Cqi
| Cqmax
| Cqmin
| Cqw
| Deg
| Dpi
| Dvb
| Dvh
| Dvi
| Dvmax
| Dvmin
| Em
| Ex
| Fr
| Grad
| Hz
| Ic
| In
| KHz
| Lh
| Lvb
| Lvh
| Lvi
| Lvmax
| Lvmin
| Mm
| Ms
| N -- virtual unit used for pasing nth-child(-2n + 1)
| Pc
| Pt
| Percent
| Px
| Q
| Rad
| Rcap
| Rch
| Rem
| Rex
| Ric
| Rlh
| Second
| Svb
| Svh
| Svi
| Svmax
| Svmin
| Turn
| Vb
| Vh
| Vi
| Vmax
| Vmin
| Vw
| K
deriving (Eq, Ord, Show, Enum, Bounded, Generic)
instance CssShow PropValType where
toCssText = \case
Cap -> "cap"
Ch -> "ch"
Cm -> "cm"
Cqb -> "cqb"
Cqh -> "cqh"
Cqi -> "cqi"
Cqmax -> "cqmax"
Cqmin -> "cqmin"
Cqw -> "cqw"
Deg -> "deg"
Dpi -> "dpi"
Dvb -> "dvb"
Dvh -> "dvh"
Dvi -> "dvi"
Dvmax -> "dvmax"
Dvmin -> "dvmin"
Em -> "em"
Ex -> "ex"
Fr -> "fr"
Grad -> "grad"
Hz -> "Hz"
KHz -> "kHz"
Ic -> "ic"
In -> "in"
Lh -> "lh"
Lvb -> "lvb"
Lvh -> "lvh"
Lvi -> "lvi"
Lvmax -> "lvmax"
Lvmin -> "lvmin"
Mm -> "mm"
Ms -> "ms"
N -> "n"
Pc -> "pc"
Pt -> "pt"
Percent -> "%"
Px -> "px"
Q -> "q"
Rad -> "rad"
Rcap -> "rcap"
Rch -> "rch"
Rem -> "rem"
Rex -> "rex"
Ric -> "ric"
Rlh -> "rlh"
Second -> "s"
Svb -> "svb"
Svh -> "svh"
Svi -> "svi"
Svmax -> "svmax"
Svmin -> "svmin"
Turn -> "turn"
Vb -> "vb"
Vh -> "vh"
Vi -> "vi"
Vmax -> "vmax"
Vmin -> "vmin"
Vw -> "vw"
K -> ""
unitMap :: HM.HashMap Text PropValType
unitMap = mkDecodingMap
newtype RawNum = RawNum Text
deriving newtype (Eq, Ord, Show, IsString) deriving (Generic)
mkRawNum :: String -> RawNum
mkRawNum = RawNum . C8.pack
instance CssShow RawNum where
toCssText (RawNum x) = fromStrict x
data TypedNum = TypedNum RawNum PropValType deriving (Show, Ord, Eq, Generic)
instance CssShow TypedNum where
toCssText (TypedNum n t) = toCssText n <> toCssText t
tryGet :: PropValType -> TypedNum -> P RawNum
tryGet tt tn@(TypedNum v t)
| t == tt = pure v
| otherwise = Failed $ "Expected " <> toCssStr tt <> " but " <> toCssStr tn
parseTypedNum :: NumberStr -> P TypedNum
parseTypedNum = go . break isDigit . reverse
where
go (rSuf, rNum) =
let suf = reverse rSuf in
case smartLookup (C8.pack suf) unitMap of
Just pvt ->
pure $ TypedNum (mkRawNum $ reverse rNum) pvt
Nothing ->
Failed $ "Unknown number unit: " <> suf <> " in " <> reverse rNum
parseAsUnitType :: Text -> P PropValType
parseAsUnitType ut =
case smartLookup ut unitMap of
Just pvt -> pure pvt
Nothing -> Failed $ "Unkown number unit: " <> C8.unpack ut