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> page_selector
262 %type <boolean> declaration_list
263 %type <boolean> decl_list
264 %type <boolean> declaration
265 %type <boolean> declarations_and_margins
269 %type <integer> match
270 %type <integer> unary_operator
271 %type <integer> maybe_unary_operator
272 %type <character> operator
274 %type <valueList> expr
276 %type <value> unary_term
277 %type <value> function
279 %type <string> element_name
280 %type <string> attr_name
282 %type <string> variable_name
283 %type <boolean> variables_declaration_list
284 %type <boolean> variables_decl_list
285 %type <boolean> variables_declaration
286 %type <value> variable_reference
291 maybe_space maybe_charset maybe_sgml rule_list
292 | webkit_rule maybe_space
293 | webkit_decls maybe_space
294 | webkit_value maybe_space
295 | webkit_mediaquery maybe_space
296 | webkit_selector maybe_space
297 | webkit_variables_decls maybe_space
298 | webkit_keyframe_rule maybe_space
302 WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
303 static_cast<CSSParser*>(parser)->m_rule = $4;
307 webkit_keyframe_rule:
308 WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
309 static_cast<CSSParser*>(parser)->m_keyframe = $4;
314 WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' {
319 webkit_variables_decls:
320 WEBKIT_VARIABLES_DECLS_SYM '{' maybe_space variables_declaration_list '}' {
326 WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
327 CSSParser* p = static_cast<CSSParser*>(parser);
329 p->m_valueList = p->sinkFloatingValueList($4);
330 int oldParsedProperties = p->m_numParsedProperties;
331 if (!p->parseValue(p->m_id, p->m_important))
332 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
333 delete p->m_valueList;
340 WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
341 CSSParser* p = static_cast<CSSParser*>(parser);
342 p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
347 WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
349 CSSParser* p = static_cast<CSSParser*>(parser);
350 if (p->m_selectorListForParseSelector)
351 p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
357 /* empty */ %prec UNIMPORTANT_TOK
358 | maybe_space WHITESPACE
364 | maybe_sgml WHITESPACE
375 | %prec LOWEST_PREC TOKEN_EOF
379 CHARSET_SYM maybe_space STRING maybe_space ';' {
380 CSSParser* p = static_cast<CSSParser*>(parser);
381 $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
382 if ($$ && p->m_styleSheet)
383 p->m_styleSheet->append($$);
385 | CHARSET_SYM error invalid_block {
387 | CHARSET_SYM error ';' {
393 | rule_list rule maybe_sgml {
394 CSSParser* p = static_cast<CSSParser*>(parser);
395 if ($2 && p->m_styleSheet)
396 p->m_styleSheet->append($2);
413 static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
420 /* empty */ { $$ = 0; }
421 | block_rule_list block_rule maybe_sgml {
425 $$ = static_cast<CSSParser*>(parser)->createRuleList();
450 IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
451 $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
453 | IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
456 | IMPORT_SYM error ';' {
459 | IMPORT_SYM error invalid_block {
465 WEBKIT_VARIABLES_SYM maybe_space maybe_media_list '{' maybe_space variables_declaration_list '}' {
466 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, true);
469 WEBKIT_DEFINE_SYM maybe_space variables_media_list '{' maybe_space variables_declaration_list '}' {
470 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, false);
474 variables_media_list:
476 $$ = static_cast<CSSParser*>(parser)->createMediaList();
479 VARIABLES_FOR WHITESPACE media_list {
484 variables_declaration_list:
485 variables_declaration {
488 | variables_decl_list variables_declaration {
493 | variables_decl_list {
496 | error invalid_block_list error {
502 | variables_decl_list error {
508 variables_declaration ';' maybe_space {
511 | variables_declaration invalid_block_list ';' maybe_space {
514 | error ';' maybe_space {
517 | error invalid_block_list error ';' maybe_space {
520 | variables_decl_list variables_declaration ';' maybe_space {
525 | variables_decl_list error ';' maybe_space {
528 | variables_decl_list error invalid_block_list error ';' maybe_space {
533 variables_declaration:
534 variable_name ':' maybe_space expr {
535 $$ = static_cast<CSSParser*>(parser)->addVariable($1, $4);
538 variable_name maybe_space '{' maybe_space declaration_list '}' maybe_space {
539 $$ = static_cast<CSSParser*>(parser)->addVariableDeclarationBlock($1);
542 variable_name error {
546 variable_name ':' maybe_space error expr {
550 variable_name ':' maybe_space {
551 /* @variables { varname: } Just reduce away this variable with no value. */
555 variable_name ':' maybe_space error {
556 /* if we come across rules with invalid values like this case: @variables { varname: *; }, just discard the property/value pair */
568 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
569 static_cast<CSSParser*>(parser)->addNamespace($3, $4);
572 | NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
575 | NAMESPACE_SYM error invalid_block {
578 | NAMESPACE_SYM error ';' {
584 /* empty */ { $$.characters = 0; }
585 | IDENT maybe_space { $$ = $1; }
603 | ':' maybe_space expr maybe_space {
609 '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
611 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
615 media_query_exp_list:
617 CSSParser* p = static_cast<CSSParser*>(parser);
618 $$ = p->createFloatingMediaQueryExpList();
619 $$->append(p->sinkFloatingMediaQueryExp($1));
621 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
623 $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
627 maybe_and_media_query_exp_list:
629 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
631 | MEDIA_AND maybe_space media_query_exp_list {
636 maybe_media_restrictor:
638 $$ = MediaQuery::None;
641 $$ = MediaQuery::Only;
644 $$ = MediaQuery::Not;
649 media_query_exp_list {
650 CSSParser* p = static_cast<CSSParser*>(parser);
651 $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
654 maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
655 CSSParser* p = static_cast<CSSParser*>(parser);
657 $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
663 $$ = static_cast<CSSParser*>(parser)->createMediaList();
670 CSSParser* p = static_cast<CSSParser*>(parser);
671 $$ = p->createMediaList();
672 $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
674 | media_list ',' maybe_space media_query {
677 $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
685 MEDIA_SYM maybe_space media_list '{' maybe_space block_rule_list save_block {
686 $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
688 | MEDIA_SYM maybe_space '{' maybe_space block_rule_list save_block {
689 $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
700 WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name maybe_space '{' maybe_space keyframes_rule '}' {
702 $7->setNameInternal($3);
712 /* empty */ { $$ = static_cast<CSSParser*>(parser)->createKeyframesRule(); }
713 | keyframes_rule keyframe_rule maybe_space {
721 key_list maybe_space '{' maybe_space declaration_list '}' {
722 $$ = static_cast<CSSParser*>(parser)->createKeyframeRule($1);
728 CSSParser* p = static_cast<CSSParser*>(parser);
729 $$ = p->createFloatingValueList();
730 $$->addValue(p->sinkFloatingValue($1));
732 | key_list maybe_space ',' maybe_space key {
733 CSSParser* p = static_cast<CSSParser*>(parser);
736 $$->addValue(p->sinkFloatingValue($5));
741 PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
743 $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
744 CSSParserString& str = $1;
745 if (equalIgnoringCase("from", str.characters, str.length))
747 else if (equalIgnoringCase("to", str.characters, str.length))
755 PAGE_SYM maybe_space page_selector maybe_space
756 '{' maybe_space declarations_and_margins closing_brace {
757 CSSParser* p = static_cast<CSSParser*>(parser);
758 $$ = p->createPageRule(p->sinkFloatingSelector($3));
760 | PAGE_SYM error invalid_block {
763 | PAGE_SYM error ';' {
770 CSSParser* p = static_cast<CSSParser*>(parser);
771 $$ = p->createFloatingSelector();
772 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
775 CSSParser* p = static_cast<CSSParser*>(parser);
778 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
784 CSSParser* p = static_cast<CSSParser*>(parser);
785 $$ = p->createFloatingSelector();
789 declarations_and_margins:
791 | declarations_and_margins margin_box maybe_space declaration_list
796 static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
797 } maybe_space '{' maybe_space declaration_list closing_brace {
798 $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
804 $$ = CSSSelector::TopLeftCornerMarginBox;
807 $$ = CSSSelector::TopLeftMarginBox;
810 $$ = CSSSelector::TopCenterMarginBox;
813 $$ = CSSSelector::TopRightMarginBox;
815 | TOPRIGHTCORNER_SYM {
816 $$ = CSSSelector::TopRightCornerMarginBox;
818 | BOTTOMLEFTCORNER_SYM {
819 $$ = CSSSelector::BottomLeftCornerMarginBox;
822 $$ = CSSSelector::BottomLeftMarginBox;
825 $$ = CSSSelector::BottomCenterMarginBox;
828 $$ = CSSSelector::BottomRightMarginBox;
830 | BOTTOMRIGHTCORNER_SYM {
831 $$ = CSSSelector::BottomRightCornerMarginBox;
834 $$ = CSSSelector::LeftTopMarginBox;
837 $$ = CSSSelector::LeftMiddleMarginBox;
840 $$ = CSSSelector::LeftBottomMarginBox;
843 $$ = CSSSelector::RightTopMarginBox;
846 $$ = CSSSelector::RightMiddleMarginBox;
849 $$ = CSSSelector::RightBottomMarginBox;
854 FONT_FACE_SYM maybe_space
855 '{' maybe_space declaration_list '}' maybe_space {
856 $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
858 | FONT_FACE_SYM error invalid_block {
861 | FONT_FACE_SYM error ';' {
867 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
868 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
869 | '>' maybe_space { $$ = CSSSelector::Child; }
872 maybe_unary_operator:
873 unary_operator { $$ = $1; }
883 selector_list '{' maybe_space declaration_list closing_brace {
884 $$ = static_cast<CSSParser*>(parser)->createStyleRule($1);
889 selector %prec UNIMPORTANT_TOK {
891 CSSParser* p = static_cast<CSSParser*>(parser);
892 $$ = p->reusableSelectorVector();
893 deleteAllValues(*$$);
895 $$->append(p->sinkFloatingSelector($1));
896 p->updateLastSelectorLine();
899 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
901 CSSParser* p = static_cast<CSSParser*>(parser);
903 $$->append(p->sinkFloatingSelector($4));
904 p->updateLastSelectorLine();
908 | selector_list error {
913 selector_with_trailing_whitespace:
914 selector WHITESPACE {
923 | selector_with_trailing_whitespace
927 | selector_with_trailing_whitespace simple_selector
933 CSSParser* p = static_cast<CSSParser*>(parser);
934 CSSSelector* end = $$;
935 while (end->tagHistory())
936 end = end->tagHistory();
937 end->m_relation = CSSSelector::Descendant;
938 end->setTagHistory(p->sinkFloatingSelector($1));
939 if (Document* doc = p->document())
940 doc->setUsesDescendantRules(true);
943 | selector combinator simple_selector {
948 CSSParser* p = static_cast<CSSParser*>(parser);
949 CSSSelector* end = $$;
950 while (end->tagHistory())
951 end = end->tagHistory();
952 end->m_relation = $2;
953 end->setTagHistory(p->sinkFloatingSelector($1));
954 if ($2 == CSSSelector::Child) {
955 if (Document* doc = p->document())
956 doc->setUsesDescendantRules(true);
957 } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
958 if (Document* doc = p->document())
959 doc->setUsesSiblingRules(true);
969 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
970 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
971 | IDENT '|' { $$ = $1; }
976 CSSParser* p = static_cast<CSSParser*>(parser);
977 $$ = p->createFloatingSelector();
978 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
980 | element_name specifier_list {
983 CSSParser* p = static_cast<CSSParser*>(parser);
984 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
989 CSSParser* p = static_cast<CSSParser*>(parser);
990 if ($$ && p->m_defaultNamespace != starAtom)
991 $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
993 | namespace_selector element_name {
994 AtomicString namespacePrefix = $1;
995 CSSParser* p = static_cast<CSSParser*>(parser);
996 $$ = p->createFloatingSelector();
998 $$->m_tag = QualifiedName(namespacePrefix, $2,
999 p->m_styleSheet->determineNamespace(namespacePrefix));
1000 else // FIXME: Shouldn't this case be an error?
1001 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1003 | namespace_selector element_name specifier_list {
1006 AtomicString namespacePrefix = $1;
1007 CSSParser* p = static_cast<CSSParser*>(parser);
1008 if (p->m_styleSheet)
1009 $$->m_tag = QualifiedName(namespacePrefix, $2,
1010 p->m_styleSheet->determineNamespace(namespacePrefix));
1011 else // FIXME: Shouldn't this case be an error?
1012 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1015 | namespace_selector specifier_list {
1018 AtomicString namespacePrefix = $1;
1019 CSSParser* p = static_cast<CSSParser*>(parser);
1020 if (p->m_styleSheet)
1021 $$->m_tag = QualifiedName(namespacePrefix, starAtom,
1022 p->m_styleSheet->determineNamespace(namespacePrefix));
1029 CSSParserString& str = $1;
1030 CSSParser* p = static_cast<CSSParser*>(parser);
1031 Document* doc = p->document();
1032 if (doc && doc->isHTMLDocument())
1037 static UChar star = '*';
1038 $$.characters = ☆
1047 | specifier_list specifier {
1052 CSSParser* p = static_cast<CSSParser*>(parser);
1053 CSSSelector* end = $1;
1054 while (end->tagHistory())
1055 end = end->tagHistory();
1056 end->m_relation = CSSSelector::SubSelector;
1057 end->setTagHistory(p->sinkFloatingSelector($2));
1060 | specifier_list error {
1067 CSSParser* p = static_cast<CSSParser*>(parser);
1068 $$ = p->createFloatingSelector();
1069 $$->m_match = CSSSelector::Id;
1075 if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
1078 CSSParser* p = static_cast<CSSParser*>(parser);
1079 $$ = p->createFloatingSelector();
1080 $$->m_match = CSSSelector::Id;
1093 CSSParser* p = static_cast<CSSParser*>(parser);
1094 $$ = p->createFloatingSelector();
1095 $$->m_match = CSSSelector::Class;
1104 CSSParserString& str = $1;
1105 CSSParser* p = static_cast<CSSParser*>(parser);
1106 Document* doc = p->document();
1107 if (doc && doc->isHTMLDocument())
1114 '[' maybe_space attr_name ']' {
1115 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1116 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1117 $$->m_match = CSSSelector::Set;
1119 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1120 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1121 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1122 $$->m_match = (CSSSelector::Match)$4;
1125 | '[' maybe_space namespace_selector attr_name ']' {
1126 AtomicString namespacePrefix = $3;
1127 CSSParser* p = static_cast<CSSParser*>(parser);
1128 $$ = p->createFloatingSelector();
1129 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1130 p->m_styleSheet->determineNamespace(namespacePrefix)));
1131 $$->m_match = CSSSelector::Set;
1133 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
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::Match)$5;
1146 $$ = CSSSelector::Exact;
1149 $$ = CSSSelector::List;
1152 $$ = CSSSelector::Hyphen;
1155 $$ = CSSSelector::Begin;
1158 $$ = CSSSelector::End;
1161 $$ = CSSSelector::Contain;
1172 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1173 $$->m_match = CSSSelector::PseudoClass;
1176 CSSSelector::PseudoType type = $$->pseudoType();
1177 if (type == CSSSelector::PseudoUnknown)
1179 else if (type == CSSSelector::PseudoEmpty ||
1180 type == CSSSelector::PseudoFirstChild ||
1181 type == CSSSelector::PseudoFirstOfType ||
1182 type == CSSSelector::PseudoLastChild ||
1183 type == CSSSelector::PseudoLastOfType ||
1184 type == CSSSelector::PseudoOnlyChild ||
1185 type == CSSSelector::PseudoOnlyOfType) {
1186 CSSParser* p = static_cast<CSSParser*>(parser);
1187 Document* doc = p->document();
1189 doc->setUsesSiblingRules(true);
1190 } else if (type == CSSSelector::PseudoFirstLine) {
1191 CSSParser* p = static_cast<CSSParser*>(parser);
1192 if (Document* doc = p->document())
1193 doc->setUsesFirstLineRules(true);
1194 } else if (type == CSSSelector::PseudoBefore ||
1195 type == CSSSelector::PseudoAfter) {
1196 CSSParser* p = static_cast<CSSParser*>(parser);
1197 if (Document* doc = p->document())
1198 doc->setUsesBeforeAfterRules(true);
1199 } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) {
1200 CSSParser* p = static_cast<CSSParser*>(parser);
1201 if (Document* doc = p->document())
1202 doc->setUsesLinkRules(true);
1206 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1207 $$->m_match = CSSSelector::PseudoElement;
1210 CSSSelector::PseudoType type = $$->pseudoType();
1211 if (type == CSSSelector::PseudoUnknown)
1213 else if (type == CSSSelector::PseudoFirstLine) {
1214 CSSParser* p = static_cast<CSSParser*>(parser);
1215 if (Document* doc = p->document())
1216 doc->setUsesFirstLineRules(true);
1217 } else if (type == CSSSelector::PseudoBefore ||
1218 type == CSSSelector::PseudoAfter) {
1219 CSSParser* p = static_cast<CSSParser*>(parser);
1220 if (Document* doc = p->document())
1221 doc->setUsesBeforeAfterRules(true);
1224 // used by :nth-*(ax+b)
1225 | ':' FUNCTION maybe_space NTH maybe_space ')' {
1226 CSSParser *p = static_cast<CSSParser*>(parser);
1227 $$ = p->createFloatingSelector();
1228 $$->m_match = CSSSelector::PseudoClass;
1229 $$->setArgument($4);
1231 CSSSelector::PseudoType type = $$->pseudoType();
1232 if (type == CSSSelector::PseudoUnknown)
1234 else if (type == CSSSelector::PseudoNthChild ||
1235 type == CSSSelector::PseudoNthOfType ||
1236 type == CSSSelector::PseudoNthLastChild ||
1237 type == CSSSelector::PseudoNthLastOfType) {
1239 p->document()->setUsesSiblingRules(true);
1243 | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
1244 CSSParser *p = static_cast<CSSParser*>(parser);
1245 $$ = p->createFloatingSelector();
1246 $$->m_match = CSSSelector::PseudoClass;
1247 $$->setArgument(String::number($4 * $5));
1249 CSSSelector::PseudoType type = $$->pseudoType();
1250 if (type == CSSSelector::PseudoUnknown)
1252 else if (type == CSSSelector::PseudoNthChild ||
1253 type == CSSSelector::PseudoNthOfType ||
1254 type == CSSSelector::PseudoNthLastChild ||
1255 type == CSSSelector::PseudoNthLastOfType) {
1257 p->document()->setUsesSiblingRules(true);
1260 // used by :nth-*(odd/even) and :lang
1261 | ':' FUNCTION maybe_space IDENT maybe_space ')' {
1262 CSSParser *p = static_cast<CSSParser*>(parser);
1263 $$ = p->createFloatingSelector();
1264 $$->m_match = CSSSelector::PseudoClass;
1265 $$->setArgument($4);
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);
1280 | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1281 if (!$4 || !$4->isSimple())
1284 CSSParser* p = static_cast<CSSParser*>(parser);
1285 $$ = p->createFloatingSelector();
1286 $$->m_match = CSSSelector::PseudoClass;
1287 $$->setSimpleSelector(p->sinkFloatingSelector($4));
1298 | decl_list declaration {
1306 | error invalid_block_list error {
1315 | decl_list invalid_block_list {
1321 declaration ';' maybe_space {
1324 | declaration invalid_block_list maybe_space {
1327 | declaration invalid_block_list ';' maybe_space {
1330 | error ';' maybe_space {
1333 | error invalid_block_list error ';' maybe_space {
1336 | decl_list declaration ';' maybe_space {
1341 | decl_list error ';' maybe_space {
1344 | decl_list error invalid_block_list error ';' maybe_space {
1350 property ':' maybe_space expr prio {
1352 CSSParser* p = static_cast<CSSParser*>(parser);
1354 p->m_valueList = p->sinkFloatingValueList($4);
1355 int oldParsedProperties = p->m_numParsedProperties;
1356 $$ = p->parseValue($1, $5);
1358 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1359 delete p->m_valueList;
1364 variable_reference maybe_space {
1365 CSSParser* p = static_cast<CSSParser*>(parser);
1366 p->m_valueList = new CSSParserValueList;
1367 p->m_valueList->addValue(p->sinkFloatingValue($1));
1368 int oldParsedProperties = p->m_numParsedProperties;
1369 $$ = p->parseValue(CSSPropertyWebkitVariableDeclarationBlock, false);
1371 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1372 delete p->m_valueList;
1380 property ':' maybe_space error expr prio {
1381 /* The default movable type template has letter-spacing: .none; Handle this by looking for
1382 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1383 up and deleting the shifted expr. */
1387 property ':' maybe_space expr prio error {
1388 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1392 IMPORTANT_SYM maybe_space {
1393 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1397 property ':' maybe_space {
1398 /* div { font-family: } Just reduce away this property with no value. */
1402 property ':' maybe_space error {
1403 /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1407 property invalid_block {
1408 /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
1415 $$ = cssPropertyID($1);
1420 IMPORTANT_SYM maybe_space { $$ = true; }
1421 | /* empty */ { $$ = false; }
1426 CSSParser* p = static_cast<CSSParser*>(parser);
1427 $$ = p->createFloatingValueList();
1428 $$->addValue(p->sinkFloatingValue($1));
1430 | expr operator term {
1431 CSSParser* p = static_cast<CSSParser*>(parser);
1437 v.unit = CSSParserValue::Operator;
1441 $$->addValue(p->sinkFloatingValue($3));
1444 | expr invalid_block_list {
1447 | expr invalid_block_list error {
1468 unary_term { $$ = $1; }
1469 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1470 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1471 | IDENT maybe_space {
1472 $$.id = cssValueKeywordID($1);
1473 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1476 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1477 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1478 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1479 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1480 | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1481 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1482 | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1483 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1487 | variable_reference maybe_space {
1490 | '%' maybe_space { /* Handle width: %; */
1491 $$.id = 0; $$.unit = 0;
1496 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1497 | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1498 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1499 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1500 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1501 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1502 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1503 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1504 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1505 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1506 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1507 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1508 | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1509 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1510 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1511 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1512 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1513 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1514 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1515 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1516 | REMS maybe_space {
1519 $$.unit = CSSPrimitiveValue::CSS_REMS;
1520 CSSParser* p = static_cast<CSSParser*>(parser);
1521 if (Document* doc = p->document())
1522 doc->setUsesRemUnits(true);
1530 $$.unit = CSSPrimitiveValue::CSS_PARSER_VARIABLE_FUNCTION_SYNTAX;
1535 FUNCTION maybe_space expr ')' maybe_space {
1536 CSSParser* p = static_cast<CSSParser*>(parser);
1537 CSSParserFunction* f = p->createFloatingFunction();
1539 f->args = p->sinkFloatingValueList($3);
1541 $$.unit = CSSParserValue::Function;
1544 FUNCTION maybe_space error {
1545 CSSParser* p = static_cast<CSSParser*>(parser);
1546 CSSParserFunction* f = p->createFloatingFunction();
1550 $$.unit = CSSParserValue::Function;
1555 * There is a constraint on the color that it must
1556 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1557 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1560 HEX maybe_space { $$ = $1; }
1561 | IDSEL maybe_space { $$ = $1; }
1565 /* error handling rules */
1571 | error closing_brace {
1577 ATKEYWORD error invalid_block {
1580 | ATKEYWORD error ';' {
1586 error invalid_block {
1591 Seems like the two rules below are trying too much and violating
1592 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1604 '{' error invalid_block_list error closing_brace {
1605 static_cast<CSSParser*>(parser)->invalidBlockHit();
1607 | '{' error closing_brace {
1608 static_cast<CSSParser*>(parser)->invalidBlockHit();
1614 | invalid_block_list error invalid_block