Inheritance: CssObject, ICssValue
Exemplo n.º 1
0
        /// <summary>
        /// (BNF) declaration : property ':' S* value;
        /// (BNF) property    : IDENT S*;
        /// </summary>
        /// <returns></returns>
        private CssDeclaration ParseDeclaration()
        {
            CssDeclaration declaration = new CssDeclaration();
            char ch;

            while (this.Read(out ch) && (Char.IsWhiteSpace(ch) || ch == ';'))
            {
                // skip whitespace, and empty declarations
            }

            // consume property name
            switch (ch)
            {
                case '{':
                case ':':
                //case ';':
                {
                    throw new SyntaxError("Declaration missing property name", this.reader.FilePath, this.reader.Line, this.reader.Column);
                }
                case '}':
                {
                    // no more declarations
                    return null;
                }
            }

            // read property, starting with current char
            int start = this.Position;
            while (this.Read(out ch) && !Char.IsWhiteSpace(ch) && ch != ':')
            {
                // consume property name
                switch (ch)
                {
                    case '{':
                    //case ':':
                    case ';':
                    {
                        throw new SyntaxError("Invalid CSS property name: "+this.Copy(start), this.reader.FilePath, this.reader.Line, this.reader.Column);
                    }
                    case '}':
                    {
                        this.PutBack();
                        goto case ';';
                    }
                }
            }
            declaration.Property = this.Copy(start);

            if (Char.IsWhiteSpace(ch))
            {
                while (this.Read(out ch) && (Char.IsWhiteSpace(ch)))
                {
                    // skip whitespace
                }
            }

            if (ch != ':')
            {
                // missing the property delim and value

                if (ch == ';' || ch == '}')
                {
                    // these are good chars for resyncing
                    // so put them back on the stream to
                    // not create subsequent errors
                    this.PutBack();
                }
                throw new SyntaxError("Expected <property> : <value>", this.reader.FilePath, this.reader.Line, this.reader.Column);
            }

            CssValueList value = this.ParseValue();
            declaration.Value = value;

            return declaration;
        }
Exemplo n.º 2
0
        /*
         * /// <summary>
         * /// (BNF) block : '{' S* [ any | block | ATKEYWORD S* | ';' S* ]* '}' S*;
         * /// </summary>
         * /// <returns></returns>
         * private CssBlock ParseBlock()
         * {
         *      CssBlock block = new CssBlock();
         *      int start = this.Position;// start with current char
         *
         *      char ch;
         *      while (this.Read(out ch))
         *      {
         *              switch (ch)
         *              {
         *                      case '@':
         *                      {
         *                              // copy anything before
         *                              string value = this.Copy(start);
         *                              if (value != null && !String.IsNullOrEmpty(value = value.Trim()))
         *                              {
         *                                      CssString any = new CssString();
         *                                      any.Value = value;
         *                                      block.Values.Add(any);
         *                              }
         *
         *                              // parse inner block
         *                              CssAtRule atRule = this.ParseAtRule();
         *                              block.Values.Add(atRule);
         *
         *                              // reset start with current char
         *                              start = this.Position;
         *                              break;
         *                      }
         *                      case '{':
         *                      {
         *                              // copy anything before
         *                              string value = this.Copy(start);
         *                              if (value != null && !String.IsNullOrEmpty(value = value.Trim()))
         *                              {
         *                                      CssString any = new CssString();
         *                                      any.Value = value;
         *                                      block.Values.Add(any);
         *                              }
         *
         *                              // parse inner block
         *                              CssBlock innerBlock = this.ParseBlock();
         *                              block.Values.Add(innerBlock);
         *
         *                              // reset start with current char
         *                              start = this.Position;
         *                              break;
         *                      }
         *                      case '}':
         *                      {
         *                              // copy anything before
         *                              string value = this.Copy(start);
         *                              if (value != null && !String.IsNullOrEmpty(value = value.Trim()))
         *                              {
         *                                      CssString any = new CssString();
         *                                      any.Value = value;
         *                                      block.Values.Add(any);
         *                              }
         *
         *                              return block;
         *                      }
         *              }
         *      }
         *
         *      throw new UnexpectedEndOfFile("Unclosed block", this.reader.FilePath, this.reader.Line, this.reader.Column);
         * }
         */

        #endregion Block

        #region RuleSet

        /// <summary>
        /// (BNF) ruleset : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
        /// </summary>
        /// <returns></returns>
        private CssRuleSet ParseRuleSet()
        {
            char       ch;
            CssRuleSet ruleSet = new CssRuleSet();

ParseSelectors:
            while (true)
            {
                try
                {
                    CssSelector selector = this.ParseSelector();
                    if (selector == null)
                    {
                        break;
                    }
                    ruleSet.Selectors.Add(selector);
                }
                catch (ParseException ex)
                {
                    this.errors.Add(ex);

                    while (this.Read(out ch))
                    {
                        // restabalize on next rulset
                        switch (ch)
                        {
                        case ',':
                        {
                            // continue parsing rest of Selectors
                            goto ParseSelectors;
                        }

                        case '{':
                        {
                            goto ParseDeclarations;
                        }

                        //case ':':// keep going
                        case ';':
                        case '}':
                        {
                            throw new SyntaxError("Invalid selector list", this.reader.FilePath, this.reader.Line, this.reader.Column);
                        }
                        }
                    }
                }
            }

ParseDeclarations:
            while (true)
            {
                try
                {
                    CssDeclaration declaration = this.ParseDeclaration();
                    if (declaration == null)
                    {
                        break;
                    }
                    ruleSet.Declarations.Add(declaration);
                }
                catch (ParseException ex)
                {
                    this.errors.Add(ex);

                    while (this.Read(out ch))
                    {
                        // restabalize on next declaration
                        switch (ch)
                        {
                        case '{':
                        {
                            throw new SyntaxError("Invalid ruleset", this.reader.FilePath, this.reader.Line, this.reader.Column);
                        }

                        //case ':':// keep going
                        case ';':
                        {
                            // continue parsing rest of delcarations
                            goto ParseDeclarations;
                        }

                        case '}':
                        {
                            // no more declarations
                            return(ruleSet);
                        }
                        }
                    }
                }
            }

            return(ruleSet);
        }
Exemplo n.º 3
0
        /// <summary>
        /// (BNF) declaration : property ':' S* value;
        /// (BNF) property    : IDENT S*;
        /// </summary>
        /// <returns></returns>
        private CssDeclaration ParseDeclaration()
        {
            CssDeclaration declaration = new CssDeclaration();
            char           ch;

            while (this.Read(out ch) && (Char.IsWhiteSpace(ch) || ch == ';'))
            {
                // skip whitespace, and empty declarations
            }

            // consume property name
            switch (ch)
            {
            case '{':
            case ':':
                //case ';':
            {
                throw new SyntaxError("Declaration missing property name", this.reader.FilePath, this.reader.Line, this.reader.Column);
            }

            case '}':
            {
                // no more declarations
                return(null);
            }
            }

            // read property, starting with current char
            int start = this.Position;

            while (this.Read(out ch) && !Char.IsWhiteSpace(ch) && ch != ':')
            {
                // consume property name
                switch (ch)
                {
                case '{':
                //case ':':
                case ';':
                {
                    throw new SyntaxError("Invalid CSS property name: " + this.Copy(start), this.reader.FilePath, this.reader.Line, this.reader.Column);
                }

                case '}':
                {
                    this.PutBack();
                    goto case ';';
                }
                }
            }
            declaration.Property = this.Copy(start);

            if (Char.IsWhiteSpace(ch))
            {
                while (this.Read(out ch) && (Char.IsWhiteSpace(ch)))
                {
                    // skip whitespace
                }
            }

            if (ch != ':')
            {
                // missing the property delim and value

                if (ch == ';' || ch == '}')
                {
                    // these are good chars for resyncing
                    // so put them back on the stream to
                    // not create subsequent errors
                    this.PutBack();
                }
                throw new SyntaxError("Expected <property> : <value>", this.reader.FilePath, this.reader.Line, this.reader.Column);
            }

            CssValueList value = this.ParseValue();

            declaration.Value = value;

            return(declaration);
        }
Exemplo n.º 4
0
        /// <summary>
        /// (BNF) at-rule : ATKEYWORD S* any* [ block | ';' S* ];
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// NOTE: each at-rule might parse differently according to CSS3
        /// The @media block for example contains a block of statements
        /// while other at-rules with a block contain a block of declarations
        /// </remarks>
        private CssAtRule ParseAtRule()
        {
            CssAtRule atRule = new CssAtRule();
            int       start  = this.Position + 1;   // start with first char of ident

            char ch;

            while (this.Read(out ch) && !Char.IsWhiteSpace(ch))
            {
                // continue consuming
            }

            atRule.Ident = this.Copy(start);

            while (this.Read(out ch) && Char.IsWhiteSpace(ch))
            {
                // consuming whitespace
            }

            start = this.Position;            // start with current char
            do
            {
                switch (ch)
                {
                case '{':                         //Block Begin
                {
                    atRule.Value = this.Copy(start);

                    bool containsRuleSets = String.Equals(atRule.Ident, CssAtRule.MediaIdent, StringComparison.Ordinal);
                    while (true)
                    {
                        while (this.Read(out ch) && Char.IsWhiteSpace(ch))
                        {
                            // consume whitespace
                        }

                        if (ch == '}')
                        {
                            break;
                        }

                        try
                        {
                            if (containsRuleSets)
                            {
                                // includes @media
                                CssStatement statement = this.ParseStatement();
                                atRule.Block.Values.Add(statement);
                            }
                            else
                            {
                                // includes @font-face, @page
                                this.PutBack();
                                CssDeclaration declaration = this.ParseDeclaration();
                                atRule.Block.Values.Add(declaration);
                            }
                        }
                        catch (ParseException ex)
                        {
                            this.errors.Add(ex);

                            while (this.Read(out ch) && ch != '}')
                            {
                                // restabilize on block end
                            }
                            break;
                        }
                    }
                    return(atRule);
                }

                case ';':                         //At-Rule End
                {
                    atRule.Value = this.Copy(start);
                    return(atRule);
                }
                }
            } while (this.Read(out ch));

            throw new UnexpectedEndOfFile("Unclosed At-Rule", this.reader.FilePath, this.reader.Line, this.reader.Column);
        }