summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/css/CSSGrammar.y
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/CSSGrammar.y')
-rw-r--r--Source/WebCore/css/CSSGrammar.y281
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 */