parseNumericValue :: Parser (Text, NumericValue)
parseNumericValue = do
    -- Sign
    (sS, s) <- parseSign

    -- Digits before the decimal dot. They are optional (".1em").
    (iS, i) <- do
        digits <- AP.takeWhile isDigit
        return $ if (T.null digits)
            then ("", 0)
            else (digits, read $ T.unpack digits)

    -- Decimal dot and digits after it. If the decimal dot is there then it
    -- MUST be followed by one or more digits. This is not allowed: "1.".
    (fS, f, fB) <- option ("", 0, False) $ do
        _ <- AP.char '.'
        digits <- AP.takeWhile1 isDigit
        return ("." <> digits, read $ T.unpack digits, True)

    -- Exponent (with optional sign).
    (tS, t, eS, e, eB) <- option ("", 1, "", 0, False) $ do
        e <- AP.char 'E' <|> AP.char 'e'
        (tS, t) <- parseSign
        eS <- AP.takeWhile1 isDigit

        return (T.singleton e <> tS, t, eS, read $ T.unpack eS, True)

    let repr = sS<>iS<>fS<>tS<>eS
    if T.null repr || repr == "-" || repr == "+" || T.head repr == 'e' || T.head repr == 'E'
        then fail "parseNumericValue: no parse"
        else do
            let v = fromIntegral s * (i + f*10^^(-(T.length fS - 1))) * 10^^(t*e)
            return $ if fB || eB
                then (repr, NVNumber v)
                else (repr, NVInteger v)
parseNumericValue :: Parser (Text, NumericValue)
parseNumericValue = do
    -- Sign
    (sS, s) <- parseSign

    -- Digits before the decimal dot. They are optional (".1em").
    (iS, i) <- do
        digits <- AP.takeWhile isDigit
        return $ if (T.null digits)
            then ("", 0)
            else (digits, read $ T.unpack digits)

    -- Decimal dot and digits after it. If the decimal dot is there then it
    -- MUST be followed by one or more digits. This is not allowed: "1.".
    (fS, f, fB) <- option ("", 0, False) $ do
        _ <- AP.char '.'
        digits <- AP.takeWhile1 isDigit
        return ("." <> digits, read $ T.unpack digits, True)

    -- Exponent (with optional sign).
    (tS, t, eS, e, eB) <- option ("", 1, "", 0, False) $ do
        e <- AP.char 'E' <|> AP.char 'e'
        (tS, t) <- parseSign
        eS <- AP.takeWhile1 isDigit

        return (T.singleton e <> tS, t, eS, read $ T.unpack eS, True)

    let repr = sS<>iS<>fS<>tS<>eS
    if T.null repr || repr == "-" || repr == "+" || T.head repr == 'e' || T.head repr == 'E'
        then fail "parseNumericValue: no parse"
        else do
            let v = fromIntegral s * (i + f*10^^(-(T.length fS - 1))) * 10^^(t*e)
            return $ if fB || eB
                then (repr, NVNumber v)
                else (repr, NVInteger v)
parseNumericValue = do
    -- Sign
    (sS, s) <- parseSign

    -- Digits before the decimal dot. They are optional (".1em").
    (iS, i) <- do
        digits <- AP.takeWhile isDigit
        return $ if (T.null digits)
            then ("", 0)
            else (digits, read $ T.unpack digits)

    -- Decimal dot and digits after it. If the decimal dot is there then it
    -- MUST be followed by one or more digits. This is not allowed: "1.".
    (fS, f, fB) <- option ("", 0, False) $ do
        _ <- AP.char '.'
        digits <- AP.takeWhile1 isDigit
        return ("." <> digits, read $ T.unpack digits, True)

    -- Exponent (with optional sign).
    (tS, t, eS, e, eB) <- option ("", 1, "", 0, False) $ do
        e <- AP.char 'E' <|> AP.char 'e'
        (tS, t) <- parseSign
        eS <- AP.takeWhile1 isDigit

        return (T.singleton e <> tS, t, eS, read $ T.unpack eS, True)

    let repr = sS<>iS<>fS<>tS<>eS
    if T.null repr || repr == "-" || repr == "+" || T.head repr == 'e' || T.head repr == 'E'
        then fail "parseNumericValue: no parse"
        else do
            let v = fromIntegral s * (i + f*10^^(-(T.length fS - 1))) * 10^^(t*e)
            return $ if fB || eB
                then (repr, NVNumber v)
                else (repr, NVInteger v)