diff options
Diffstat (limited to 'Source/WebCore/css/CSSGrammar.y')
-rw-r--r-- | Source/WebCore/css/CSSGrammar.y | 281 |
1 files changed, 206 insertions, 75 deletions
diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y index 03d25d9..269eaf0 100644 --- a/Source/WebCore/css/CSSGrammar.y +++ b/Source/WebCore/css/CSSGrammar.y @@ -99,7 +99,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %} -%expect 51 +%expect 54 %nonassoc LOWEST_PREC @@ -183,13 +183,18 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %token <number> HERTZ %token <number> KHERTZ %token <string> DIMEN +%token <string> INVALIDDIMEN %token <number> PERCENTAGE %token <number> FLOATTOKEN %token <number> INTEGER %token <string> URI %token <string> FUNCTION +%token <string> ANYFUNCTION %token <string> NOTFUNCTION +%token <string> CALCFUNCTION +%token <string> MINFUNCTION +%token <string> MAXFUNCTION %token <string> UNICODERANGE @@ -221,7 +226,6 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <string> string_or_uri %type <string> ident_or_string %type <string> medium -%type <string> hexcolor %type <marginBox> margin_sym %type <string> media_feature @@ -247,6 +251,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <selector> simple_selector %type <selector> selector %type <selectorList> selector_list +%type <selectorList> simple_selector_list %type <selector> selector_with_trailing_whitespace %type <selector> class %type <selector> attrib @@ -270,6 +275,14 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <value> term %type <value> unary_term %type <value> function +%type <value> calc_func_term +%type <character> calc_func_operator +%type <valueList> calc_func_expr +%type <valueList> calc_func_expr_list +%type <valueList> calc_func_paren_expr +%type <value> calc_function +%type <string> min_or_max +%type <value> min_or_max_function %type <string> element_name %type <string> attr_name @@ -857,8 +870,6 @@ selector: end = end->tagHistory(); end->setRelation(CSSSelector::Descendant); end->setTagHistory(p->sinkFloatingSelector($1)); - if (Document* doc = p->document()) - doc->setUsesDescendantRules(true); } } | selector combinator simple_selector { @@ -872,13 +883,6 @@ selector: end = end->tagHistory(); end->setRelation($2); end->setTagHistory(p->sinkFloatingSelector($1)); - if ($2 == CSSSelector::Child) { - if (Document* doc = p->document()) - doc->setUsesDescendantRules(true); - } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) { - if (Document* doc = p->document()) - doc->setUsesSiblingRules(true); - } } } | selector error { @@ -930,6 +934,28 @@ simple_selector: } ; +simple_selector_list: + simple_selector %prec UNIMPORTANT_TOK { + if ($1) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelectorVector(); + $$->append(p->sinkFloatingSelector($1)); + } else + $$ = 0 + } + | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK { + if ($1 && $5) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = $1; + $$->append(p->sinkFloatingSelector($5)); + } else + $$ = 0; + } + | simple_selector_list error { + $$ = 0; + } + ; + element_name: IDENT { CSSParserString& str = $1; @@ -1102,48 +1128,33 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoEmpty || - type == CSSSelector::PseudoFirstChild || - type == CSSSelector::PseudoFirstOfType || - type == CSSSelector::PseudoLastChild || - type == CSSSelector::PseudoLastOfType || - type == CSSSelector::PseudoOnlyChild || - type == CSSSelector::PseudoOnlyOfType) { - CSSParser* p = static_cast<CSSParser*>(parser); - Document* doc = p->document(); - if (doc) - doc->setUsesSiblingRules(true); - } else if (type == CSSSelector::PseudoFirstLine) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesFirstLineRules(true); - } else if (type == CSSSelector::PseudoBefore || - type == CSSSelector::PseudoAfter) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesBeforeAfterRules(true); - } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesLinkRules(true); - } } | ':' ':' IDENT { $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); $$->setMatch(CSSSelector::PseudoElement); $3.lower(); $$->setValue($3); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoFirstLine) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesFirstLineRules(true); - } else if (type == CSSSelector::PseudoBefore || - type == CSSSelector::PseudoAfter) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesBeforeAfterRules(true); - } + // FIXME: This call is needed to force selector to compute the pseudoType early enough. + $$->pseudoType(); + } + // use by :-webkit-any. + // FIXME: should we support generic selectors here or just simple_selectors? + // Use simple_selector_list for now to match -moz-any. + // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some + // related discussion with respect to :not. + | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' { + if ($4) { + CSSParser *p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->setMatch(CSSSelector::PseudoClass); + $$->adoptSelectorVector(*p->sinkFloatingSelectorVector($4)); + $2.lower(); + $$->setValue($2); + CSSSelector::PseudoType type = $$->pseudoType(); + if (type != CSSSelector::PseudoAny) + $$ = 0; + } else + $$ = 0; } // used by :nth-*(ax+b) | ':' FUNCTION maybe_space NTH maybe_space ')' { @@ -1155,13 +1166,6 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoNthChild || - type == CSSSelector::PseudoNthOfType || - type == CSSSelector::PseudoNthLastChild || - type == CSSSelector::PseudoNthLastOfType) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } } // used by :nth-* | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' { @@ -1173,13 +1177,6 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoNthChild || - type == CSSSelector::PseudoNthOfType || - type == CSSSelector::PseudoNthLastChild || - type == CSSSelector::PseudoNthLastOfType) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } } // used by :nth-*(odd/even) and :lang | ':' FUNCTION maybe_space IDENT maybe_space ')' { @@ -1196,10 +1193,7 @@ pseudo: type == CSSSelector::PseudoNthOfType || type == CSSSelector::PseudoNthLastChild || type == CSSSelector::PseudoNthLastOfType) { - if (isValidNthToken($4)) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } else + if (!isValidNthToken($4)) $$ = 0; } } @@ -1211,7 +1205,11 @@ pseudo: CSSParser* p = static_cast<CSSParser*>(parser); $$ = p->createFloatingSelector(); $$->setMatch(CSSSelector::PseudoClass); - $$->setSimpleSelector(p->sinkFloatingSelector($4)->releaseSelector()); + + Vector<OwnPtr<CSSParserSelector> > selectorVector; + selectorVector.append(p->sinkFloatingSelector($4)); + $$->adoptSelectorVector(selectorVector); + $2.lower(); $$->setValue($2); } @@ -1415,12 +1413,18 @@ term: | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; } | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } - | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } + | HEX maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */ /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ | function { $$ = $1; } + | calc_function { + $$ = $1; + } + | min_or_max_function { + $$ = $1; + } | '%' maybe_space { /* Handle width: %; */ $$.id = 0; $$.unit = 0; } @@ -1477,16 +1481,143 @@ function: $$.function = f; } ; -/* - * There is a constraint on the color that it must - * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) - * after the "#"; e.g., "#000" is OK, but "#abcd" is not. - */ -hexcolor: - HEX maybe_space { $$ = $1; } - | IDSEL maybe_space { $$ = $1; } + +calc_func_term: + unary_term { $$ = $1; } + | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } ; +calc_func_operator: + '+' WHITESPACE { + $$ = '+'; + } + | '-' WHITESPACE { + $$ = '-'; + } + | '*' maybe_space { + $$ = '*'; + } + | '/' maybe_space { + $$ = '/'; + } + | IDENT maybe_space { + if (equalIgnoringCase("mod", $1.characters, $1.length)) + $$ = '%'; + else + $$ = 0; + } + ; + +calc_func_paren_expr: + '(' maybe_space calc_func_expr maybe_space ')' maybe_space { + if ($3) { + $$ = $3; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = '('; + $$->insertValueAt(0, v); + v.iValue = ')'; + $$->addValue(v); + } else + $$ = 0; + } + +calc_func_expr: + calc_func_term maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingValueList(); + $$->addValue(p->sinkFloatingValue($1)); + } + | calc_func_expr calc_func_operator calc_func_term { + CSSParser* p = static_cast<CSSParser*>(parser); + if ($1 && $2) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = $2; + $$->addValue(v); + $$->addValue(p->sinkFloatingValue($3)); + } else + $$ = 0; + + } + | calc_func_expr calc_func_operator calc_func_paren_expr { + if ($1 && $2 && $3) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = $2; + $$->addValue(v); + $$->extend(*($3)); + } else + $$ = 0; + } + | calc_func_paren_expr + | calc_func_expr error { + $$ = 0; + } + ; + +calc_func_expr_list: + calc_func_expr { + $$ = $1; + } + | calc_func_expr_list ',' maybe_space calc_func_expr { + if ($1 && $4) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = ','; + $$->addValue(v); + $$->extend(*($4)); + } else + $$ = 0; + } + + +calc_function: + CALCFUNCTION maybe_space calc_func_expr ')' maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSParserFunction* f = p->createFloatingFunction(); + f->name = $1; + f->args = p->sinkFloatingValueList($3); + $$.id = 0; + $$.unit = CSSParserValue::Function; + $$.function = f; + } + | CALCFUNCTION maybe_space error { + YYERROR; + } + ; + + +min_or_max: + MINFUNCTION { + $$ = $1; + } + | MAXFUNCTION { + $$ = $1; + } + ; + +min_or_max_function: + min_or_max maybe_space calc_func_expr_list ')' maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSParserFunction* f = p->createFloatingFunction(); + f->name = $1; + f->args = p->sinkFloatingValueList($3); + $$.id = 0; + $$.unit = CSSParserValue::Function; + $$.function = f; + } + | min_or_max maybe_space error { + YYERROR; + } + ; /* error handling rules */ |