예제 #1
0
 void EmitBuffer(int i, CssTokenName tokenName)
 {
     //flush existing buffer
     if (this._appendLength > 0)
     {
         _emitHandler(tokenName, this._startIndex, this._appendLength);
     }
     this._appendLength = 0;
 }
예제 #2
0
 void Emit(CssTokenName tkname, int i)
 {
     _emitHandler(tkname, i, 1);
 }
예제 #3
0
        public void Lex(char[] cssSourceBuffer)
        {
            //----------------------
            //clear previous result
            this._appendLength    = 0;
            this._startIndex      = 0;
            this.latestEscapeChar = '\0';
            //----------------------

            CssLexState lexState = CssLexState.Init;
            int         j        = cssSourceBuffer.Length;

            for (int i = 0; i < j; ++i)
            {
                char c = cssSourceBuffer[i];
#if DEBUG
                // Console.Write(c);
#endif
                //--------------------------------------
                switch (lexState)
                {
                default:
                {
                    throw new NotSupportedException();
                }

                case CssLexState.Init:
                {
                    //--------------------------------------
                    //1. first name
                    CssTokenName terminalTokenName = GetTerminalTokenName(c);
                    //--------------------------------------
                    switch (terminalTokenName)
                    {
                    default:
                    {
                        Emit(terminalTokenName, i);
                    }
                    break;

                    case CssTokenName.Colon:
                    {
                        if (i < j - 1)
                        {
                            char c1 = cssSourceBuffer[i + 1];
                            if (c1 == ':')
                            {
                                i++;
                                Emit(CssTokenName.DoubleColon, i);
                                continue;
                            }
                        }
                        Emit(terminalTokenName, i);
                    }
                    break;

                    case CssTokenName.DoubleQuote:
                    {
                        latestEscapeChar = '"';
                        lexState         = CssLexState.CollectString;
                    }
                    break;

                    case CssTokenName.Quote:
                    {
                        latestEscapeChar = '\'';
                        lexState         = CssLexState.CollectString;
                    }
                    break;

                    case CssTokenName.Divide:
                    {
                        //is open comment or not
                        if (i < j - 1)
                        {
                            if (cssSourceBuffer[i + 1] == '*')
                            {
                                i++;
                                //Emit(CssTokenName.LComment, i);
                                lexState = CssLexState.Comment;
                                continue;
                            }
                        }
                        Emit(CssTokenName.Divide, i);
                    }
                    break;

                    case CssTokenName.Sharp:
                    {
                        AppendBuffer(i);
                        lexState = CssLexState.Iden;
                    }
                    break;

                    case CssTokenName.Dot:
                    {
                        if (i < j - 1)
                        {
                            char c1 = cssSourceBuffer[i + 1];
                            if (char.IsNumber(c1))
                            {
                                AppendBuffer(i);
                                i++;
                                AppendBuffer(i);
                                lexState = CssLexState.Number;
                                continue;
                            }
                        }
                        Emit(terminalTokenName, i);
                    }
                    break;

                    case CssTokenName.Minus:
                    {
                        //as iden
                        AppendBuffer(i);
                        lexState = CssLexState.Iden;
                    }
                    break;

                    case CssTokenName.Unknown:
                    {
                        //this is not terminal
                        AppendBuffer(i);
                        if (char.IsNumber(c))
                        {
                            lexState = CssLexState.Number;
                        }
                        else
                        {
                            lexState = CssLexState.Iden;
                        }
                    }
                    break;

                    case CssTokenName.Whitespace:
                    case CssTokenName.Newline:
                    {
                        isCollectionWhitespace = true;
                    }
                    break;
                    }
                }
                break;

                case CssLexState.CollectString:
                {
                    if (c == latestEscapeChar)
                    {
                        //exit collect string
                        lexState = CssLexState.Init;
                        EmitBuffer(i, CssTokenName.LiteralString);
                    }
                    else
                    {
                        AppendBuffer(i);
                    }
                }
                break;

                case CssLexState.Comment:
                {
                    if (c == '*')
                    {
                        if (i < j - 1)
                        {
                            char c1 = cssSourceBuffer[i + 1];
                            if (c1 == '/')
                            {
                                i++;
                                //Emit(CssTokenName.RComment, i);
                                lexState = CssLexState.Init;
                                continue;
                            }
                        }
                    }
                    //skip comment?
                }
                break;

                case CssLexState.Iden:
                {
                    CssTokenName terminalTokenName = GetTerminalTokenName(c);
                    switch (terminalTokenName)
                    {
                    case CssTokenName.Whitespace:
                    case CssTokenName.Newline:
                    {
                        EmitBuffer(i, CssTokenName.Iden);
                        lexState = CssLexState.Init;
                    }
                    break;

                    case CssTokenName.Divide:
                    {
                        //is open comment or not
                        throw new NotSupportedException();
                    }

                    case CssTokenName.Star:
                    {
                        //is close comment or not
                        throw new NotSupportedException();
                    }

                    case CssTokenName.Minus:
                    {
                        //iden can contains minus
                        AppendBuffer(i);
                    }
                    break;

                    default:
                    {
                        //flush exising buffer
                        EmitBuffer(i, CssTokenName.Iden);
                        Emit(terminalTokenName, i);
                        lexState = CssLexState.Init;
                    }
                    break;

                    case CssTokenName.Unknown:
                    {
                        //this is not terminal
                        AppendBuffer(i);
                        lexState = CssLexState.Iden;
                    }
                    break;
                    }
                }
                break;

                case CssLexState.Number:
                {
                    if (char.IsNumber(c))
                    {
                        AppendBuffer(i);
                        continue;
                    }
                    //----------------------------------------------------------
                    CssTokenName terminalTokenName = GetTerminalTokenName(c);
                    switch (terminalTokenName)
                    {
                    case CssTokenName.Whitespace:
                    case CssTokenName.Newline:
                    {
                        if (this._appendLength > 0)
                        {
                            EmitBuffer(i, CssTokenName.Number);
                        }

                        lexState = CssLexState.Init;
                    }
                    break;

                    case CssTokenName.Divide:
                    {
                        //is open comment or not
                        throw new NotSupportedException();
                    }

                    case CssTokenName.Star:
                    {                   //is close comment or not
                        throw new NotSupportedException();
                    }

                    case CssTokenName.Dot:
                    {
                        //after number
                        if (i < j - 1)
                        {
                            char c1 = cssSourceBuffer[i + 1];
                            if (char.IsNumber(c1))
                            {
                                AppendBuffer(i);
                                i++;
                                AppendBuffer(i);
                                lexState = CssLexState.Number;
                                continue;
                            }
                        }
                        EmitBuffer(i, CssTokenName.Number);
                        Emit(terminalTokenName, i);
                    }
                    break;

                    default:
                    {
                        //flush exising buffer
                        EmitBuffer(i, CssTokenName.Number);
                        Emit(terminalTokenName, i);
                        lexState = CssLexState.Init;
                    }
                    break;

                    case CssTokenName.Unknown:
                    {
                        EmitBuffer(i, CssTokenName.Number);
                        //iden after number may be unit of number***
                        AppendBuffer(i);
                        lexState = CssLexState.UnitAfterNumber;
                    }
                    break;
                    }
                }
                break;

                case CssLexState.UnitAfterNumber:
                {
                    if (char.IsLetter(c))
                    {
                        AppendBuffer(i);
                    }
                    else
                    {
                        //terminate

                        EmitBuffer(i, CssTokenName.NumberUnit);
                        //-------------------------------------------
                        CssTokenName terminalTokenName = GetTerminalTokenName(c);
                        switch (terminalTokenName)
                        {
                        case CssTokenName.Whitespace:
                        case CssTokenName.Newline:
                        {
                        }
                        break;

                        default:
                        {
                            Emit(terminalTokenName, i);
                        }
                        break;
                        }
                        lexState = CssLexState.Init;
                    }
                }
                break;
                }
            }
            if (this._appendLength > 0)
            {
                switch (lexState)
                {
                case CssLexState.UnitAfterNumber:
                    EmitBuffer(cssSourceBuffer.Length - 1, CssTokenName.NumberUnit);
                    break;

                case CssLexState.Number:
                    EmitBuffer(cssSourceBuffer.Length - 1, CssTokenName.Number);
                    break;

                case CssLexState.Iden:
                default:
                    EmitBuffer(cssSourceBuffer.Length - 1, CssTokenName.Iden);
                    break;
                }
            }
        }
예제 #4
0
 void Emit(CssTokenName tkname, int i)
 {
     _emitHandler(tkname, i, 1);
 }
예제 #5
0
 void EmitBuffer(int i, CssTokenName tokenName)
 {
     //flush existing buffer
     if (this._appendLength > 0)
     {
         _emitHandler(tokenName, this._startIndex, this._appendLength);
     }
     this._appendLength = 0;
 }
예제 #6
0
        void LexerEmitHandler(CssTokenName tkname, int start, int len)
        {
            switch (parseState)
            {
                default:
                    {
                        throw new NotSupportedException();
                    }
                    break;
                case CssParseState.Init:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.Comment:
                                {
                                    //comment token  
                                }
                                break;
                            case CssTokenName.RBrace:
                                {
                                    //exit from current ruleset block
                                    if (this._mediaStack.Count > 0)
                                    {
                                        this._currentAtMedia = this._mediaStack.Pop();
                                    }
                                }
                                break;
                            case CssTokenName.Star:
                                {
                                    //start new code block 
                                    CssRuleSet newblock;
                                    this._currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector(SimpleElementSelectorKind.All));
                                    parseState = CssParseState.MoreBlockName;
                                }
                                break;
                            case CssTokenName.At:
                                {
                                    //at rule                                    
                                    parseState = CssParseState.ExpectAtRuleName;
                                }
                                break;
                            //--------------------------------------------------
                            //1.
                            case CssTokenName.Colon:
                                {
                                    CssRuleSet newblock;
                                    _currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector(SimpleElementSelectorKind.PseudoClass));
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //2.
                            case CssTokenName.Dot:
                                {
                                    CssRuleSet newblock;
                                    _currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector(SimpleElementSelectorKind.ClassName));
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //3. 
                            case CssTokenName.DoubleColon:
                                {
                                    CssRuleSet newblock;
                                    _currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector(SimpleElementSelectorKind.Extend));
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //4.
                            case CssTokenName.Iden:
                                {
                                    //block name
                                    CssRuleSet newblock;
                                    _currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector());
                                    this._currentSelectorExpr.Name = new string(this.textBuffer, start, len);
                                    parseState = CssParseState.MoreBlockName;
                                }
                                break;
                            //5. 
                            case CssTokenName.Sharp:
                                {
                                    CssRuleSet newblock;
                                    _currentAtMedia.AddRuleSet(this._currentRuleSet = newblock = new CssRuleSet());
                                    newblock.AddSelector(this._currentSelectorExpr = new CssSimpleElementSelector(SimpleElementSelectorKind.Id));
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.MoreBlockName:
                    {
                        //more 
                        switch (tkname)
                        {
                            case CssTokenName.LBrace:
                                {
                                    //block body
                                    parseState = CssParseState.BlockBody;
                                }
                                break;
                            case CssTokenName.LBracket:
                                {
                                    //element attr
                                    parseState = CssParseState.ExpectBlockAttrIden;
                                }
                                break;
                            //1. 
                            case CssTokenName.Colon:
                                {
                                    //wait iden after colon
                                    var cssSelector = new CssSimpleElementSelector();
                                    cssSelector.selectorType = SimpleElementSelectorKind.PseudoClass;
                                    _currentRuleSet.AddSelector(cssSelector);
                                    this._currentSelectorExpr = cssSelector;
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //2. 
                            case CssTokenName.Dot:
                                {
                                    var cssSelector = new CssSimpleElementSelector();
                                    cssSelector.selectorType = SimpleElementSelectorKind.ClassName;
                                    _currentRuleSet.AddSelector(cssSelector);
                                    this._currentSelectorExpr = cssSelector;
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //3. 
                            case CssTokenName.DoubleColon:
                                {
                                    var cssSelector = new CssSimpleElementSelector();
                                    cssSelector.selectorType = SimpleElementSelectorKind.Extend;
                                    _currentRuleSet.AddSelector(cssSelector);
                                    this._currentSelectorExpr = cssSelector;
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //4. 
                            case CssTokenName.Iden:
                                {
                                    //add more block name                                     
                                    var cssSelector = new CssSimpleElementSelector();
                                    cssSelector.selectorType = SimpleElementSelectorKind.TagName;
                                    cssSelector.Name = new string(this.textBuffer, start, len);
                                    _currentRuleSet.AddSelector(cssSelector);
                                    this._currentSelectorExpr = cssSelector;
                                }
                                break;
                            //5. 
                            case CssTokenName.Sharp:
                                {
                                    //id
                                    var cssSelector = new CssSimpleElementSelector();
                                    cssSelector.selectorType = SimpleElementSelectorKind.Id;
                                    _currentRuleSet.AddSelector(cssSelector);
                                    this._currentSelectorExpr = cssSelector;
                                    parseState = CssParseState.ExpectIdenAfterSpecialBlockNameSymbol;
                                }
                                break;
                            //----------------------------------------------------
                               
                            //element combinator operators
                            case CssTokenName.Comma:
                                {
                                    this._currentRuleSet.PrepareExpression(CssCombinatorOperator.List);
                                }
                                break;
                            case CssTokenName.Star:
                                {
                                }break;

                            case CssTokenName.RAngle:
                                {
                                }
                                break;
                            case CssTokenName.Plus:
                                {
                                }
                                break;
                            case CssTokenName.Tile:
                                {
                                }
                                break;
                            //----------------------------------------------------
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.ExpectIdenAfterSpecialBlockNameSymbol:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.Iden:
                                {
                                    this._currentSelectorExpr.Name = new string(this.textBuffer, start, len);
                                    parseState = CssParseState.MoreBlockName;
                                }
                                break;
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                        }
                    }
                    break;
                case CssParseState.ExpectBlockAttrIden:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.Iden:
                                {
                                    //attribute  
                                    parseState = CssParseState.AfterAttrName;
                                    this._currentSelectorExpr.AddAttribute(this._currentSelectorAttr = new CssAttributeSelectorExpression());
                                    this._currentSelectorAttr.AttributeName = new string(this.textBuffer, start, len);
                                }
                                break;
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.AfterAttrName:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.OpEq:
                                {
                                    parseState = CssParseState.ExpectedBlockAttrValue;
                                    //expected  attr value
                                }
                                break;
                            case CssTokenName.RBracket:
                                {
                                    //no attr value
                                    parseState = CssParseState.MoreBlockName;
                                }
                                break;
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.ExpectedBlockAttrValue:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.LiteralString:
                                {
                                    this._currentSelectorAttr.valueExpression = this._latestPropertyValue =
                                        new CssCodePrimitiveExpression(new string(this.textBuffer, start, len), CssValueHint.LiteralString);
                                    this._currentSelectorAttr = null;
                                }
                                break;
                            default:
                                {
                                }
                                break;
                        }
                        parseState = CssParseState.AfterBlockNameAttr;
                    }
                    break;
                case CssParseState.AfterBlockNameAttr:
                    {
                        switch (tkname)
                        {
                            default:
                                {
                                }
                                break;
                            case CssTokenName.RBracket:
                                {
                                    parseState = CssParseState.MoreBlockName;
                                    this._currentSelectorAttr = null;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.BlockBody:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.Iden:
                                {
                                    //block name

                                    //create css property 
                                    string cssPropName = new string(this.textBuffer, start, len);
                                    var wellknownName = UserMapUtil.GetWellKnownPropName(cssPropName);
                                    if (wellknownName == WellknownCssPropertyName.Unknown)
                                    {
                                        _currentRuleSet.AddCssCodeProperty(this._currentProperty =
                                            new CssPropertyDeclaration(cssPropName));
                                    }
                                    else
                                    {
                                        _currentRuleSet.AddCssCodeProperty(this._currentProperty =
                                            new CssPropertyDeclaration(wellknownName));
                                    }
                                    this._latestPropertyValue = null;
                                    parseState = CssParseState.AfterPropertyName;
                                }
                                break;
                            case CssTokenName.RBrace:
                                {
                                    //close current block
                                    this._currentProperty = null;
                                    this._currentSelectorAttr = null;
                                    this._currentSelectorExpr = null;
                                    parseState = CssParseState.Init;
                                }
                                break;
                            case CssTokenName.SemiColon:
                                {
                                    //another semi colon just skip
                                }
                                break;
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.AfterPropertyName:
                    {
                        if (tkname == CssTokenName.Colon)
                        {
                            parseState = CssParseState.ExpectPropertyValue;
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                    }
                    break;
                case CssParseState.ExpectPropertyValue:
                    {
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.Sharp:
                                {
                                    //follow by hex color value
                                    parseState = CssParseState.ExpectValueOfHexColor;
                                }
                                break;
                            case CssTokenName.LiteralString:
                                {
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                         new CssCodePrimitiveExpression(new string(this.textBuffer, start, len), CssValueHint.LiteralString));
                                    parseState = CssParseState.AfterPropertyValue;
                                }
                                break;
                            case CssTokenName.Number:
                                {
                                    float number = float.Parse(new string(this.textBuffer, start, len));
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                          new CssCodePrimitiveExpression(number));
                                    parseState = CssParseState.AfterPropertyValue;
                                }
                                break;
                            case CssTokenName.NumberUnit:
                                {
                                }
                                break;
                            case CssTokenName.Iden:
                                {
                                    //property value
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                        new CssCodePrimitiveExpression(new string(this.textBuffer, start, len), CssValueHint.Iden));
                                    parseState = CssParseState.AfterPropertyValue;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.ExpectValueOfHexColor:
                    {
                        switch (tkname)
                        {
                            case CssTokenName.Iden:
                                {
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                       new CssCodePrimitiveExpression("#" + new string(this.textBuffer, start, len),
                                           CssValueHint.HexColor));
                                }
                                break;
                            case CssTokenName.Number:
                                {
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                         new CssCodePrimitiveExpression("#" + new string(this.textBuffer, start, len),
                                             CssValueHint.HexColor));
                                }
                                break;
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                        }
                        parseState = CssParseState.AfterPropertyValue;
                    }
                    break;
                case CssParseState.AfterPropertyValue:
                    {
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.Comma:
                                {
                                    //skip comma
                                }
                                break;
                            case CssTokenName.Percent:
                                {
                                    if (_latestPropertyValue is CssCodePrimitiveExpression)
                                    {
                                        ((CssCodePrimitiveExpression)_latestPropertyValue).Unit = "%";
                                    }
                                }
                                break;
                            case CssTokenName.Divide:
                                {
                                    //eg. font: style variant weight size/line-height family;

                                    CssCodeBinaryExpression codeBinaryOpExpr = new CssCodeBinaryExpression();
                                    codeBinaryOpExpr.OpName = CssValueOpName.Divide;
                                    codeBinaryOpExpr.Left = this._latestPropertyValue;
                                    //replace previous add value ***
                                    int valueCount = this._currentProperty.ValueCount;
                                    //replace
                                    this._currentProperty.ReplaceValue(valueCount - 1, codeBinaryOpExpr);
                                    this._latestPropertyValue = codeBinaryOpExpr;
                                }
                                break;
                            case CssTokenName.LiteralString:
                                {
                                    var literalValue = new string(this.textBuffer, start, len);
                                    throw new NotSupportedException();
                                }
                                break;
                            case CssTokenName.LParen:
                                {
                                    //function 
                                    parseState = CssParseState.ExpectedFuncParameter;
                                    //make current prop value as func
                                    CssCodeFunctionCallExpression funcCallExpr = new CssCodeFunctionCallExpression(
                                        this._latestPropertyValue.ToString());
                                    int valueCount = this._currentProperty.ValueCount;
                                    this._currentProperty.ReplaceValue(valueCount - 1, funcCallExpr);
                                    this._latestPropertyValue = funcCallExpr;
                                }
                                break;
                            case CssTokenName.RBrace:
                                {
                                    //close block
                                    parseState = CssParseState.Init;
                                }
                                break;
                            case CssTokenName.SemiColon:
                                {
                                    //start new proeprty
                                    parseState = CssParseState.BlockBody;
                                    this._currentProperty = null;
                                }
                                break;
                            case CssTokenName.Iden:
                                {
                                    //another property value                                     
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                        new CssCodePrimitiveExpression(new string(this.textBuffer, start, len), CssValueHint.Iden));
                                }
                                break;
                            case CssTokenName.Number:
                                {
                                    //another property value
                                    float number = float.Parse(new string(this.textBuffer, start, len));
                                    this._currentProperty.AddValue(this._latestPropertyValue =
                                        new CssCodePrimitiveExpression(number));
                                }
                                break;
                            case CssTokenName.NumberUnit:
                                {
                                    //number unit 
                                    if (_latestPropertyValue is CssCodePrimitiveExpression)
                                    {
                                        ((CssCodePrimitiveExpression)_latestPropertyValue).Unit = new string(this.textBuffer, start, len);
                                    }
                                }
                                break;
                            case CssTokenName.Sharp:
                                {
                                    parseState = CssParseState.ExpectValueOfHexColor;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.ExpectAtRuleName:
                    {
                        //iden
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.Iden:
                                {
                                    string iden = new string(this.textBuffer, start, len);
                                    //create new rule
                                    _currentRuleSet = null;
                                    _currentProperty = null;
                                    _currentSelectorAttr = null;
                                    _currentSelectorExpr = null;
                                    switch (iden)
                                    {
                                        case "media":
                                            {
                                                parseState = CssParseState.MediaList;
                                                //store previous media 
                                                if (this._currentAtMedia != null)
                                                {
                                                    this._mediaStack.Push(this._currentAtMedia);
                                                }

                                                this.cssDocument.Add(this._currentAtMedia = new CssAtMedia());
                                            }
                                            break;
                                        case "import":
                                            {
                                                parseState = CssParseState.ExpectImportURL;
                                            }
                                            break;
                                        case "page":
                                            {
                                                throw new NotSupportedException();
                                            }
                                            break;
                                        default:
                                            {
                                                throw new NotSupportedException();
                                            }
                                            break;
                                    }
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.MediaList:
                    {
                        //medialist sep by comma
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.Iden:
                                {
                                    //media name                                     
                                    this._currentAtMedia.AddMedia(new string(this.textBuffer, start, len));
                                }
                                break;
                            case CssTokenName.Comma:
                                {
                                    //wait for another media
                                }
                                break;
                            case CssTokenName.LBrace:
                                {
                                    //begin rule set part
                                    parseState = CssParseState.Init;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.ExpectedFuncParameter:
                    {
                        string funcArg = new string(this.textBuffer, start, len);
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.RParen:
                                {
                                    this.parseState = CssParseState.AfterPropertyValue;
                                }
                                break;
                            case CssTokenName.LiteralString:
                                {
                                    ((CssCodeFunctionCallExpression)this._latestPropertyValue).AddFuncArg(
                                        new CssCodePrimitiveExpression(funcArg, CssValueHint.LiteralString));
                                    this.parseState = CssParseState.AfterFuncParameter;
                                }
                                break;
                            case CssTokenName.Number:
                                {
                                    float number = float.Parse(funcArg);
                                    ((CssCodeFunctionCallExpression)this._latestPropertyValue).AddFuncArg(
                                          new CssCodePrimitiveExpression(number));
                                    this.parseState = CssParseState.AfterFuncParameter;
                                }
                                break;
                            case CssTokenName.Iden:
                                {
                                    ((CssCodeFunctionCallExpression)this._latestPropertyValue).AddFuncArg(
                                        new CssCodePrimitiveExpression(funcArg, CssValueHint.Iden));
                                    this.parseState = CssParseState.AfterFuncParameter;
                                }
                                break;
                        }
                    }
                    break;
                case CssParseState.AfterFuncParameter:
                    {
                        switch (tkname)
                        {
                            default:
                                {
                                    throw new NotSupportedException();
                                }
                            case CssTokenName.RParen:
                                {
                                    this.parseState = CssParseState.AfterPropertyValue;
                                }
                                break;
                            case CssTokenName.Comma:
                                {
                                    this.parseState = CssParseState.ExpectedFuncParameter;
                                }
                                break;
                        }
                    }
                    break;
            }
        }