зеркало из https://github.com/mozilla/gecko-dev.git
Making invalid selectors ignore the following rule in more cases. b=265542 r=bzbarsky sr=dbaron
This commit is contained in:
Родитель
f98dac5a17
Коммит
6a6fc8d7ac
|
@ -179,28 +179,51 @@ protected:
|
||||||
PRBool ParseFontFaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
PRBool ParseFontFaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||||
PRBool ParsePageRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
PRBool ParsePageRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||||
|
|
||||||
void ParseIDSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
enum nsSelectorParsingStatus {
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// we have parsed a selector and we saw a token that cannot be part of a selector:
|
||||||
void ParseClassSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
eSelectorParsingStatus_Done,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// we should continue parsing the selector:
|
||||||
void ParsePseudoSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
eSelectorParsingStatus_Continue,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode,
|
// same as "Done" but we did not find a selector:
|
||||||
PRBool aIsNegated);
|
eSelectorParsingStatus_Empty,
|
||||||
void ParseAttributeSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
// we saw an unexpected token or token value,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// or we saw end-of-file with an unfinished selector:
|
||||||
|
eSelectorParsingStatus_Error
|
||||||
|
};
|
||||||
|
nsSelectorParsingStatus ParseIDSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
void ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
nsSelectorParsingStatus ParseClassSelector(PRInt32& aDataMask,
|
||||||
nsCSSSelector& aSelector,
|
nsCSSSelector& aSelector,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode,
|
nsresult& aErrorCode);
|
||||||
PRBool aIsNegated);
|
|
||||||
void ParseNegatedSimpleSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
nsSelectorParsingStatus ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
nsCSSSelector& aSelector,
|
||||||
void ParseLangSelector(nsCSSSelector& aSelector, PRInt32& aParsingStatus,
|
nsresult& aErrorCode,
|
||||||
nsresult& aErrorCode);
|
PRBool aIsNegated);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode,
|
||||||
|
PRBool aIsNegated);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseLangSelector(nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseSelector(nsresult& aErrorCode,
|
||||||
|
nsCSSSelector& aSelectorResult);
|
||||||
|
|
||||||
PRBool ParseSelectorList(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
PRBool ParseSelectorList(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||||
PRBool ParseSelectorGroup(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
PRBool ParseSelectorGroup(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||||
PRBool ParseSelector(nsresult& aErrorCode, nsCSSSelector& aSelectorResult);
|
|
||||||
nsCSSDeclaration* ParseDeclarationBlock(nsresult& aErrorCode,
|
nsCSSDeclaration* ParseDeclarationBlock(nsresult& aErrorCode,
|
||||||
PRBool aCheckForBraces);
|
PRBool aCheckForBraces);
|
||||||
PRBool ParseDeclaration(nsresult& aErrorCode,
|
PRBool ParseDeclaration(nsresult& aErrorCode,
|
||||||
|
@ -1651,7 +1674,18 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
PRBool done = PR_FALSE;
|
PRBool done = PR_FALSE;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
nsCSSSelector selector;
|
nsCSSSelector selector;
|
||||||
if (! ParseSelector(aErrorCode, selector)) {
|
nsSelectorParsingStatus parsingStatus = ParseSelector(aErrorCode, selector);
|
||||||
|
if (parsingStatus == eSelectorParsingStatus_Empty) {
|
||||||
|
if (!list) {
|
||||||
|
REPORT_UNEXPECTED(PESelectorGroupNoSelector);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parsingStatus == eSelectorParsingStatus_Error) {
|
||||||
|
if (list) {
|
||||||
|
delete list;
|
||||||
|
list = nsnull;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nsnull == list) {
|
if (nsnull == list) {
|
||||||
|
@ -1747,14 +1781,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
weight += selector.CalcWeight();
|
weight += selector.CalcWeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!list) {
|
|
||||||
REPORT_UNEXPECTED(PESelectorGroupNoSelector);
|
|
||||||
}
|
|
||||||
if (PRUnichar(0) != combinator) { // no dangling combinators
|
if (PRUnichar(0) != combinator) { // no dangling combinators
|
||||||
if (list) {
|
if (list) {
|
||||||
delete list;
|
delete list;
|
||||||
|
list = nsnull;
|
||||||
}
|
}
|
||||||
list = nsnull;
|
|
||||||
// This should report the problematic combinator
|
// This should report the problematic combinator
|
||||||
REPORT_UNEXPECTED(PESelectorGroupExtraCombinator);
|
REPORT_UNEXPECTED(PESelectorGroupExtraCombinator);
|
||||||
}
|
}
|
||||||
|
@ -1773,17 +1805,13 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
#define SEL_MASK_PCLASS 0x20
|
#define SEL_MASK_PCLASS 0x20
|
||||||
#define SEL_MASK_PELEM 0x40
|
#define SEL_MASK_PELEM 0x40
|
||||||
|
|
||||||
#define SELECTOR_PARSING_ENDED_OK 1
|
|
||||||
#define SELECTOR_PARSING_STOPPED_OK 2
|
|
||||||
#define SELECTOR_PARSING_STOPPED_ERROR 3
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parses an ID selector #name
|
// Parses an ID selector #name
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
if (!mToken.mIdent.IsEmpty()) { // verify is legal ID
|
if (!mToken.mIdent.IsEmpty()) { // verify is legal ID
|
||||||
PRUnichar first = mToken.mIdent.First();
|
PRUnichar first = mToken.mIdent.First();
|
||||||
|
@ -1795,8 +1823,7 @@ void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
nsCSSScanner::GetLexTable())) {
|
nsCSSScanner::GetLexTable())) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEIDSelNotIdent);
|
REPORT_UNEXPECTED_TOKEN(PEIDSelNotIdent);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aDataMask |= SEL_MASK_ID;
|
aDataMask |= SEL_MASK_ID;
|
||||||
aSelector.AddID(mToken.mIdent);
|
aSelector.AddID(mToken.mIdent);
|
||||||
|
@ -1804,47 +1831,44 @@ void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEIDSelEmpty);
|
REPORT_UNEXPECTED_TOKEN(PEIDSelEmpty);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parses a class selector .name
|
// Parses a class selector .name
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
|
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
|
||||||
REPORT_UNEXPECTED_EOF(PEClassSelEOF);
|
REPORT_UNEXPECTED_EOF(PEClassSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident != mToken.mType) { // malformed selector
|
if (eCSSToken_Ident != mToken.mType) { // malformed selector
|
||||||
REPORT_UNEXPECTED_TOKEN(PEClassSelNotIdent);
|
REPORT_UNEXPECTED_TOKEN(PEClassSelNotIdent);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aDataMask |= SEL_MASK_CLASS;
|
aDataMask |= SEL_MASK_CLASS;
|
||||||
|
|
||||||
aSelector.AddClass(mToken.mIdent);
|
aSelector.AddClass(mToken.mIdent);
|
||||||
|
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse a type element selector or a universal selector
|
// Parse a type element selector or a universal selector
|
||||||
// namespace|type or namespace|* or *|* or *
|
// namespace|type or namespace|* or *|* or *
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode,
|
nsresult& aErrorCode,
|
||||||
PRBool aIsNegated)
|
PRBool aIsNegated)
|
||||||
{
|
{
|
||||||
nsAutoString buffer;
|
nsAutoString buffer;
|
||||||
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
|
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
|
||||||
|
@ -1854,8 +1878,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1874,8 +1897,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // was universal element selector
|
else { // was universal element selector
|
||||||
|
@ -1893,8 +1915,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
// don't set any tag in the selector
|
// don't set any tag in the selector
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eCSSToken_Ident == mToken.mType) { // element name or namespace name
|
else if (eCSSToken_Ident == mToken.mType) { // element name or namespace name
|
||||||
|
@ -1913,15 +1934,13 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
buffer.get()
|
buffer.get()
|
||||||
};
|
};
|
||||||
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aSelector.SetNameSpace(nameSpaceID);
|
aSelector.SetNameSpace(nameSpaceID);
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1940,8 +1959,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // was element name
|
else { // was element name
|
||||||
|
@ -1965,8 +1983,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('|')) { // No namespace
|
else if (mToken.IsSymbol('|')) { // No namespace
|
||||||
|
@ -1976,8 +1993,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
// get mandatory tag
|
// get mandatory tag
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1996,12 +2012,10 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2019,26 +2033,25 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
|
||||||
if (aIsNegated) {
|
if (aIsNegated) {
|
||||||
// restore last token read in case of a negated type selector
|
// restore last token read in case of a negated type selector
|
||||||
UngetToken();
|
UngetToken();
|
||||||
}
|
}
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse attribute selectors [attr], [attr=value], [attr|=value],
|
// Parse attribute selectors [attr], [attr=value], [attr|=value],
|
||||||
// [attr~=value], [attr^=value], [attr$=value] and [attr*=value]
|
// [attr~=value], [attr^=value], [attr$=value] and [attr*=value]
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
|
CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
nsCSSSelector& aSelector,
|
nsCSSSelector& aSelector,
|
||||||
PRInt32& aParsingStatus,
|
nsresult& aErrorCode)
|
||||||
nsresult& aErrorCode)
|
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 nameSpaceID = kNameSpaceID_None;
|
PRInt32 nameSpaceID = kNameSpaceID_None;
|
||||||
|
@ -2048,8 +2061,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
|
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2057,21 +2069,18 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelNoBar);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelNoBar);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('|')) { // NO namespace
|
else if (mToken.IsSymbol('|')) { // NO namespace
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2079,8 +2088,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eCSSToken_Ident == mToken.mType) { // attr name or namespace
|
else if (eCSSToken_Ident == mToken.mType) { // attr name or namespace
|
||||||
|
@ -2097,13 +2105,11 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
attr.get()
|
attr.get()
|
||||||
};
|
};
|
||||||
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2111,16 +2117,14 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // malformed
|
else { // malformed
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameOrNamespaceExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameOrNamespaceExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! mCaseSensitive) {
|
if (! mCaseSensitive) {
|
||||||
|
@ -2128,8 +2132,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelInnerEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelInnerEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if ((eCSSToken_Symbol == mToken.mType) ||
|
if ((eCSSToken_Symbol == mToken.mType) ||
|
||||||
(eCSSToken_Includes == mToken.mType) ||
|
(eCSSToken_Includes == mToken.mType) ||
|
||||||
|
@ -2164,21 +2167,18 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
||||||
UngetToken(); // bad function
|
UngetToken(); // bad function
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (NS_ATTR_FUNC_SET != func) { // get value
|
if (NS_ATTR_FUNC_SET != func) { // get value
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelValueEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelValueEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
|
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
|
||||||
nsAutoString value(mToken.mIdent);
|
nsAutoString value(mToken.mIdent);
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelCloseEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelCloseEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (mToken.IsSymbol(']')) {
|
if (mToken.IsSymbol(']')) {
|
||||||
PRBool isCaseSensitive = mCaseSensitive;
|
PRBool isCaseSensitive = mCaseSensitive;
|
||||||
|
@ -2207,40 +2207,36 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelNoClose);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelNoClose);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelBadValue);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelBadValue);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
||||||
UngetToken(); // bad dog, no biscut!
|
UngetToken(); // bad dog, no biscut!
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse pseudo-classes and pseudo-elements
|
// Parse pseudo-classes and pseudo-elements
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode,
|
nsresult& aErrorCode,
|
||||||
PRBool aIsNegated)
|
PRBool aIsNegated)
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, find out whether we are parsing a CSS3 pseudo-element
|
// First, find out whether we are parsing a CSS3 pseudo-element
|
||||||
|
@ -2249,8 +2245,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
parsingPseudoElement = PR_TRUE;
|
parsingPseudoElement = PR_TRUE;
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2259,8 +2254,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
// malformed selector
|
// malformed selector
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelBadName);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelBadName);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, now we know we have an mIdent. Atomize it. All the atoms, for
|
// OK, now we know we have an mIdent. Atomize it. All the atoms, for
|
||||||
|
@ -2297,8 +2291,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
nsCSSPseudoClasses::lang == pseudo)) { // There are no other function pseudos
|
nsCSSPseudoClasses::lang == pseudo)) { // There are no other function pseudos
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it starts with "::", it better be a pseudo-element
|
// If it starts with "::", it better be a pseudo-element
|
||||||
|
@ -2307,36 +2300,35 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
!isAnonBox) {
|
!isAnonBox) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsCSSPseudoClasses::notPseudo == pseudo) {
|
if (nsCSSPseudoClasses::notPseudo == pseudo) {
|
||||||
if (aIsNegated) { // :not() can't be itself negated
|
if (aIsNegated) { // :not() can't be itself negated
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// CSS 3 Negation pseudo-class takes one simple selector as argument
|
// CSS 3 Negation pseudo-class takes one simple selector as argument
|
||||||
ParseNegatedSimpleSelector(aDataMask, aSelector, aParsingStatus, aErrorCode);
|
nsSelectorParsingStatus parsingStatus =
|
||||||
if (SELECTOR_PARSING_ENDED_OK != aParsingStatus) {
|
ParseNegatedSimpleSelector(aDataMask, aSelector, aErrorCode);
|
||||||
return;
|
if (eSelectorParsingStatus_Continue != parsingStatus) {
|
||||||
|
return parsingStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!parsingPseudoElement &&
|
else if (!parsingPseudoElement &&
|
||||||
nsCSSPseudoClasses::IsPseudoClass(pseudo)) {
|
nsCSSPseudoClasses::IsPseudoClass(pseudo)) {
|
||||||
aDataMask |= SEL_MASK_PCLASS;
|
aDataMask |= SEL_MASK_PCLASS;
|
||||||
if (nsCSSPseudoClasses::lang == pseudo) {
|
if (nsCSSPseudoClasses::lang == pseudo) {
|
||||||
ParseLangSelector(aSelector, aParsingStatus, aErrorCode);
|
nsSelectorParsingStatus parsingStatus = ParseLangSelector(aSelector, aErrorCode);
|
||||||
|
if (eSelectorParsingStatus_Continue != parsingStatus) {
|
||||||
|
return parsingStatus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// XXX are there more pseudo classes which accept arguments ?
|
// XXX are there more pseudo classes which accept arguments ?
|
||||||
else {
|
else {
|
||||||
aSelector.AddPseudoClass(pseudo);
|
aSelector.AddPseudoClass(pseudo);
|
||||||
}
|
}
|
||||||
if (SELECTOR_PARSING_ENDED_OK != aParsingStatus) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (isPseudoElement || isAnonBox) {
|
else if (isPseudoElement || isAnonBox) {
|
||||||
// Pseudo-element. Make some more sanity checks.
|
// Pseudo-element. Make some more sanity checks.
|
||||||
|
@ -2344,8 +2336,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
if (aIsNegated) { // pseudo-elements can't be negated
|
if (aIsNegated) { // pseudo-elements can't be negated
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// CSS2 pseudo-elements and -moz-tree-* pseudo-elements are allowed
|
// CSS2 pseudo-elements and -moz-tree-* pseudo-elements are allowed
|
||||||
// to have a single ':' on them. Others (CSS3+ pseudo-elements and
|
// to have a single ':' on them. Others (CSS3+ pseudo-elements and
|
||||||
|
@ -2359,8 +2350,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
) {
|
) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == (aDataMask & SEL_MASK_PELEM)) {
|
if (0 == (aDataMask & SEL_MASK_PELEM)) {
|
||||||
|
@ -2374,8 +2364,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
// item in the list to the pseudoclass list. They will be pulled
|
// item in the list to the pseudoclass list. They will be pulled
|
||||||
// from the list later along with the pseudo-element.
|
// from the list later along with the pseudo-element.
|
||||||
if (!ParseTreePseudoElement(aErrorCode, aSelector)) {
|
if (!ParseTreePseudoElement(aErrorCode, aSelector)) {
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2385,194 +2374,178 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
if ((eCSSToken_WhiteSpace == mToken.mType) ||
|
if ((eCSSToken_WhiteSpace == mToken.mType) ||
|
||||||
(mToken.IsSymbol('{') || mToken.IsSymbol(','))) {
|
(mToken.IsSymbol('{') || mToken.IsSymbol(','))) {
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelTrailing);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelTrailing);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // multiple pseudo elements, not legal
|
else { // multiple pseudo elements, not legal
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelMultiplePE);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelMultiplePE);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a pseudo-class, not a pseudo-element.... forget it
|
// Not a pseudo-class, not a pseudo-element.... forget it
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the argument of a negation pseudo-class :not()
|
// Parse the argument of a negation pseudo-class :not()
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
// Check if we have the first parenthesis
|
// Check if we have the first parenthesis
|
||||||
if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
if (!ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationBadArg);
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
return eSelectorParsingStatus_Error;
|
||||||
REPORT_UNEXPECTED_EOF(PENegationEOF);
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
}
|
REPORT_UNEXPECTED_EOF(PENegationEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
if (!aSelector.mNegations) {
|
||||||
|
aSelector.mNegations = new nsCSSSelector();
|
||||||
if (!aSelector.mNegations) {
|
if (!aSelector.mNegations) {
|
||||||
aSelector.mNegations = new nsCSSSelector();
|
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||||
if (!aSelector.mNegations) {
|
return eSelectorParsingStatus_Error;
|
||||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ID, class and attribute selectors and pseudo-classes are stored in
|
|
||||||
// the first mNegations attached to a selector
|
|
||||||
if (eCSSToken_ID == mToken.mType) { // #id
|
|
||||||
ParseIDSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol('.')) { // .class
|
|
||||||
ParseClassSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol(':')) { // :pseudo
|
|
||||||
ParsePseudoSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode, PR_TRUE);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol('[')) { // attribute
|
|
||||||
ParseAttributeSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// then it should be a type element or universal selector
|
|
||||||
nsCSSSelector *newSel = new nsCSSSelector();
|
|
||||||
if (!newSel) {
|
|
||||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nsCSSSelector* negations = aSelector.mNegations;
|
|
||||||
while (nsnull != negations->mNegations) {
|
|
||||||
negations = negations->mNegations;
|
|
||||||
}
|
|
||||||
// negated type element selectors and universal selectors are stored after the first
|
|
||||||
// mNegations containing only negated IDs, classes, attributes and pseudo-classes
|
|
||||||
negations->mNegations = newSel;
|
|
||||||
ParseTypeOrUniversalSelector(aDataMask, *newSel, aParsingStatus, aErrorCode, PR_TRUE);
|
|
||||||
}
|
|
||||||
if (SELECTOR_PARSING_STOPPED_ERROR == aParsingStatus) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationBadInner);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// close the parenthesis
|
|
||||||
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationNoClose);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ID, class and attribute selectors and pseudo-classes are stored in
|
||||||
|
// the first mNegations attached to a selector
|
||||||
|
nsSelectorParsingStatus parsingStatus;
|
||||||
|
if (eCSSToken_ID == mToken.mType) { // #id
|
||||||
|
parsingStatus = ParseIDSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol('.')) { // .class
|
||||||
|
parsingStatus = ParseClassSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol(':')) { // :pseudo
|
||||||
|
parsingStatus = ParsePseudoSelector(aDataMask, *aSelector.mNegations, aErrorCode, PR_TRUE);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol('[')) { // [attribute
|
||||||
|
parsingStatus = ParseAttributeSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationBadArg);
|
// then it should be a type element or universal selector
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
nsCSSSelector *newSel = new nsCSSSelector();
|
||||||
|
if (!newSel) {
|
||||||
|
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
nsCSSSelector* negations = aSelector.mNegations;
|
||||||
|
while (nsnull != negations->mNegations) {
|
||||||
|
negations = negations->mNegations;
|
||||||
|
}
|
||||||
|
// negated type element selectors and universal selectors are stored after the first
|
||||||
|
// mNegations containing only negated IDs, classes, attributes and pseudo-classes
|
||||||
|
negations->mNegations = newSel;
|
||||||
|
parsingStatus = ParseTypeOrUniversalSelector(aDataMask, *newSel, aErrorCode, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
if (eSelectorParsingStatus_Error == parsingStatus) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationBadInner);
|
||||||
|
return parsingStatus;
|
||||||
|
}
|
||||||
|
// close the parenthesis
|
||||||
|
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationNoClose);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the argument of a pseudo-class :lang()
|
// Parse the argument of a pseudo-class :lang()
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseLangSelector(nsCSSSelector& aSelector,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
PRInt32& aParsingStatus,
|
CSSParserImpl::ParseLangSelector(nsCSSSelector& aSelector, nsresult& aErrorCode)
|
||||||
nsresult& aErrorCode)
|
|
||||||
{
|
{
|
||||||
// Check if we have the first parenthesis
|
// Check if we have the first parenthesis
|
||||||
if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
if (!ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature eof
|
|
||||||
REPORT_UNEXPECTED_EOF(PELangArgEOF);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We expect an identifier with a language abbreviation
|
|
||||||
if (eCSSToken_Ident != mToken.mType) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangArgNotIdent);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the pseudo with the language parameter
|
|
||||||
aSelector.AddPseudoClass(nsCSSPseudoClasses::lang, mToken.mIdent.get());
|
|
||||||
|
|
||||||
// close the parenthesis
|
|
||||||
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangNoClose);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangNoArg);
|
REPORT_UNEXPECTED_TOKEN(PELangNoArg);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature eof
|
||||||
|
REPORT_UNEXPECTED_EOF(PELangArgEOF);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
// We expect an identifier with a language abbreviation
|
||||||
|
if (eCSSToken_Ident != mToken.mType) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PELangArgNotIdent);
|
||||||
|
UngetToken();
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the pseudo with the language parameter
|
||||||
|
aSelector.AddPseudoClass(nsCSSPseudoClasses::lang, mToken.mIdent.get());
|
||||||
|
|
||||||
|
// close the parenthesis
|
||||||
|
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PELangNoClose);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the format for selectors:
|
* This is the format for selectors:
|
||||||
* operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
|
* operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
|
||||||
*/
|
*/
|
||||||
PRBool CSSParserImpl::ParseSelector(nsresult& aErrorCode,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector)
|
CSSParserImpl::ParseSelector(nsresult& aErrorCode, nsCSSSelector& aSelector)
|
||||||
{
|
{
|
||||||
PRInt32 dataMask = 0;
|
|
||||||
PRInt32 parsingStatus = SELECTOR_PARSING_ENDED_OK;
|
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) {
|
if (! GetToken(aErrorCode, PR_TRUE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PESelectorEOF);
|
REPORT_UNEXPECTED_EOF(PESelectorEOF);
|
||||||
return PR_FALSE;
|
return eSelectorParsingStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseTypeOrUniversalSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);
|
PRInt32 dataMask = 0;
|
||||||
if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {
|
nsSelectorParsingStatus parsingStatus =
|
||||||
return PR_TRUE;
|
ParseTypeOrUniversalSelector(dataMask, aSelector, aErrorCode, PR_FALSE);
|
||||||
}
|
if (parsingStatus != eSelectorParsingStatus_Continue) {
|
||||||
else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {
|
return parsingStatus;
|
||||||
return PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
parsingStatus = SELECTOR_PARSING_ENDED_OK;
|
if (eCSSToken_ID == mToken.mType) { // #id
|
||||||
if (eCSSToken_ID == mToken.mType) { // #id
|
parsingStatus = ParseIDSelector(dataMask, aSelector, aErrorCode);
|
||||||
ParseIDSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('.')) { // .class
|
else if (mToken.IsSymbol('.')) { // .class
|
||||||
ParseClassSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
parsingStatus = ParseClassSelector(dataMask, aSelector, aErrorCode);
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol(':')) { // :pseudo
|
else if (mToken.IsSymbol(':')) { // :pseudo
|
||||||
ParsePseudoSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);
|
parsingStatus = ParsePseudoSelector(dataMask, aSelector, aErrorCode, PR_FALSE);
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('[')) { // attribute
|
else if (mToken.IsSymbol('[')) { // [attribute
|
||||||
ParseAttributeSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
parsingStatus = ParseAttributeSelector(dataMask, aSelector, aErrorCode);
|
||||||
}
|
}
|
||||||
else { // not a selector token, we're done
|
else { // not a selector token, we're done
|
||||||
|
parsingStatus = eSelectorParsingStatus_Done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {
|
if (parsingStatus != eSelectorParsingStatus_Continue) {
|
||||||
return PR_TRUE;
|
return parsingStatus;
|
||||||
}
|
}
|
||||||
else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
return PR_TRUE;
|
return eSelectorParsingStatus_Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UngetToken();
|
UngetToken();
|
||||||
return PRBool(0 != dataMask);
|
return dataMask ? parsingStatus : eSelectorParsingStatus_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSDeclaration*
|
nsCSSDeclaration*
|
||||||
|
|
|
@ -179,28 +179,51 @@ protected:
|
||||||
PRBool ParseFontFaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
PRBool ParseFontFaceRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||||
PRBool ParsePageRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
PRBool ParsePageRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||||
|
|
||||||
void ParseIDSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
enum nsSelectorParsingStatus {
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// we have parsed a selector and we saw a token that cannot be part of a selector:
|
||||||
void ParseClassSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
eSelectorParsingStatus_Done,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// we should continue parsing the selector:
|
||||||
void ParsePseudoSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
eSelectorParsingStatus_Continue,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode,
|
// same as "Done" but we did not find a selector:
|
||||||
PRBool aIsNegated);
|
eSelectorParsingStatus_Empty,
|
||||||
void ParseAttributeSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
// we saw an unexpected token or token value,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
// or we saw end-of-file with an unfinished selector:
|
||||||
|
eSelectorParsingStatus_Error
|
||||||
|
};
|
||||||
|
nsSelectorParsingStatus ParseIDSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
void ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
nsSelectorParsingStatus ParseClassSelector(PRInt32& aDataMask,
|
||||||
nsCSSSelector& aSelector,
|
nsCSSSelector& aSelector,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode,
|
nsresult& aErrorCode);
|
||||||
PRBool aIsNegated);
|
|
||||||
void ParseNegatedSimpleSelector(PRInt32& aDataMask, nsCSSSelector& aSelector,
|
nsSelectorParsingStatus ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus, nsresult& aErrorCode);
|
nsCSSSelector& aSelector,
|
||||||
void ParseLangSelector(nsCSSSelector& aSelector, PRInt32& aParsingStatus,
|
nsresult& aErrorCode,
|
||||||
nsresult& aErrorCode);
|
PRBool aIsNegated);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode,
|
||||||
|
PRBool aIsNegated);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseLangSelector(nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
||||||
|
nsCSSSelector& aSelector,
|
||||||
|
nsresult& aErrorCode);
|
||||||
|
|
||||||
|
nsSelectorParsingStatus ParseSelector(nsresult& aErrorCode,
|
||||||
|
nsCSSSelector& aSelectorResult);
|
||||||
|
|
||||||
PRBool ParseSelectorList(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
PRBool ParseSelectorList(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||||
PRBool ParseSelectorGroup(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
PRBool ParseSelectorGroup(nsresult& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||||
PRBool ParseSelector(nsresult& aErrorCode, nsCSSSelector& aSelectorResult);
|
|
||||||
nsCSSDeclaration* ParseDeclarationBlock(nsresult& aErrorCode,
|
nsCSSDeclaration* ParseDeclarationBlock(nsresult& aErrorCode,
|
||||||
PRBool aCheckForBraces);
|
PRBool aCheckForBraces);
|
||||||
PRBool ParseDeclaration(nsresult& aErrorCode,
|
PRBool ParseDeclaration(nsresult& aErrorCode,
|
||||||
|
@ -1651,7 +1674,18 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
PRBool done = PR_FALSE;
|
PRBool done = PR_FALSE;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
nsCSSSelector selector;
|
nsCSSSelector selector;
|
||||||
if (! ParseSelector(aErrorCode, selector)) {
|
nsSelectorParsingStatus parsingStatus = ParseSelector(aErrorCode, selector);
|
||||||
|
if (parsingStatus == eSelectorParsingStatus_Empty) {
|
||||||
|
if (!list) {
|
||||||
|
REPORT_UNEXPECTED(PESelectorGroupNoSelector);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parsingStatus == eSelectorParsingStatus_Error) {
|
||||||
|
if (list) {
|
||||||
|
delete list;
|
||||||
|
list = nsnull;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nsnull == list) {
|
if (nsnull == list) {
|
||||||
|
@ -1747,14 +1781,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
weight += selector.CalcWeight();
|
weight += selector.CalcWeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!list) {
|
|
||||||
REPORT_UNEXPECTED(PESelectorGroupNoSelector);
|
|
||||||
}
|
|
||||||
if (PRUnichar(0) != combinator) { // no dangling combinators
|
if (PRUnichar(0) != combinator) { // no dangling combinators
|
||||||
if (list) {
|
if (list) {
|
||||||
delete list;
|
delete list;
|
||||||
|
list = nsnull;
|
||||||
}
|
}
|
||||||
list = nsnull;
|
|
||||||
// This should report the problematic combinator
|
// This should report the problematic combinator
|
||||||
REPORT_UNEXPECTED(PESelectorGroupExtraCombinator);
|
REPORT_UNEXPECTED(PESelectorGroupExtraCombinator);
|
||||||
}
|
}
|
||||||
|
@ -1773,17 +1805,13 @@ PRBool CSSParserImpl::ParseSelectorGroup(nsresult& aErrorCode,
|
||||||
#define SEL_MASK_PCLASS 0x20
|
#define SEL_MASK_PCLASS 0x20
|
||||||
#define SEL_MASK_PELEM 0x40
|
#define SEL_MASK_PELEM 0x40
|
||||||
|
|
||||||
#define SELECTOR_PARSING_ENDED_OK 1
|
|
||||||
#define SELECTOR_PARSING_STOPPED_OK 2
|
|
||||||
#define SELECTOR_PARSING_STOPPED_ERROR 3
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parses an ID selector #name
|
// Parses an ID selector #name
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
if (!mToken.mIdent.IsEmpty()) { // verify is legal ID
|
if (!mToken.mIdent.IsEmpty()) { // verify is legal ID
|
||||||
PRUnichar first = mToken.mIdent.First();
|
PRUnichar first = mToken.mIdent.First();
|
||||||
|
@ -1795,8 +1823,7 @@ void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
nsCSSScanner::GetLexTable())) {
|
nsCSSScanner::GetLexTable())) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEIDSelNotIdent);
|
REPORT_UNEXPECTED_TOKEN(PEIDSelNotIdent);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aDataMask |= SEL_MASK_ID;
|
aDataMask |= SEL_MASK_ID;
|
||||||
aSelector.AddID(mToken.mIdent);
|
aSelector.AddID(mToken.mIdent);
|
||||||
|
@ -1804,47 +1831,44 @@ void CSSParserImpl::ParseIDSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEIDSelEmpty);
|
REPORT_UNEXPECTED_TOKEN(PEIDSelEmpty);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parses a class selector .name
|
// Parses a class selector .name
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
|
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
|
||||||
REPORT_UNEXPECTED_EOF(PEClassSelEOF);
|
REPORT_UNEXPECTED_EOF(PEClassSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident != mToken.mType) { // malformed selector
|
if (eCSSToken_Ident != mToken.mType) { // malformed selector
|
||||||
REPORT_UNEXPECTED_TOKEN(PEClassSelNotIdent);
|
REPORT_UNEXPECTED_TOKEN(PEClassSelNotIdent);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aDataMask |= SEL_MASK_CLASS;
|
aDataMask |= SEL_MASK_CLASS;
|
||||||
|
|
||||||
aSelector.AddClass(mToken.mIdent);
|
aSelector.AddClass(mToken.mIdent);
|
||||||
|
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse a type element selector or a universal selector
|
// Parse a type element selector or a universal selector
|
||||||
// namespace|type or namespace|* or *|* or *
|
// namespace|type or namespace|* or *|* or *
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode,
|
nsresult& aErrorCode,
|
||||||
PRBool aIsNegated)
|
PRBool aIsNegated)
|
||||||
{
|
{
|
||||||
nsAutoString buffer;
|
nsAutoString buffer;
|
||||||
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
|
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
|
||||||
|
@ -1854,8 +1878,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1874,8 +1897,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // was universal element selector
|
else { // was universal element selector
|
||||||
|
@ -1893,8 +1915,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
// don't set any tag in the selector
|
// don't set any tag in the selector
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eCSSToken_Ident == mToken.mType) { // element name or namespace name
|
else if (eCSSToken_Ident == mToken.mType) { // element name or namespace name
|
||||||
|
@ -1913,15 +1934,13 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
buffer.get()
|
buffer.get()
|
||||||
};
|
};
|
||||||
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aSelector.SetNameSpace(nameSpaceID);
|
aSelector.SetNameSpace(nameSpaceID);
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1940,8 +1959,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // was element name
|
else { // was element name
|
||||||
|
@ -1965,8 +1983,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('|')) { // No namespace
|
else if (mToken.IsSymbol('|')) { // No namespace
|
||||||
|
@ -1976,8 +1993,7 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
// get mandatory tag
|
// get mandatory tag
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) {
|
if (! GetToken(aErrorCode, PR_FALSE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
REPORT_UNEXPECTED_EOF(PETypeSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // element name
|
if (eCSSToken_Ident == mToken.mType) { // element name
|
||||||
aDataMask |= SEL_MASK_ELEM;
|
aDataMask |= SEL_MASK_ELEM;
|
||||||
|
@ -1996,12 +2012,10 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
REPORT_UNEXPECTED_TOKEN(PETypeSelNotType);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2019,26 +2033,25 @@ void CSSParserImpl::ParseTypeOrUniversalSelector(PRInt32& aDataMask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
|
||||||
if (aIsNegated) {
|
if (aIsNegated) {
|
||||||
// restore last token read in case of a negated type selector
|
// restore last token read in case of a negated type selector
|
||||||
UngetToken();
|
UngetToken();
|
||||||
}
|
}
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse attribute selectors [attr], [attr=value], [attr|=value],
|
// Parse attribute selectors [attr], [attr=value], [attr|=value],
|
||||||
// [attr~=value], [attr^=value], [attr$=value] and [attr*=value]
|
// [attr~=value], [attr^=value], [attr$=value] and [attr*=value]
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
|
CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
nsCSSSelector& aSelector,
|
nsCSSSelector& aSelector,
|
||||||
PRInt32& aParsingStatus,
|
nsresult& aErrorCode)
|
||||||
nsresult& aErrorCode)
|
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 nameSpaceID = kNameSpaceID_None;
|
PRInt32 nameSpaceID = kNameSpaceID_None;
|
||||||
|
@ -2048,8 +2061,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
|
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2057,21 +2069,18 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelNoBar);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelNoBar);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('|')) { // NO namespace
|
else if (mToken.IsSymbol('|')) { // NO namespace
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2079,8 +2088,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eCSSToken_Ident == mToken.mType) { // attr name or namespace
|
else if (eCSSToken_Ident == mToken.mType) { // attr name or namespace
|
||||||
|
@ -2097,13 +2105,11 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
attr.get()
|
attr.get()
|
||||||
};
|
};
|
||||||
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
REPORT_UNEXPECTED_P(PEUnknownNamespacePrefix, params);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
REPORT_UNEXPECTED_EOF(PEAttributeNameEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (eCSSToken_Ident == mToken.mType) { // attr name
|
if (eCSSToken_Ident == mToken.mType) { // attr name
|
||||||
attr = mToken.mIdent;
|
attr = mToken.mIdent;
|
||||||
|
@ -2111,16 +2117,14 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // malformed
|
else { // malformed
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttributeNameOrNamespaceExpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttributeNameOrNamespaceExpected);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! mCaseSensitive) {
|
if (! mCaseSensitive) {
|
||||||
|
@ -2128,8 +2132,7 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
}
|
}
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelInnerEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelInnerEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if ((eCSSToken_Symbol == mToken.mType) ||
|
if ((eCSSToken_Symbol == mToken.mType) ||
|
||||||
(eCSSToken_Includes == mToken.mType) ||
|
(eCSSToken_Includes == mToken.mType) ||
|
||||||
|
@ -2164,21 +2167,18 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
||||||
UngetToken(); // bad function
|
UngetToken(); // bad function
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (NS_ATTR_FUNC_SET != func) { // get value
|
if (NS_ATTR_FUNC_SET != func) { // get value
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelValueEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelValueEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
|
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
|
||||||
nsAutoString value(mToken.mIdent);
|
nsAutoString value(mToken.mIdent);
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
|
||||||
REPORT_UNEXPECTED_EOF(PEAttSelCloseEOF);
|
REPORT_UNEXPECTED_EOF(PEAttSelCloseEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (mToken.IsSymbol(']')) {
|
if (mToken.IsSymbol(']')) {
|
||||||
PRBool isCaseSensitive = mCaseSensitive;
|
PRBool isCaseSensitive = mCaseSensitive;
|
||||||
|
@ -2207,40 +2207,36 @@ void CSSParserImpl::ParseAttributeSelector(PRInt32& aDataMask,
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelNoClose);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelNoClose);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelBadValue);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelBadValue);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
REPORT_UNEXPECTED_TOKEN(PEAttSelUnexpected);
|
||||||
UngetToken(); // bad dog, no biscut!
|
UngetToken(); // bad dog, no biscut!
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse pseudo-classes and pseudo-elements
|
// Parse pseudo-classes and pseudo-elements
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode,
|
nsresult& aErrorCode,
|
||||||
PRBool aIsNegated)
|
PRBool aIsNegated)
|
||||||
{
|
{
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, find out whether we are parsing a CSS3 pseudo-element
|
// First, find out whether we are parsing a CSS3 pseudo-element
|
||||||
|
@ -2249,8 +2245,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
parsingPseudoElement = PR_TRUE;
|
parsingPseudoElement = PR_TRUE;
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2259,8 +2254,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
// malformed selector
|
// malformed selector
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelBadName);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelBadName);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, now we know we have an mIdent. Atomize it. All the atoms, for
|
// OK, now we know we have an mIdent. Atomize it. All the atoms, for
|
||||||
|
@ -2297,8 +2291,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
nsCSSPseudoClasses::lang == pseudo)) { // There are no other function pseudos
|
nsCSSPseudoClasses::lang == pseudo)) { // There are no other function pseudos
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it starts with "::", it better be a pseudo-element
|
// If it starts with "::", it better be a pseudo-element
|
||||||
|
@ -2307,36 +2300,35 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
!isAnonBox) {
|
!isAnonBox) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsCSSPseudoClasses::notPseudo == pseudo) {
|
if (nsCSSPseudoClasses::notPseudo == pseudo) {
|
||||||
if (aIsNegated) { // :not() can't be itself negated
|
if (aIsNegated) { // :not() can't be itself negated
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// CSS 3 Negation pseudo-class takes one simple selector as argument
|
// CSS 3 Negation pseudo-class takes one simple selector as argument
|
||||||
ParseNegatedSimpleSelector(aDataMask, aSelector, aParsingStatus, aErrorCode);
|
nsSelectorParsingStatus parsingStatus =
|
||||||
if (SELECTOR_PARSING_ENDED_OK != aParsingStatus) {
|
ParseNegatedSimpleSelector(aDataMask, aSelector, aErrorCode);
|
||||||
return;
|
if (eSelectorParsingStatus_Continue != parsingStatus) {
|
||||||
|
return parsingStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!parsingPseudoElement &&
|
else if (!parsingPseudoElement &&
|
||||||
nsCSSPseudoClasses::IsPseudoClass(pseudo)) {
|
nsCSSPseudoClasses::IsPseudoClass(pseudo)) {
|
||||||
aDataMask |= SEL_MASK_PCLASS;
|
aDataMask |= SEL_MASK_PCLASS;
|
||||||
if (nsCSSPseudoClasses::lang == pseudo) {
|
if (nsCSSPseudoClasses::lang == pseudo) {
|
||||||
ParseLangSelector(aSelector, aParsingStatus, aErrorCode);
|
nsSelectorParsingStatus parsingStatus = ParseLangSelector(aSelector, aErrorCode);
|
||||||
|
if (eSelectorParsingStatus_Continue != parsingStatus) {
|
||||||
|
return parsingStatus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// XXX are there more pseudo classes which accept arguments ?
|
// XXX are there more pseudo classes which accept arguments ?
|
||||||
else {
|
else {
|
||||||
aSelector.AddPseudoClass(pseudo);
|
aSelector.AddPseudoClass(pseudo);
|
||||||
}
|
}
|
||||||
if (SELECTOR_PARSING_ENDED_OK != aParsingStatus) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (isPseudoElement || isAnonBox) {
|
else if (isPseudoElement || isAnonBox) {
|
||||||
// Pseudo-element. Make some more sanity checks.
|
// Pseudo-element. Make some more sanity checks.
|
||||||
|
@ -2344,8 +2336,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
if (aIsNegated) { // pseudo-elements can't be negated
|
if (aIsNegated) { // pseudo-elements can't be negated
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// CSS2 pseudo-elements and -moz-tree-* pseudo-elements are allowed
|
// CSS2 pseudo-elements and -moz-tree-* pseudo-elements are allowed
|
||||||
// to have a single ':' on them. Others (CSS3+ pseudo-elements and
|
// to have a single ':' on them. Others (CSS3+ pseudo-elements and
|
||||||
|
@ -2359,8 +2350,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
) {
|
) {
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == (aDataMask & SEL_MASK_PELEM)) {
|
if (0 == (aDataMask & SEL_MASK_PELEM)) {
|
||||||
|
@ -2374,8 +2364,7 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
// item in the list to the pseudoclass list. They will be pulled
|
// item in the list to the pseudoclass list. They will be pulled
|
||||||
// from the list later along with the pseudo-element.
|
// from the list later along with the pseudo-element.
|
||||||
if (!ParseTreePseudoElement(aErrorCode, aSelector)) {
|
if (!ParseTreePseudoElement(aErrorCode, aSelector)) {
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2385,194 +2374,178 @@ void CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
|
||||||
if ((eCSSToken_WhiteSpace == mToken.mType) ||
|
if ((eCSSToken_WhiteSpace == mToken.mType) ||
|
||||||
(mToken.IsSymbol('{') || mToken.IsSymbol(','))) {
|
(mToken.IsSymbol('{') || mToken.IsSymbol(','))) {
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_OK;
|
return eSelectorParsingStatus_Done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelTrailing);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelTrailing);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // multiple pseudo elements, not legal
|
else { // multiple pseudo elements, not legal
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelMultiplePE);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelMultiplePE);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not a pseudo-class, not a pseudo-element.... forget it
|
// Not a pseudo-class, not a pseudo-element.... forget it
|
||||||
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
|
REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
|
||||||
UngetToken();
|
UngetToken();
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the argument of a negation pseudo-class :not()
|
// Parse the argument of a negation pseudo-class :not()
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector,
|
CSSParserImpl::ParseNegatedSimpleSelector(PRInt32& aDataMask,
|
||||||
PRInt32& aParsingStatus,
|
nsCSSSelector& aSelector,
|
||||||
nsresult& aErrorCode)
|
nsresult& aErrorCode)
|
||||||
{
|
{
|
||||||
// Check if we have the first parenthesis
|
// Check if we have the first parenthesis
|
||||||
if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
if (!ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationBadArg);
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
return eSelectorParsingStatus_Error;
|
||||||
REPORT_UNEXPECTED_EOF(PENegationEOF);
|
}
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
|
||||||
}
|
REPORT_UNEXPECTED_EOF(PENegationEOF);
|
||||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
if (!aSelector.mNegations) {
|
||||||
|
aSelector.mNegations = new nsCSSSelector();
|
||||||
if (!aSelector.mNegations) {
|
if (!aSelector.mNegations) {
|
||||||
aSelector.mNegations = new nsCSSSelector();
|
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||||
if (!aSelector.mNegations) {
|
return eSelectorParsingStatus_Error;
|
||||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ID, class and attribute selectors and pseudo-classes are stored in
|
|
||||||
// the first mNegations attached to a selector
|
|
||||||
if (eCSSToken_ID == mToken.mType) { // #id
|
|
||||||
ParseIDSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol('.')) { // .class
|
|
||||||
ParseClassSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol(':')) { // :pseudo
|
|
||||||
ParsePseudoSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode, PR_TRUE);
|
|
||||||
}
|
|
||||||
else if (mToken.IsSymbol('[')) { // attribute
|
|
||||||
ParseAttributeSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// then it should be a type element or universal selector
|
|
||||||
nsCSSSelector *newSel = new nsCSSSelector();
|
|
||||||
if (!newSel) {
|
|
||||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nsCSSSelector* negations = aSelector.mNegations;
|
|
||||||
while (nsnull != negations->mNegations) {
|
|
||||||
negations = negations->mNegations;
|
|
||||||
}
|
|
||||||
// negated type element selectors and universal selectors are stored after the first
|
|
||||||
// mNegations containing only negated IDs, classes, attributes and pseudo-classes
|
|
||||||
negations->mNegations = newSel;
|
|
||||||
ParseTypeOrUniversalSelector(aDataMask, *newSel, aParsingStatus, aErrorCode, PR_TRUE);
|
|
||||||
}
|
|
||||||
if (SELECTOR_PARSING_STOPPED_ERROR == aParsingStatus) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationBadInner);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// close the parenthesis
|
|
||||||
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationNoClose);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ID, class and attribute selectors and pseudo-classes are stored in
|
||||||
|
// the first mNegations attached to a selector
|
||||||
|
nsSelectorParsingStatus parsingStatus;
|
||||||
|
if (eCSSToken_ID == mToken.mType) { // #id
|
||||||
|
parsingStatus = ParseIDSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol('.')) { // .class
|
||||||
|
parsingStatus = ParseClassSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol(':')) { // :pseudo
|
||||||
|
parsingStatus = ParsePseudoSelector(aDataMask, *aSelector.mNegations, aErrorCode, PR_TRUE);
|
||||||
|
}
|
||||||
|
else if (mToken.IsSymbol('[')) { // [attribute
|
||||||
|
parsingStatus = ParseAttributeSelector(aDataMask, *aSelector.mNegations, aErrorCode);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
REPORT_UNEXPECTED_TOKEN(PENegationBadArg);
|
// then it should be a type element or universal selector
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
nsCSSSelector *newSel = new nsCSSSelector();
|
||||||
|
if (!newSel) {
|
||||||
|
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
nsCSSSelector* negations = aSelector.mNegations;
|
||||||
|
while (nsnull != negations->mNegations) {
|
||||||
|
negations = negations->mNegations;
|
||||||
|
}
|
||||||
|
// negated type element selectors and universal selectors are stored after the first
|
||||||
|
// mNegations containing only negated IDs, classes, attributes and pseudo-classes
|
||||||
|
negations->mNegations = newSel;
|
||||||
|
parsingStatus = ParseTypeOrUniversalSelector(aDataMask, *newSel, aErrorCode, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
if (eSelectorParsingStatus_Error == parsingStatus) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationBadInner);
|
||||||
|
return parsingStatus;
|
||||||
|
}
|
||||||
|
// close the parenthesis
|
||||||
|
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PENegationNoClose);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parse the argument of a pseudo-class :lang()
|
// Parse the argument of a pseudo-class :lang()
|
||||||
//
|
//
|
||||||
void CSSParserImpl::ParseLangSelector(nsCSSSelector& aSelector,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
PRInt32& aParsingStatus,
|
CSSParserImpl::ParseLangSelector(nsCSSSelector& aSelector, nsresult& aErrorCode)
|
||||||
nsresult& aErrorCode)
|
|
||||||
{
|
{
|
||||||
// Check if we have the first parenthesis
|
// Check if we have the first parenthesis
|
||||||
if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
if (!ExpectSymbol(aErrorCode, '(', PR_FALSE)) {
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) { // premature eof
|
|
||||||
REPORT_UNEXPECTED_EOF(PELangArgEOF);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We expect an identifier with a language abbreviation
|
|
||||||
if (eCSSToken_Ident != mToken.mType) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangArgNotIdent);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the pseudo with the language parameter
|
|
||||||
aSelector.AddPseudoClass(nsCSSPseudoClasses::lang, mToken.mIdent.get());
|
|
||||||
|
|
||||||
// close the parenthesis
|
|
||||||
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangNoClose);
|
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
REPORT_UNEXPECTED_TOKEN(PELangNoArg);
|
REPORT_UNEXPECTED_TOKEN(PELangNoArg);
|
||||||
aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;
|
return eSelectorParsingStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! GetToken(aErrorCode, PR_TRUE)) { // premature eof
|
||||||
|
REPORT_UNEXPECTED_EOF(PELangArgEOF);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
// We expect an identifier with a language abbreviation
|
||||||
|
if (eCSSToken_Ident != mToken.mType) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PELangArgNotIdent);
|
||||||
|
UngetToken();
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the pseudo with the language parameter
|
||||||
|
aSelector.AddPseudoClass(nsCSSPseudoClasses::lang, mToken.mIdent.get());
|
||||||
|
|
||||||
|
// close the parenthesis
|
||||||
|
if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
||||||
|
REPORT_UNEXPECTED_TOKEN(PELangNoClose);
|
||||||
|
return eSelectorParsingStatus_Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eSelectorParsingStatus_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the format for selectors:
|
* This is the format for selectors:
|
||||||
* operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
|
* operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
|
||||||
*/
|
*/
|
||||||
PRBool CSSParserImpl::ParseSelector(nsresult& aErrorCode,
|
CSSParserImpl::nsSelectorParsingStatus
|
||||||
nsCSSSelector& aSelector)
|
CSSParserImpl::ParseSelector(nsresult& aErrorCode, nsCSSSelector& aSelector)
|
||||||
{
|
{
|
||||||
PRInt32 dataMask = 0;
|
|
||||||
PRInt32 parsingStatus = SELECTOR_PARSING_ENDED_OK;
|
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_TRUE)) {
|
if (! GetToken(aErrorCode, PR_TRUE)) {
|
||||||
REPORT_UNEXPECTED_EOF(PESelectorEOF);
|
REPORT_UNEXPECTED_EOF(PESelectorEOF);
|
||||||
return PR_FALSE;
|
return eSelectorParsingStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseTypeOrUniversalSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);
|
PRInt32 dataMask = 0;
|
||||||
if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {
|
nsSelectorParsingStatus parsingStatus =
|
||||||
return PR_TRUE;
|
ParseTypeOrUniversalSelector(dataMask, aSelector, aErrorCode, PR_FALSE);
|
||||||
}
|
if (parsingStatus != eSelectorParsingStatus_Continue) {
|
||||||
else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {
|
return parsingStatus;
|
||||||
return PR_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
parsingStatus = SELECTOR_PARSING_ENDED_OK;
|
if (eCSSToken_ID == mToken.mType) { // #id
|
||||||
if (eCSSToken_ID == mToken.mType) { // #id
|
parsingStatus = ParseIDSelector(dataMask, aSelector, aErrorCode);
|
||||||
ParseIDSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('.')) { // .class
|
else if (mToken.IsSymbol('.')) { // .class
|
||||||
ParseClassSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
parsingStatus = ParseClassSelector(dataMask, aSelector, aErrorCode);
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol(':')) { // :pseudo
|
else if (mToken.IsSymbol(':')) { // :pseudo
|
||||||
ParsePseudoSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);
|
parsingStatus = ParsePseudoSelector(dataMask, aSelector, aErrorCode, PR_FALSE);
|
||||||
}
|
}
|
||||||
else if (mToken.IsSymbol('[')) { // attribute
|
else if (mToken.IsSymbol('[')) { // [attribute
|
||||||
ParseAttributeSelector(dataMask, aSelector, parsingStatus, aErrorCode);
|
parsingStatus = ParseAttributeSelector(dataMask, aSelector, aErrorCode);
|
||||||
}
|
}
|
||||||
else { // not a selector token, we're done
|
else { // not a selector token, we're done
|
||||||
|
parsingStatus = eSelectorParsingStatus_Done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {
|
if (parsingStatus != eSelectorParsingStatus_Continue) {
|
||||||
return PR_TRUE;
|
return parsingStatus;
|
||||||
}
|
}
|
||||||
else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)
|
||||||
return PR_TRUE;
|
return eSelectorParsingStatus_Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UngetToken();
|
UngetToken();
|
||||||
return PRBool(0 != dataMask);
|
return dataMask ? parsingStatus : eSelectorParsingStatus_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSDeclaration*
|
nsCSSDeclaration*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче