internal Declaration ParseDeclarationBlock(nsParseDeclaration aFlags, nsCSSContextType aContext = nsCSSContextType.General) { bool checkForBraces = (aFlags & nsParseDeclaration.InBraces) != 0; if (checkForBraces) { if (!ExpectSymbol('{', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEBadDeclBlockStart", mToken); }; mReporter.OutputError(); return null; } } Declaration declaration = new Declaration(); mData.AssertInitialState(); if (declaration != null) { for (;;) { bool changed = false; if (!ParseDeclaration(declaration, aFlags, true, ref changed, aContext)) { if (!SkipDeclaration(checkForBraces)) { break; } if (checkForBraces) { if (ExpectSymbol('}', true)) { break; } } // Since the skipped declaration didn't end the block we parse // the next declaration. } } declaration.CompressFrom(mData); } return declaration; }
//---------------------------------------------------------------------- internal bool ParseDeclaration(Declaration aDeclaration, nsParseDeclaration aFlags, bool aMustCallValueAppended, ref bool aChanged, nsCSSContextType aContext = nsCSSContextType.General) { if (!(aContext == nsCSSContextType.General || aContext == nsCSSContextType.Page)) throw new ArgumentException("Must be page or general context"); bool checkForBraces = (aFlags & nsParseDeclaration.InBraces) != 0; mTempData.AssertInitialState(); // Get property name nsCSSToken tk = mToken; string propertyName; for (;;) { if (!GetToken(true)) { if (checkForBraces) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclEndEOF"); }; } return false; } if (nsCSSTokenType.Ident == tk.mType) { propertyName = tk.mIdentStr; // grab the ident before the ExpectSymbol trashes the token if (!ExpectSymbol(':', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEParseDeclarationNoColon", mToken); }; { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclDropped"); }; mReporter.OutputError(); return false; } break; } if (tk.IsSymbol(';')) { // dangling semicolons are skipped continue; } if (!tk.IsSymbol('}')) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEParseDeclarationDeclExpected", mToken); }; { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclSkipped"); }; mReporter.OutputError(); } // Not a declaration... UngetToken(); return false; } // Don't report property parse errors if we're inside a failing @supports // rule. using (/*var suppressErrors = */new nsAutoSuppressErrors(this, mInFailingSupportsRule)) { // Map property name to its ID and then parse the property nsCSSProperty propID = nsCSSProps.LookupProperty(propertyName, nsCSSProps.EnabledState.Enabled); if (nsCSSProperty.Unknown == propID || (aContext == nsCSSContextType.Page && !nsCSSProps.PropHasFlags(propID, nsCSSProps.APPLIES_TO_PAGE_RULE))) { // unknown property if (!NonMozillaVendorIdentifier(propertyName)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEUnknownProperty", propertyName); }; { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclDropped"); }; mReporter.OutputError(); } return false; } if (! ParseProperty(propID)) { // XXX Much better to put stuff in the value parsers instead... { if (!mSuppressErrors) mReporter.ReportUnexpected("PEValueParsingError", propertyName); }; { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclDropped"); }; mReporter.OutputError(); mTempData.ClearProperty(propID); mTempData.AssertInitialState(); return false; } mReporter.ClearError(); // Look for "!important". PriorityParsingStatus status; if ((aFlags & nsParseDeclaration.AllowImportant) != 0) { status = ParsePriority(); } else { status = PriorityParsingStatus.None; } // Look for a semicolon or close brace. if (status != PriorityParsingStatus.Error) { if (!GetToken(true)) { // EOF is always ok } else if (mToken.IsSymbol(';')) { // semicolon is always ok } else if (mToken.IsSymbol('}')) { // brace is ok if checkForBraces, but don't eat it UngetToken(); if (!checkForBraces) { status = PriorityParsingStatus.Error; } } else { UngetToken(); status = PriorityParsingStatus.Error; } } if (status == PriorityParsingStatus.Error) { if (checkForBraces) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEBadDeclOrRuleEnd2", mToken); }; } else { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEBadDeclEnd", mToken); }; } { if (!mSuppressErrors) mReporter.ReportUnexpected("PEDeclDropped"); }; mReporter.OutputError(); mTempData.ClearProperty(propID); mTempData.AssertInitialState(); return false; } aChanged |= mData.TransferFromBlock(mTempData, propID, status == PriorityParsingStatus.Important, false, aMustCallValueAppended, aDeclaration); return true; } }