/// <summary> /// (BNF) value : [ any | block | ATKEYWORD S* ]+; /// (BNF) any : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING /// | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES /// | FUNCTION S* any* ')' | DASHMATCH | '(' S* any* ')' /// | '[' S* any* ']' ] S*; /// </summary> /// <returns></returns> private CssValueList ParseValue() { CssValueList value = new CssValueList(); char ch; while (this.Read(out ch) && Char.IsWhiteSpace(ch)) { // skip whitespace, and empty declarations } switch (ch) { case '{': case ':': case ';': case '}': { throw new SyntaxError("Invalid char in CSS property value: '"+ch+"'", this.reader.FilePath, this.reader.Line, this.reader.Column); } } // read value, starting with current char int start = this.Position; while (this.Read(out ch)) { // consume declaration value switch (ch) { case '{': //case ':':// leave in for "filter: progid:DXImageTransform.Microsoft..." { throw new SyntaxError("Invalid CSS property value: "+this.Copy(start), this.reader.FilePath, this.reader.Line, this.reader.Column); } case '}': case ';': { //Should this parse the value further? CssString any = new CssString(); any.Value = this.Copy(start); value.Values.Add(any); if (ch == '}') { this.PutBack(); } return value; } } } throw new UnexpectedEndOfFile("Unclosed declaration", this.reader.FilePath, this.reader.Line, this.reader.Column); }
/// <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); }