private CssToken ScanNum()

in AjaxMinDll/Css/CssScanner.cs [1019:1147]


        private CssToken ScanNum()
        {
            CssToken token = null;
            string num = GetNum();
            if (num != null)
            {
                if (m_currentChar == '%')
                {
                    NextChar();

                    // let's always keep the percentage on the number, even if it's
                    // zero -- some things require it (like the rgb function)
                    token = new CssToken(
                      TokenType.Percentage,
                      num + '%',
                      m_context
                      );

                    // and make sure the "raw number" we keep has it as well
                    m_rawNumber += '%';
                }
                else
                {
                    string dimen = GetIdent();
                    if (dimen == null)
                    {
                        // if there is no identifier, it's a num.
                        token = new CssToken(TokenType.Number, num, m_context);
                    }
                    else
                    {
                        // add the dimension to the raw number
                        m_rawNumber += dimen;

                        // classify the dimension type
                        TokenType tokenType = TokenType.Dimension;
                        switch (dimen.ToUpperInvariant())
                        {
                            case "EM":          // font-size of the element
                            case "EX":          // x-height of the element's font
                            case "CH":          // width of the zero glyph in the element's font
                            case "REM":         // font-size of the root element
                            case "VW":          // viewport's width
                            case "VH":          // viewport's height
                            case "VM":          // viewport width or height, whichever is smaller of the two (use VMIN)
                            case "VMIN":        // minimum of the viewport's height and width
                            case "VMAX":        // maximum of the viewport's height and width
                            case "FR":          // fraction of available space
                            case "GR":          // grid unit
                            case "GD":          // text grid unit
                                tokenType = TokenType.RelativeLength;
                                break;

                            case "CM":          // centimeters
                            case "MM":          // millimeters
                            case "IN":          // inches (1in == 2.54cm)
                            case "PX":          // pixels (1px == 1/96in)
                            case "PT":          // points (1pt == 1/72in)
                            case "PC":          // picas (1pc == 12pt)
                                tokenType = TokenType.AbsoluteLength;
                                break;

                            case "DEG":         // degrees (360deg == 1 full circle)
                            case "GRAD":        // gradians (400grad == 1 full circle)
                            case "RAD":         // radians (2*pi radians == 1 full circle)
                            case "TURN":        // turns (1turn == 1 full circle)
                                tokenType = TokenType.Angle;
                                break;

                            case "MS":          // milliseconds
                            case "S":           // seconds
                                tokenType = TokenType.Time;
                                break;

                            case "DPI":         // dots per inch
                            case "DPCM":        // dots per centimeter
                            case "DPPX":        // dots per pixel
                                tokenType = TokenType.Resolution;
                                break;

                            case "HZ":          // hertz
                            case "KHZ":         // kilohertz
                                tokenType = TokenType.Frequency;
                                break;

                            case "DB":          // decibel
                            case "ST":          // semitones
                                tokenType = TokenType.Speech;
                                break;
                        }

                        // if the number is zero, it really doesn't matter what the dimensions are so we can remove it
                        // EXCEPT for Angles, Times, Frequencies, and Resolutions - they should not get their units
                        // stripped, since we can only do that for LENGTHS as per the specs.
                        // And percentages, since 0% is the same as 0. (true?)
                        // ALSO, if we don't recognize the dimension, leave it -- it could be a browser hack or some
                        // other intentional construct.
                        if (num == "0" 
                            && tokenType != TokenType.Dimension
                            && tokenType != TokenType.Angle
                            && tokenType != TokenType.Time
                            && tokenType != TokenType.Frequency
                            && tokenType != TokenType.Resolution)
                        {
                            token = new CssToken(TokenType.Number, num, m_context);
                        }
                        else
                        {
                            token = new CssToken(tokenType, num + dimen, m_context);
                        }
                    }
                }
            }
            else if (m_currentChar == '.')
            {
                token = new CssToken(TokenType.Character, '.', m_context);
                NextChar();
            }
            else
            {
                // this function is only called when the first character is 
                // a digit or a period. So this block should never execute, since
                // a digit will produce a num, and if it doesn't, the previous block
                // picks up the period.
                ReportError(1, CssErrorCode.UnexpectedNumberCharacter, m_currentChar);
            }

            return token;
        }