internal static int InferSimpleType()

in src/libraries/System.Private.Xml/src/System/Xml/Schema/Inference/Infer.cs [1743:2359]


        internal static int InferSimpleType(string s, ref bool bNeedsRangeCheck)
        {
            bool bNegative = false;
            bool bPositive = false;
            bool bDate = false;
            bool bTime = false;
            bool bMissingDay = false;

            if (s.Length == 0) return TF_string;
            int i = 0;
            switch (s[i])
            {
                case 't':
                case 'f':
                    if (s == "true")
                        return TF_boolean | TF_string;
                    else if (s == "false")
                        return TF_boolean | TF_string;
                    else
                        return TF_string;
                case 'N':       //try to match "NaN"
                    if (s == "NaN")
                        return TF_float | TF_double | TF_string;
                    else
                        return TF_string;
                //else
                case 'I':       //try to match "INF"
                INF:
                    if (s.AsSpan(i) is "INF")
                        return TF_float | TF_double | TF_string;
                    else return TF_string;
                case '.':       //try to match ".9999"  decimal/float/double
                FRACTION:
                    bNeedsRangeCheck = true;
                    i++;
                    if (i == s.Length)
                    {
                        if ((i == 1) || (i == 2 && (bPositive || bNegative)))   //"." "-." "+."
                            return TF_string;
                        else
                            return TF_decimal | TF_float | TF_double | TF_string;
                    }
                    switch (s[i])
                    {
                        case 'e':
                        case 'E':
                            goto EXPONENT;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto DEC_PART;
                            else
                                return TF_string;
                    }
                DEC_PART:
                    i++; if (i == s.Length) return TF_decimal | TF_float | TF_double | TF_string; //"9999.9" was matched
                    switch (s[i])
                    {
                        case 'e':
                        case 'E':
                            goto EXPONENT;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto DEC_PART;
                            else
                                return TF_string;
                    }
                EXPONENT:
                    i++; if (i == s.Length) return TF_string;
                    switch (s[i])
                    {
                        case '+':
                        case '-':
                            goto E1;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto EXP_PART;
                            else
                                return TF_string;
                    }
                E1:
                    i++; if (i == s.Length) return TF_string; //".9999e+" was matched
                    if (char.IsAsciiDigit(s[i]))
                        goto EXP_PART;
                    else
                        return TF_string;   //".999e+X was matched
                    EXP_PART:
                    i++; if (i == s.Length) return TF_float | TF_double | TF_string;  //".9999e+99" was matched
                    if (char.IsAsciiDigit(s[i])) //".9999e+9
                        goto EXP_PART;
                    else
                        return TF_string;   //".9999e+999X" was matched
                case '-':
                    bNegative = true;
                    i++; if (i == s.Length) return TF_string;
                    switch (s[i])
                    {
                        case 'I':   //try to match "-INF"
                            goto INF;
                        case '.':   //try to match "-.9999"
                            goto FRACTION;
                        case 'P':
                            goto DURATION;
                        default:
                            if (char.IsAsciiDigit(s[i])) //-9
                                goto NUMBER;
                            else return TF_string;
                    }
                case '+':
                    bPositive = true;
                    i++; if (i == s.Length) return TF_string;
                    switch (s[i])
                    {
                        case '.':   //try to match "+.9999"
                            goto FRACTION;
                        case 'P':
                            goto DURATION;
                        default:
                            if (char.IsAsciiDigit(s[i])) //"+9
                                goto NUMBER;
                            else return TF_string;
                    }
                case 'P':       //try to match duration
                DURATION:
                    i++; if (i == s.Length) return TF_string;
                    switch (s[i])
                    {
                        case 'T':
                            goto D7;
                        default:
                            if (char.IsAsciiDigit(s[i])) //"P9"
                                goto D1;
                            else return TF_string;
                    }
                D1:
                    i++; if (i == s.Length) return TF_string; //"P999" was matched
                    switch (s[i])
                    {
                        case 'Y':
                            goto D2;
                        case 'M':
                            goto D4;
                        case 'D':
                            goto D6;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D1;
                            else
                                return TF_string;
                    }
                D2:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"P999Y" was matched
                    }
                    switch (s[i])
                    {
                        case 'T':
                            goto D7;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D3;
                            else
                                return TF_string;
                    }
                D3:
                    i++; if (i == s.Length) return TF_string; //"P999Y9" was matched
                    switch (s[i])
                    {
                        case 'M':
                            goto D4;
                        case 'D':
                            goto D6;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D3;
                            else
                                return TF_string;
                    }
                D4:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"P999Y999M" was matched
                    }
                    switch (s[i])
                    {
                        case 'T':
                            goto D7;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D5;
                            else
                                return TF_string;
                    }
                D5:
                    i++; if (i == s.Length) return TF_string; //"P999Y999M9" was matched
                    switch (s[i])
                    {
                        case 'D':
                            goto D6;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D5;
                            else
                                return TF_string;
                    }
                D6:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"P999Y999M999D" was matched
                    }
                    switch (s[i])
                    {
                        case 'T':
                            goto D7;
                        default:
                            return TF_string;
                    }
                D7:
                    i++; if (i == s.Length) return TF_string; //"P999Y999M9999DT" was matched
                    if (char.IsAsciiDigit(s[i]))
                        goto D8;
                    else
                        return TF_string;
                    D8:
                    i++; if (i == s.Length) return TF_string; //"___T9" was matched
                    switch (s[i])
                    {
                        case 'H':
                            goto D9;
                        case 'M':
                            goto D11;
                        case '.':
                            goto D13;
                        case 'S':
                            goto D15;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D8;
                            else
                                return TF_string;
                    }
                D9:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"___T999H" was matched
                    }
                    if (char.IsAsciiDigit(s[i]))
                        goto D10;
                    else
                        return TF_string;
                    D10:
                    i++; if (i == s.Length) return TF_string; //"___T999H9" was matched
                    switch (s[i])
                    {
                        case 'M':
                            goto D11;
                        case '.':
                            goto D13;
                        case 'S':
                            goto D15;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D10;
                            else
                                return TF_string;
                    }
                D11:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"___T999H999M" was matched
                    }
                    if (char.IsAsciiDigit(s[i]))
                        goto D12;
                    else
                        return TF_string;
                    D12:
                    i++; if (i == s.Length) return TF_string; //"___T999H999M9" was matched
                    switch (s[i])
                    {
                        case '.':
                            goto D13;
                        case 'S':
                            goto D15;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D12;
                            else
                                return TF_string;
                    }
                D13:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"___T999H999M999." was matched
                    }
                    if (char.IsAsciiDigit(s[i]))
                        goto D14;
                    else
                        return TF_string;
                    D14:
                    i++; if (i == s.Length) return TF_string; //"___T999H999M999.9" was matched
                    switch (s[i])
                    {
                        case 'S':
                            goto D15;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto D14;
                            else
                                return TF_string;
                    }
                D15:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_duration | TF_string; //"___T999H999M999.999S" was matched
                    }
                    else return TF_string;
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                NUMBER:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        if (bNegative || bPositive)
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;  //"-9"
                        else
                        {
                            if (s == "0" || s == "1")
                                return TF_boolean | TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
                                    TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
                            else
                                return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
                                    TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
                        }
                    }
                    switch (s[i])
                    {
                        case '.':
                            goto FRACTION;
                        case 'e':
                        case 'E':
                            bNeedsRangeCheck = true;
                            return TF_float | TF_double | TF_string;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto N2;
                            else
                                return TF_string;
                    }
                N2:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        if (bNegative || bPositive)
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;  //"-9"
                        else
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
                                TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
                    }
                    switch (s[i])
                    {
                        case '.':
                            goto FRACTION;
                        case ':':
                            bTime = true;
                            goto MINUTE;
                        case 'e':
                        case 'E':
                            bNeedsRangeCheck = true;
                            return TF_float | TF_double | TF_string;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto N3;
                            else
                                return TF_string;
                    }

                N3:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true; //three digits may not fit byte and unsignedByte
                        if (bNegative || bPositive)
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;  //"-9"
                        else
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
                                TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
                    }
                    switch (s[i])
                    {
                        case '.':
                            goto FRACTION;
                        case 'e':
                        case 'E':
                            bNeedsRangeCheck = true;
                            return TF_float | TF_double | TF_string;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto N4;
                            else
                                return TF_string;
                    }
                N4:
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        if (bNegative || bPositive)
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;  //"-9"
                        else
                            return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
                                TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
                    }

                    switch (s[i])
                    {
                        case '-':
                            bDate = true;
                            goto DATE;
                        case '.':
                            goto FRACTION;
                        case 'e':
                        case 'E':
                            bNeedsRangeCheck = true;
                            return TF_float | TF_double | TF_string;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto N4;
                            else
                                return TF_string;
                    }
                DATE:
                    i++; if (i == s.Length) return TF_string; //"9999-"
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string; //"9999-9"
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++;
                    if (i == s.Length)
                    {
                        bNeedsRangeCheck = true;
                        return TF_gYearMonth | TF_string;   //"9999-99"
                    }
                    switch (s[i])
                    {
                        case '-':
                            goto DAY;
                        case 'Z':
                        case 'z':
                            bMissingDay = true;
                            goto ZULU;
                        case '+':
                            bMissingDay = true;
                            goto ZONE_SHIFT;
                        default:
                            return TF_string;
                    }
                DAY:
                    i++; if (i == s.Length) return TF_string; //"9999-99-"
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string; //"9999-99-9"
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return DateTime(s, bDate, bTime); //"9999-99-99"
                    switch (s[i])
                    {
                        case 'Z':
                        case 'z':
                            goto ZULU;
                        case '+':
                        case '-':
                            goto ZONE_SHIFT;
                        case 'T':
                            bTime = true;
                            goto TIME;
                        case ':':
                            bMissingDay = true;
                            goto ZONE_SHIFT_MINUTE;
                        default:
                            return TF_string;
                    }
                ZULU:
                    i++;
                    if (i == s.Length)
                    {
                        if (bMissingDay)
                        {
                            bNeedsRangeCheck = true;
                            return TF_gYearMonth | TF_string;
                        }
                        else
                        {
                            return DateTime(s, bDate, bTime);
                        }
                    }
                    else
                        return TF_string;
                    ZONE_SHIFT:
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (s[i] != ':')
                        return TF_string;
                    ZONE_SHIFT_MINUTE:
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++;
                    if (i == s.Length)
                    {
                        if (bMissingDay)
                        {
                            bNeedsRangeCheck = true;
                            return TF_gYearMonth | TF_string;
                        }
                        else
                        {
                            return DateTime(s, bDate, bTime);
                        }
                    }
                    else return TF_string;
                    TIME:
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (s[i] != ':')
                        return TF_string;
                    MINUTE:
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (s[i] != ':')
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    i++; if (i == s.Length) return DateTime(s, bDate, bTime);
                    switch (s[i])
                    {
                        case 'Z':
                        case 'z':
                            goto ZULU;
                        case '+':
                        case '-':
                            goto ZONE_SHIFT;
                        case '.':
                            goto SECOND_FRACTION;
                        default:
                            return TF_string;
                    }
                SECOND_FRACTION:
                    i++; if (i == s.Length) return TF_string;
                    if (!char.IsAsciiDigit(s[i]))
                        return TF_string;
                    FRACT_DIGITS:
                    i++; if (i == s.Length) return DateTime(s, bDate, bTime);
                    switch (s[i])
                    {
                        case 'Z':
                        case 'z':
                            goto ZULU;
                        case '+':
                        case '-':
                            goto ZONE_SHIFT;
                        default:
                            if (char.IsAsciiDigit(s[i]))
                                goto FRACT_DIGITS;
                            else
                                return TF_string;
                    }
                default:
                    return TF_string;
            }
        }