4 * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "CSSMediaRule.h"
28 #include "CSSParser.h"
29 #include "CSSPrimitiveValue.h"
30 #include "CSSPropertyNames.h"
31 #include "CSSRuleList.h"
32 #include "CSSSelector.h"
33 #include "CSSStyleSheet.h"
35 #include "HTMLNames.h"
36 #include "MediaList.h"
37 #include "WebKitCSSKeyframeRule.h"
38 #include "WebKitCSSKeyframesRule.h"
39 #include <wtf/FastMalloc.h>
43 using namespace WebCore;
44 using namespace HTMLNames;
46 #define YYMALLOC fastMalloc
47 #define YYFREE fastFree
49 #define YYENABLE_NLS 0
50 #define YYLTYPE_IS_TRIVIAL 1
51 #define YYMAXDEPTH 10000
54 // FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x
55 #define YYPARSE_PARAM parser
56 #define YYLEX_PARAM parser
67 CSSParserString string;
70 CSSRuleList* ruleList;
71 CSSSelector* selector;
72 Vector<CSSSelector*>* selectorList;
73 CSSSelector::MarginBoxType marginBox;
74 CSSSelector::Relation relation;
76 MediaQuery* mediaQuery;
77 MediaQuery::Restrictor mediaQueryRestrictor;
78 MediaQueryExp* mediaQueryExp;
80 CSSParserValueList* valueList;
81 Vector<MediaQueryExp*>* mediaQueryExpList;
82 WebKitCSSKeyframeRule* keyframeRule;
83 WebKitCSSKeyframesRule* keyframesRule;
89 static inline int cssyyerror(const char*)
94 static int cssyylex(YYSTYPE* yylval, void* parser)
96 return static_cast<CSSParser*>(parser)->lex(yylval);
103 %nonassoc LOWEST_PREC
105 %left UNIMPORTANT_TOK
107 %token WHITESPACE SGML_CD
116 %token <string> STRING
117 %right <string> IDENT
120 %nonassoc <string> HEX
121 %nonassoc <string> IDSEL
125 %nonassoc <string> '*'
135 %token WEBKIT_RULE_SYM
136 %token WEBKIT_DECLS_SYM
137 %token WEBKIT_KEYFRAME_RULE_SYM
138 %token WEBKIT_KEYFRAMES_SYM
139 %token WEBKIT_VALUE_SYM
140 %token WEBKIT_MEDIAQUERY_SYM
141 %token WEBKIT_SELECTOR_SYM
142 %token WEBKIT_VARIABLES_SYM
143 %token WEBKIT_DEFINE_SYM
145 %token WEBKIT_VARIABLES_DECLS_SYM
146 %token <marginBox> TOPLEFTCORNER_SYM
147 %token <marginBox> TOPLEFT_SYM
148 %token <marginBox> TOPCENTER_SYM
149 %token <marginBox> TOPRIGHT_SYM
150 %token <marginBox> TOPRIGHTCORNER_SYM
151 %token <marginBox> BOTTOMLEFTCORNER_SYM
152 %token <marginBox> BOTTOMLEFT_SYM
153 %token <marginBox> BOTTOMCENTER_SYM
154 %token <marginBox> BOTTOMRIGHT_SYM
155 %token <marginBox> BOTTOMRIGHTCORNER_SYM
156 %token <marginBox> LEFTTOP_SYM
157 %token <marginBox> LEFTMIDDLE_SYM
158 %token <marginBox> LEFTBOTTOM_SYM
159 %token <marginBox> RIGHTTOP_SYM
160 %token <marginBox> RIGHTMIDDLE_SYM
161 %token <marginBox> RIGHTBOTTOM_SYM
182 %token <number> GRADS
183 %token <number> TURNS
184 %token <number> MSECS
187 %token <number> KHERZ
188 %token <string> DIMEN
189 %token <number> PERCENTAGE
190 %token <number> FLOATTOKEN
191 %token <number> INTEGER
194 %token <string> FUNCTION
195 %token <string> NOTFUNCTION
197 %token <string> UNICODERANGE
199 %token <string> VARCALL
201 %type <relation> combinator
207 %type <rule> namespace
209 %type <rule> margin_box
210 %type <rule> font_face
211 %type <rule> keyframes
212 %type <rule> invalid_rule
213 %type <rule> save_block
214 %type <rule> invalid_at
216 %type <rule> valid_rule
217 %type <ruleList> block_rule_list
218 %type <rule> block_rule
219 %type <rule> block_valid_rule
220 %type <rule> variables_rule
221 %type <mediaList> variables_media_list
223 %type <string> maybe_ns_prefix
225 %type <string> namespace_selector
227 %type <string> string_or_uri
228 %type <string> ident_or_string
229 %type <string> medium
230 %type <string> hexcolor
231 %type <marginBox> margin_sym
233 %type <string> media_feature
234 %type <mediaList> media_list
235 %type <mediaList> maybe_media_list
236 %type <mediaQuery> media_query
237 %type <mediaQueryRestrictor> maybe_media_restrictor
238 %type <valueList> maybe_media_value
239 %type <mediaQueryExp> media_query_exp
240 %type <mediaQueryExpList> media_query_exp_list
241 %type <mediaQueryExpList> maybe_and_media_query_exp_list
243 %type <string> keyframe_name
244 %type <keyframeRule> keyframe_rule
245 %type <keyframesRule> keyframes_rule
246 %type <valueList> key_list
249 %type <integer> property
251 %type <selector> specifier
252 %type <selector> specifier_list
253 %type <selector> simple_selector
254 %type <selector> selector
255 %type <selectorList> selector_list
256 %type <selector> selector_with_trailing_whitespace
257 %type <selector> class
258 %type <selector> attrib
259 %type <selector> pseudo
260 %type <selector> pseudo_page
261 %type <selector> page_selector
263 %type <boolean> declaration_list
264 %type <boolean> decl_list
265 %type <boolean> declaration
266 %type <boolean> declarations_and_margins
270 %type <integer> match
271 %type <integer> unary_operator
272 %type <integer> maybe_unary_operator
273 %type <character> operator
275 %type <valueList> expr
277 %type <value> unary_term
278 %type <value> function
280 %type <string> element_name
281 %type <string> attr_name
283 %type <string> variable_name
284 %type <boolean> variables_declaration_list
285 %type <boolean> variables_decl_list
286 %type <boolean> variables_declaration
287 %type <value> variable_reference
292 maybe_space maybe_charset maybe_sgml rule_list
293 | webkit_rule maybe_space
294 | webkit_decls maybe_space
295 | webkit_value maybe_space
296 | webkit_mediaquery maybe_space
297 | webkit_selector maybe_space
298 | webkit_variables_decls maybe_space
299 | webkit_keyframe_rule maybe_space
303 WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
304 static_cast<CSSParser*>(parser)->m_rule = $4;
308 webkit_keyframe_rule:
309 WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
310 static_cast<CSSParser*>(parser)->m_keyframe = $4;
315 WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' {
320 webkit_variables_decls:
321 WEBKIT_VARIABLES_DECLS_SYM '{' maybe_space variables_declaration_list '}' {
327 WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
328 CSSParser* p = static_cast<CSSParser*>(parser);
330 p->m_valueList = p->sinkFloatingValueList($4);
331 int oldParsedProperties = p->m_numParsedProperties;
332 if (!p->parseValue(p->m_id, p->m_important))
333 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
334 delete p->m_valueList;
341 WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
342 CSSParser* p = static_cast<CSSParser*>(parser);
343 p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
348 WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
350 CSSParser* p = static_cast<CSSParser*>(parser);
351 if (p->m_selectorListForParseSelector)
352 p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
358 /* empty */ %prec UNIMPORTANT_TOK
359 | maybe_space WHITESPACE
365 | maybe_sgml WHITESPACE
376 | %prec LOWEST_PREC TOKEN_EOF
380 CHARSET_SYM maybe_space STRING maybe_space ';' {
381 CSSParser* p = static_cast<CSSParser*>(parser);
382 $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
383 if ($$ && p->m_styleSheet)
384 p->m_styleSheet->append($$);
386 | CHARSET_SYM error invalid_block {
388 | CHARSET_SYM error ';' {
394 | rule_list rule maybe_sgml {
395 CSSParser* p = static_cast<CSSParser*>(parser);
396 if ($2 && p->m_styleSheet)
397 p->m_styleSheet->append($2);
414 static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
421 /* empty */ { $$ = 0; }
422 | block_rule_list block_rule maybe_sgml {
426 $$ = static_cast<CSSParser*>(parser)->createRuleList();
451 IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
452 $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
454 | IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
457 | IMPORT_SYM error ';' {
460 | IMPORT_SYM error invalid_block {
466 WEBKIT_VARIABLES_SYM maybe_space maybe_media_list '{' maybe_space variables_declaration_list '}' {
467 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, true);
470 WEBKIT_DEFINE_SYM maybe_space variables_media_list '{' maybe_space variables_declaration_list '}' {
471 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, false);
475 variables_media_list:
477 $$ = static_cast<CSSParser*>(parser)->createMediaList();
480 VARIABLES_FOR WHITESPACE media_list {
485 variables_declaration_list:
486 variables_declaration {
489 | variables_decl_list variables_declaration {
494 | variables_decl_list {
497 | error invalid_block_list error {
503 | variables_decl_list error {
509 variables_declaration ';' maybe_space {
512 | variables_declaration invalid_block_list ';' maybe_space {
515 | error ';' maybe_space {
518 | error invalid_block_list error ';' maybe_space {
521 | variables_decl_list variables_declaration ';' maybe_space {
526 | variables_decl_list error ';' maybe_space {
529 | variables_decl_list error invalid_block_list error ';' maybe_space {
534 variables_declaration:
535 variable_name ':' maybe_space expr {
536 $$ = static_cast<CSSParser*>(parser)->addVariable($1, $4);
539 variable_name maybe_space '{' maybe_space declaration_list '}' maybe_space {
540 $$ = static_cast<CSSParser*>(parser)->addVariableDeclarationBlock($1);
543 variable_name error {
547 variable_name ':' maybe_space error expr {
551 variable_name ':' maybe_space {
552 /* @variables { varname: } Just reduce away this variable with no value. */
556 variable_name ':' maybe_space error {
557 /* if we come across rules with invalid values like this case: @variables { varname: *; }, just discard the property/value pair */
569 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
570 static_cast<CSSParser*>(parser)->addNamespace($3, $4);
573 | NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
576 | NAMESPACE_SYM error invalid_block {
579 | NAMESPACE_SYM error ';' {
585 /* empty */ { $$.characters = 0; }
586 | IDENT maybe_space { $$ = $1; }
604 | ':' maybe_space expr maybe_space {
610 '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
612 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
616 media_query_exp_list:
618 CSSParser* p = static_cast<CSSParser*>(parser);
619 $$ = p->createFloatingMediaQueryExpList();
620 $$->append(p->sinkFloatingMediaQueryExp($1));
622 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
624 $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
628 maybe_and_media_query_exp_list:
630 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
632 | MEDIA_AND maybe_space media_query_exp_list {
637 maybe_media_restrictor:
639 $$ = MediaQuery::None;
642 $$ = MediaQuery::Only;
645 $$ = MediaQuery::Not;
650 media_query_exp_list {
651 CSSParser* p = static_cast<CSSParser*>(parser);
652 $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
655 maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
656 CSSParser* p = static_cast<CSSParser*>(parser);
658 $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
664 $$ = static_cast<CSSParser*>(parser)->createMediaList();
671 CSSParser* p = static_cast<CSSParser*>(parser);
672 $$ = p->createMediaList();
673 $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
675 | media_list ',' maybe_space media_query {
678 $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
686 MEDIA_SYM maybe_space media_list '{' maybe_space block_rule_list save_block {
687 $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
689 | MEDIA_SYM maybe_space '{' maybe_space block_rule_list save_block {
690 $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
701 WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name maybe_space '{' maybe_space keyframes_rule '}' {
703 $7->setNameInternal($3);
713 /* empty */ { $$ = static_cast<CSSParser*>(parser)->createKeyframesRule(); }
714 | keyframes_rule keyframe_rule maybe_space {
722 key_list maybe_space '{' maybe_space declaration_list '}' {
723 $$ = static_cast<CSSParser*>(parser)->createKeyframeRule($1);
729 CSSParser* p = static_cast<CSSParser*>(parser);
730 $$ = p->createFloatingValueList();
731 $$->addValue(p->sinkFloatingValue($1));
733 | key_list maybe_space ',' maybe_space key {
734 CSSParser* p = static_cast<CSSParser*>(parser);
737 $$->addValue(p->sinkFloatingValue($5));
742 PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
744 $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
745 CSSParserString& str = $1;
746 if (equalIgnoringCase("from", str.characters, str.length))
748 else if (equalIgnoringCase("to", str.characters, str.length))
756 PAGE_SYM maybe_space page_selector maybe_space
757 '{' maybe_space declarations_and_margins closing_brace {
758 CSSParser* p = static_cast<CSSParser*>(parser);
760 $$ = p->createPageRule(p->sinkFloatingSelector($3));
762 // Clear properties in the invalid @page rule.
763 p->clearProperties();
764 // Also clear margin at-rules here once we fully implement margin at-rules parsing.
768 | PAGE_SYM error invalid_block {
771 | PAGE_SYM error ';' {
778 CSSParser* p = static_cast<CSSParser*>(parser);
779 $$ = p->createFloatingSelector();
780 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
782 | IDENT pseudo_page {
783 CSSParser* p = static_cast<CSSParser*>(parser);
786 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
792 CSSParser* p = static_cast<CSSParser*>(parser);
793 $$ = p->createFloatingSelector();
797 declarations_and_margins:
799 | declarations_and_margins margin_box maybe_space declaration_list
804 static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
805 } maybe_space '{' maybe_space declaration_list closing_brace {
806 $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
812 $$ = CSSSelector::TopLeftCornerMarginBox;
815 $$ = CSSSelector::TopLeftMarginBox;
818 $$ = CSSSelector::TopCenterMarginBox;
821 $$ = CSSSelector::TopRightMarginBox;
823 | TOPRIGHTCORNER_SYM {
824 $$ = CSSSelector::TopRightCornerMarginBox;
826 | BOTTOMLEFTCORNER_SYM {
827 $$ = CSSSelector::BottomLeftCornerMarginBox;
830 $$ = CSSSelector::BottomLeftMarginBox;
833 $$ = CSSSelector::BottomCenterMarginBox;
836 $$ = CSSSelector::BottomRightMarginBox;
838 | BOTTOMRIGHTCORNER_SYM {
839 $$ = CSSSelector::BottomRightCornerMarginBox;
842 $$ = CSSSelector::LeftTopMarginBox;
845 $$ = CSSSelector::LeftMiddleMarginBox;
848 $$ = CSSSelector::LeftBottomMarginBox;
851 $$ = CSSSelector::RightTopMarginBox;
854 $$ = CSSSelector::RightMiddleMarginBox;
857 $$ = CSSSelector::RightBottomMarginBox;
862 FONT_FACE_SYM maybe_space
863 '{' maybe_space declaration_list '}' maybe_space {
864 $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
866 | FONT_FACE_SYM error invalid_block {
869 | FONT_FACE_SYM error ';' {
875 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
876 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
877 | '>' maybe_space { $$ = CSSSelector::Child; }
880 maybe_unary_operator:
881 unary_operator { $$ = $1; }
891 selector_list '{' maybe_space declaration_list closing_brace {
892 $$ = static_cast<CSSParser*>(parser)->createStyleRule($1);
897 selector %prec UNIMPORTANT_TOK {
899 CSSParser* p = static_cast<CSSParser*>(parser);
900 $$ = p->reusableSelectorVector();
901 deleteAllValues(*$$);
903 $$->append(p->sinkFloatingSelector($1));
904 p->updateLastSelectorLine();
907 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
909 CSSParser* p = static_cast<CSSParser*>(parser);
911 $$->append(p->sinkFloatingSelector($4));
912 p->updateLastSelectorLine();
916 | selector_list error {
921 selector_with_trailing_whitespace:
922 selector WHITESPACE {
931 | selector_with_trailing_whitespace
935 | selector_with_trailing_whitespace simple_selector
941 CSSParser* p = static_cast<CSSParser*>(parser);
942 CSSSelector* end = $$;
943 while (end->tagHistory())
944 end = end->tagHistory();
945 end->m_relation = CSSSelector::Descendant;
946 end->setTagHistory(p->sinkFloatingSelector($1));
947 if (Document* doc = p->document())
948 doc->setUsesDescendantRules(true);
951 | selector combinator simple_selector {
956 CSSParser* p = static_cast<CSSParser*>(parser);
957 CSSSelector* end = $$;
958 while (end->tagHistory())
959 end = end->tagHistory();
960 end->m_relation = $2;
961 end->setTagHistory(p->sinkFloatingSelector($1));
962 if ($2 == CSSSelector::Child) {
963 if (Document* doc = p->document())
964 doc->setUsesDescendantRules(true);
965 } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
966 if (Document* doc = p->document())
967 doc->setUsesSiblingRules(true);
977 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
978 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
979 | IDENT '|' { $$ = $1; }
984 CSSParser* p = static_cast<CSSParser*>(parser);
985 $$ = p->createFloatingSelector();
986 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
988 | element_name specifier_list {
991 CSSParser* p = static_cast<CSSParser*>(parser);
992 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
997 CSSParser* p = static_cast<CSSParser*>(parser);
998 if ($$ && p->m_defaultNamespace != starAtom)
999 $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
1001 | namespace_selector element_name {
1002 AtomicString namespacePrefix = $1;
1003 CSSParser* p = static_cast<CSSParser*>(parser);
1004 $$ = p->createFloatingSelector();
1005 if (p->m_styleSheet)
1006 $$->m_tag = QualifiedName(namespacePrefix, $2,
1007 p->m_styleSheet->determineNamespace(namespacePrefix));
1008 else // FIXME: Shouldn't this case be an error?
1009 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1011 | namespace_selector element_name specifier_list {
1014 AtomicString namespacePrefix = $1;
1015 CSSParser* p = static_cast<CSSParser*>(parser);
1016 if (p->m_styleSheet)
1017 $$->m_tag = QualifiedName(namespacePrefix, $2,
1018 p->m_styleSheet->determineNamespace(namespacePrefix));
1019 else // FIXME: Shouldn't this case be an error?
1020 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1023 | namespace_selector specifier_list {
1026 AtomicString namespacePrefix = $1;
1027 CSSParser* p = static_cast<CSSParser*>(parser);
1028 if (p->m_styleSheet)
1029 $$->m_tag = QualifiedName(namespacePrefix, starAtom,
1030 p->m_styleSheet->determineNamespace(namespacePrefix));
1037 CSSParserString& str = $1;
1038 CSSParser* p = static_cast<CSSParser*>(parser);
1039 Document* doc = p->document();
1040 if (doc && doc->isHTMLDocument())
1045 static UChar star = '*';
1046 $$.characters = ☆
1055 | specifier_list specifier {
1060 CSSParser* p = static_cast<CSSParser*>(parser);
1061 CSSSelector* end = $1;
1062 while (end->tagHistory())
1063 end = end->tagHistory();
1064 end->m_relation = CSSSelector::SubSelector;
1065 end->setTagHistory(p->sinkFloatingSelector($2));
1068 | specifier_list error {
1075 CSSParser* p = static_cast<CSSParser*>(parser);
1076 $$ = p->createFloatingSelector();
1077 $$->m_match = CSSSelector::Id;
1083 if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
1086 CSSParser* p = static_cast<CSSParser*>(parser);
1087 $$ = p->createFloatingSelector();
1088 $$->m_match = CSSSelector::Id;
1101 CSSParser* p = static_cast<CSSParser*>(parser);
1102 $$ = p->createFloatingSelector();
1103 $$->m_match = CSSSelector::Class;
1112 CSSParserString& str = $1;
1113 CSSParser* p = static_cast<CSSParser*>(parser);
1114 Document* doc = p->document();
1115 if (doc && doc->isHTMLDocument())
1122 '[' maybe_space attr_name ']' {
1123 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1124 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1125 $$->m_match = CSSSelector::Set;
1127 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1128 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1129 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1130 $$->m_match = (CSSSelector::Match)$4;
1133 | '[' maybe_space namespace_selector attr_name ']' {
1134 AtomicString namespacePrefix = $3;
1135 CSSParser* p = static_cast<CSSParser*>(parser);
1136 $$ = p->createFloatingSelector();
1137 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1138 p->m_styleSheet->determineNamespace(namespacePrefix)));
1139 $$->m_match = CSSSelector::Set;
1141 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
1142 AtomicString namespacePrefix = $3;
1143 CSSParser* p = static_cast<CSSParser*>(parser);
1144 $$ = p->createFloatingSelector();
1145 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1146 p->m_styleSheet->determineNamespace(namespacePrefix)));
1147 $$->m_match = (CSSSelector::Match)$5;
1154 $$ = CSSSelector::Exact;
1157 $$ = CSSSelector::List;
1160 $$ = CSSSelector::Hyphen;
1163 $$ = CSSSelector::Begin;
1166 $$ = CSSSelector::End;
1169 $$ = CSSSelector::Contain;
1180 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1181 $$->m_match = CSSSelector::PagePseudoClass;
1184 CSSSelector::PseudoType type = $$->pseudoType();
1185 if (type == CSSSelector::PseudoUnknown)
1191 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1192 $$->m_match = CSSSelector::PseudoClass;
1195 CSSSelector::PseudoType type = $$->pseudoType();
1196 if (type == CSSSelector::PseudoUnknown)
1198 else if (type == CSSSelector::PseudoEmpty ||
1199 type == CSSSelector::PseudoFirstChild ||
1200 type == CSSSelector::PseudoFirstOfType ||
1201 type == CSSSelector::PseudoLastChild ||
1202 type == CSSSelector::PseudoLastOfType ||
1203 type == CSSSelector::PseudoOnlyChild ||
1204 type == CSSSelector::PseudoOnlyOfType) {
1205 CSSParser* p = static_cast<CSSParser*>(parser);
1206 Document* doc = p->document();
1208 doc->setUsesSiblingRules(true);
1209 } else if (type == CSSSelector::PseudoFirstLine) {
1210 CSSParser* p = static_cast<CSSParser*>(parser);
1211 if (Document* doc = p->document())
1212 doc->setUsesFirstLineRules(true);
1213 } else if (type == CSSSelector::PseudoBefore ||
1214 type == CSSSelector::PseudoAfter) {
1215 CSSParser* p = static_cast<CSSParser*>(parser);
1216 if (Document* doc = p->document())
1217 doc->setUsesBeforeAfterRules(true);
1218 } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) {
1219 CSSParser* p = static_cast<CSSParser*>(parser);
1220 if (Document* doc = p->document())
1221 doc->setUsesLinkRules(true);
1225 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1226 $$->m_match = CSSSelector::PseudoElement;
1229 CSSSelector::PseudoType type = $$->pseudoType();
1230 if (type == CSSSelector::PseudoUnknown)
1232 else if (type == CSSSelector::PseudoFirstLine) {
1233 CSSParser* p = static_cast<CSSParser*>(parser);
1234 if (Document* doc = p->document())
1235 doc->setUsesFirstLineRules(true);
1236 } else if (type == CSSSelector::PseudoBefore ||
1237 type == CSSSelector::PseudoAfter) {
1238 CSSParser* p = static_cast<CSSParser*>(parser);
1239 if (Document* doc = p->document())
1240 doc->setUsesBeforeAfterRules(true);
1243 // used by :nth-*(ax+b)
1244 | ':' FUNCTION maybe_space NTH maybe_space ')' {
1245 CSSParser *p = static_cast<CSSParser*>(parser);
1246 $$ = p->createFloatingSelector();
1247 $$->m_match = CSSSelector::PseudoClass;
1248 $$->setArgument($4);
1250 CSSSelector::PseudoType type = $$->pseudoType();
1251 if (type == CSSSelector::PseudoUnknown)
1253 else if (type == CSSSelector::PseudoNthChild ||
1254 type == CSSSelector::PseudoNthOfType ||
1255 type == CSSSelector::PseudoNthLastChild ||
1256 type == CSSSelector::PseudoNthLastOfType) {
1258 p->document()->setUsesSiblingRules(true);
1262 | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
1263 CSSParser *p = static_cast<CSSParser*>(parser);
1264 $$ = p->createFloatingSelector();
1265 $$->m_match = CSSSelector::PseudoClass;
1266 $$->setArgument(String::number($4 * $5));
1268 CSSSelector::PseudoType type = $$->pseudoType();
1269 if (type == CSSSelector::PseudoUnknown)
1271 else if (type == CSSSelector::PseudoNthChild ||
1272 type == CSSSelector::PseudoNthOfType ||
1273 type == CSSSelector::PseudoNthLastChild ||
1274 type == CSSSelector::PseudoNthLastOfType) {
1276 p->document()->setUsesSiblingRules(true);
1279 // used by :nth-*(odd/even) and :lang
1280 | ':' FUNCTION maybe_space IDENT maybe_space ')' {
1281 CSSParser *p = static_cast<CSSParser*>(parser);
1282 $$ = p->createFloatingSelector();
1283 $$->m_match = CSSSelector::PseudoClass;
1284 $$->setArgument($4);
1287 CSSSelector::PseudoType type = $$->pseudoType();
1288 if (type == CSSSelector::PseudoUnknown)
1290 else if (type == CSSSelector::PseudoNthChild ||
1291 type == CSSSelector::PseudoNthOfType ||
1292 type == CSSSelector::PseudoNthLastChild ||
1293 type == CSSSelector::PseudoNthLastOfType) {
1295 p->document()->setUsesSiblingRules(true);
1299 | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1300 if (!$4 || !$4->isSimple())
1303 CSSParser* p = static_cast<CSSParser*>(parser);
1304 $$ = p->createFloatingSelector();
1305 $$->m_match = CSSSelector::PseudoClass;
1306 $$->setSimpleSelector(p->sinkFloatingSelector($4));
1317 | decl_list declaration {
1325 | error invalid_block_list error {
1334 | decl_list invalid_block_list {
1340 declaration ';' maybe_space {
1343 | declaration invalid_block_list maybe_space {
1346 | declaration invalid_block_list ';' maybe_space {
1349 | error ';' maybe_space {
1352 | error invalid_block_list error ';' maybe_space {
1355 | decl_list declaration ';' maybe_space {
1360 | decl_list error ';' maybe_space {
1363 | decl_list error invalid_block_list error ';' maybe_space {
1369 property ':' maybe_space expr prio {
1371 CSSParser* p = static_cast<CSSParser*>(parser);
1373 p->m_valueList = p->sinkFloatingValueList($4);
1374 int oldParsedProperties = p->m_numParsedProperties;
1375 $$ = p->parseValue($1, $5);
1377 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1378 delete p->m_valueList;
1383 variable_reference maybe_space {
1384 CSSParser* p = static_cast<CSSParser*>(parser);
1385 p->m_valueList = new CSSParserValueList;
1386 p->m_valueList->addValue(p->sinkFloatingValue($1));
1387 int oldParsedProperties = p->m_numParsedProperties;
1388 $$ = p->parseValue(CSSPropertyWebkitVariableDeclarationBlock, false);
1390 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1391 delete p->m_valueList;
1399 property ':' maybe_space error expr prio {
1400 /* The default movable type template has letter-spacing: .none; Handle this by looking for
1401 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1402 up and deleting the shifted expr. */
1406 property ':' maybe_space expr prio error {
1407 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1411 IMPORTANT_SYM maybe_space {
1412 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1416 property ':' maybe_space {
1417 /* div { font-family: } Just reduce away this property with no value. */
1421 property ':' maybe_space error {
1422 /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1426 property invalid_block {
1427 /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
1434 $$ = cssPropertyID($1);
1439 IMPORTANT_SYM maybe_space { $$ = true; }
1440 | /* empty */ { $$ = false; }
1445 CSSParser* p = static_cast<CSSParser*>(parser);
1446 $$ = p->createFloatingValueList();
1447 $$->addValue(p->sinkFloatingValue($1));
1449 | expr operator term {
1450 CSSParser* p = static_cast<CSSParser*>(parser);
1456 v.unit = CSSParserValue::Operator;
1460 $$->addValue(p->sinkFloatingValue($3));
1463 | expr invalid_block_list {
1466 | expr invalid_block_list error {
1487 unary_term { $$ = $1; }
1488 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1489 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1490 | IDENT maybe_space {
1491 $$.id = cssValueKeywordID($1);
1492 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1495 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1496 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1497 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1498 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1499 | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1500 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1501 | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1502 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1506 | variable_reference maybe_space {
1509 | '%' maybe_space { /* Handle width: %; */
1510 $$.id = 0; $$.unit = 0;
1515 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1516 | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1517 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1518 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1519 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1520 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1521 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1522 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1523 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1524 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1525 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1526 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1527 | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1528 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1529 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1530 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1531 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1532 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1533 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1534 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1535 | REMS maybe_space {
1538 $$.unit = CSSPrimitiveValue::CSS_REMS;
1539 CSSParser* p = static_cast<CSSParser*>(parser);
1540 if (Document* doc = p->document())
1541 doc->setUsesRemUnits(true);
1549 $$.unit = CSSPrimitiveValue::CSS_PARSER_VARIABLE_FUNCTION_SYNTAX;
1554 FUNCTION maybe_space expr ')' maybe_space {
1555 CSSParser* p = static_cast<CSSParser*>(parser);
1556 CSSParserFunction* f = p->createFloatingFunction();
1558 f->args = p->sinkFloatingValueList($3);
1560 $$.unit = CSSParserValue::Function;
1563 FUNCTION maybe_space error {
1564 CSSParser* p = static_cast<CSSParser*>(parser);
1565 CSSParserFunction* f = p->createFloatingFunction();
1569 $$.unit = CSSParserValue::Function;
1574 * There is a constraint on the color that it must
1575 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1576 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1579 HEX maybe_space { $$ = $1; }
1580 | IDSEL maybe_space { $$ = $1; }
1584 /* error handling rules */
1590 | error closing_brace {
1596 ATKEYWORD error invalid_block {
1599 | ATKEYWORD error ';' {
1605 error invalid_block {
1610 Seems like the two rules below are trying too much and violating
1611 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1623 '{' error invalid_block_list error closing_brace {
1624 static_cast<CSSParser*>(parser)->invalidBlockHit();
1626 | '{' error closing_brace {
1627 static_cast<CSSParser*>(parser)->invalidBlockHit();
1633 | invalid_block_list error invalid_block