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);
783 | IDENT pseudo_page {
784 CSSParser* p = static_cast<CSSParser*>(parser);
787 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
797 CSSParser* p = static_cast<CSSParser*>(parser);
798 $$ = p->createFloatingSelector();
803 declarations_and_margins:
805 | declarations_and_margins margin_box maybe_space declaration_list
810 static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
811 } maybe_space '{' maybe_space declaration_list closing_brace {
812 $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
818 $$ = CSSSelector::TopLeftCornerMarginBox;
821 $$ = CSSSelector::TopLeftMarginBox;
824 $$ = CSSSelector::TopCenterMarginBox;
827 $$ = CSSSelector::TopRightMarginBox;
829 | TOPRIGHTCORNER_SYM {
830 $$ = CSSSelector::TopRightCornerMarginBox;
832 | BOTTOMLEFTCORNER_SYM {
833 $$ = CSSSelector::BottomLeftCornerMarginBox;
836 $$ = CSSSelector::BottomLeftMarginBox;
839 $$ = CSSSelector::BottomCenterMarginBox;
842 $$ = CSSSelector::BottomRightMarginBox;
844 | BOTTOMRIGHTCORNER_SYM {
845 $$ = CSSSelector::BottomRightCornerMarginBox;
848 $$ = CSSSelector::LeftTopMarginBox;
851 $$ = CSSSelector::LeftMiddleMarginBox;
854 $$ = CSSSelector::LeftBottomMarginBox;
857 $$ = CSSSelector::RightTopMarginBox;
860 $$ = CSSSelector::RightMiddleMarginBox;
863 $$ = CSSSelector::RightBottomMarginBox;
868 FONT_FACE_SYM maybe_space
869 '{' maybe_space declaration_list '}' maybe_space {
870 $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
872 | FONT_FACE_SYM error invalid_block {
875 | FONT_FACE_SYM error ';' {
881 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
882 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
883 | '>' maybe_space { $$ = CSSSelector::Child; }
886 maybe_unary_operator:
887 unary_operator { $$ = $1; }
897 selector_list '{' maybe_space declaration_list closing_brace {
898 CSSParser* p = static_cast<CSSParser*>(parser);
899 $$ = p->createStyleRule($1);
904 selector %prec UNIMPORTANT_TOK {
906 CSSParser* p = static_cast<CSSParser*>(parser);
907 $$ = p->reusableSelectorVector();
908 deleteAllValues(*$$);
910 $$->append(p->sinkFloatingSelector($1));
911 p->updateLastSelectorLineAndPosition();
914 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
916 CSSParser* p = static_cast<CSSParser*>(parser);
918 $$->append(p->sinkFloatingSelector($4));
919 p->updateLastSelectorLineAndPosition();
923 | selector_list error {
928 selector_with_trailing_whitespace:
929 selector WHITESPACE {
938 | selector_with_trailing_whitespace
942 | selector_with_trailing_whitespace simple_selector
948 CSSParser* p = static_cast<CSSParser*>(parser);
949 CSSSelector* end = $$;
950 while (end->tagHistory())
951 end = end->tagHistory();
952 end->m_relation = CSSSelector::Descendant;
953 end->setTagHistory(p->sinkFloatingSelector($1));
954 if (Document* doc = p->document())
955 doc->setUsesDescendantRules(true);
958 | selector combinator simple_selector {
963 CSSParser* p = static_cast<CSSParser*>(parser);
964 CSSSelector* end = $$;
965 while (end->tagHistory())
966 end = end->tagHistory();
967 end->m_relation = $2;
968 end->setTagHistory(p->sinkFloatingSelector($1));
969 if ($2 == CSSSelector::Child) {
970 if (Document* doc = p->document())
971 doc->setUsesDescendantRules(true);
972 } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
973 if (Document* doc = p->document())
974 doc->setUsesSiblingRules(true);
984 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
985 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
986 | IDENT '|' { $$ = $1; }
991 CSSParser* p = static_cast<CSSParser*>(parser);
992 $$ = p->createFloatingSelector();
993 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
995 | element_name specifier_list {
998 CSSParser* p = static_cast<CSSParser*>(parser);
999 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
1004 CSSParser* p = static_cast<CSSParser*>(parser);
1005 if ($$ && p->m_defaultNamespace != starAtom)
1006 $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
1008 | namespace_selector element_name {
1009 AtomicString namespacePrefix = $1;
1010 CSSParser* p = static_cast<CSSParser*>(parser);
1011 $$ = p->createFloatingSelector();
1012 if (p->m_styleSheet)
1013 $$->m_tag = QualifiedName(namespacePrefix, $2,
1014 p->m_styleSheet->determineNamespace(namespacePrefix));
1015 else // FIXME: Shouldn't this case be an error?
1016 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1018 | namespace_selector element_name specifier_list {
1021 AtomicString namespacePrefix = $1;
1022 CSSParser* p = static_cast<CSSParser*>(parser);
1023 if (p->m_styleSheet)
1024 $$->m_tag = QualifiedName(namespacePrefix, $2,
1025 p->m_styleSheet->determineNamespace(namespacePrefix));
1026 else // FIXME: Shouldn't this case be an error?
1027 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
1030 | namespace_selector specifier_list {
1033 AtomicString namespacePrefix = $1;
1034 CSSParser* p = static_cast<CSSParser*>(parser);
1035 if (p->m_styleSheet)
1036 $$->m_tag = QualifiedName(namespacePrefix, starAtom,
1037 p->m_styleSheet->determineNamespace(namespacePrefix));
1044 CSSParserString& str = $1;
1045 CSSParser* p = static_cast<CSSParser*>(parser);
1046 Document* doc = p->document();
1047 if (doc && doc->isHTMLDocument())
1052 static UChar star = '*';
1053 $$.characters = ☆
1062 | specifier_list specifier {
1067 CSSParser* p = static_cast<CSSParser*>(parser);
1068 CSSSelector* end = $1;
1069 while (end->tagHistory())
1070 end = end->tagHistory();
1071 end->m_relation = CSSSelector::SubSelector;
1072 end->setTagHistory(p->sinkFloatingSelector($2));
1075 | specifier_list error {
1082 CSSParser* p = static_cast<CSSParser*>(parser);
1083 $$ = p->createFloatingSelector();
1084 $$->m_match = CSSSelector::Id;
1090 if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
1093 CSSParser* p = static_cast<CSSParser*>(parser);
1094 $$ = p->createFloatingSelector();
1095 $$->m_match = CSSSelector::Id;
1108 CSSParser* p = static_cast<CSSParser*>(parser);
1109 $$ = p->createFloatingSelector();
1110 $$->m_match = CSSSelector::Class;
1119 CSSParserString& str = $1;
1120 CSSParser* p = static_cast<CSSParser*>(parser);
1121 Document* doc = p->document();
1122 if (doc && doc->isHTMLDocument())
1129 '[' maybe_space attr_name ']' {
1130 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1131 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1132 $$->m_match = CSSSelector::Set;
1134 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1135 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1136 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1137 $$->m_match = (CSSSelector::Match)$4;
1140 | '[' maybe_space namespace_selector attr_name ']' {
1141 AtomicString namespacePrefix = $3;
1142 CSSParser* p = static_cast<CSSParser*>(parser);
1143 $$ = p->createFloatingSelector();
1144 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1145 p->m_styleSheet->determineNamespace(namespacePrefix)));
1146 $$->m_match = CSSSelector::Set;
1148 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
1149 AtomicString namespacePrefix = $3;
1150 CSSParser* p = static_cast<CSSParser*>(parser);
1151 $$ = p->createFloatingSelector();
1152 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1153 p->m_styleSheet->determineNamespace(namespacePrefix)));
1154 $$->m_match = (CSSSelector::Match)$5;
1161 $$ = CSSSelector::Exact;
1164 $$ = CSSSelector::List;
1167 $$ = CSSSelector::Hyphen;
1170 $$ = CSSSelector::Begin;
1173 $$ = CSSSelector::End;
1176 $$ = CSSSelector::Contain;
1187 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1188 $$->m_match = CSSSelector::PagePseudoClass;
1191 CSSSelector::PseudoType type = $$->pseudoType();
1192 if (type == CSSSelector::PseudoUnknown)
1198 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1199 $$->m_match = CSSSelector::PseudoClass;
1202 CSSSelector::PseudoType type = $$->pseudoType();
1203 if (type == CSSSelector::PseudoUnknown)
1205 else if (type == CSSSelector::PseudoEmpty ||
1206 type == CSSSelector::PseudoFirstChild ||
1207 type == CSSSelector::PseudoFirstOfType ||
1208 type == CSSSelector::PseudoLastChild ||
1209 type == CSSSelector::PseudoLastOfType ||
1210 type == CSSSelector::PseudoOnlyChild ||
1211 type == CSSSelector::PseudoOnlyOfType) {
1212 CSSParser* p = static_cast<CSSParser*>(parser);
1213 Document* doc = p->document();
1215 doc->setUsesSiblingRules(true);
1216 } else if (type == CSSSelector::PseudoFirstLine) {
1217 CSSParser* p = static_cast<CSSParser*>(parser);
1218 if (Document* doc = p->document())
1219 doc->setUsesFirstLineRules(true);
1220 } else if (type == CSSSelector::PseudoBefore ||
1221 type == CSSSelector::PseudoAfter) {
1222 CSSParser* p = static_cast<CSSParser*>(parser);
1223 if (Document* doc = p->document())
1224 doc->setUsesBeforeAfterRules(true);
1225 } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) {
1226 CSSParser* p = static_cast<CSSParser*>(parser);
1227 if (Document* doc = p->document())
1228 doc->setUsesLinkRules(true);
1232 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1233 $$->m_match = CSSSelector::PseudoElement;
1236 CSSSelector::PseudoType type = $$->pseudoType();
1237 if (type == CSSSelector::PseudoUnknown)
1239 else if (type == CSSSelector::PseudoFirstLine) {
1240 CSSParser* p = static_cast<CSSParser*>(parser);
1241 if (Document* doc = p->document())
1242 doc->setUsesFirstLineRules(true);
1243 } else if (type == CSSSelector::PseudoBefore ||
1244 type == CSSSelector::PseudoAfter) {
1245 CSSParser* p = static_cast<CSSParser*>(parser);
1246 if (Document* doc = p->document())
1247 doc->setUsesBeforeAfterRules(true);
1250 // used by :nth-*(ax+b)
1251 | ':' FUNCTION maybe_space NTH maybe_space ')' {
1252 CSSParser *p = static_cast<CSSParser*>(parser);
1253 $$ = p->createFloatingSelector();
1254 $$->m_match = CSSSelector::PseudoClass;
1255 $$->setArgument($4);
1257 CSSSelector::PseudoType type = $$->pseudoType();
1258 if (type == CSSSelector::PseudoUnknown)
1260 else if (type == CSSSelector::PseudoNthChild ||
1261 type == CSSSelector::PseudoNthOfType ||
1262 type == CSSSelector::PseudoNthLastChild ||
1263 type == CSSSelector::PseudoNthLastOfType) {
1265 p->document()->setUsesSiblingRules(true);
1269 | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
1270 CSSParser *p = static_cast<CSSParser*>(parser);
1271 $$ = p->createFloatingSelector();
1272 $$->m_match = CSSSelector::PseudoClass;
1273 $$->setArgument(String::number($4 * $5));
1275 CSSSelector::PseudoType type = $$->pseudoType();
1276 if (type == CSSSelector::PseudoUnknown)
1278 else if (type == CSSSelector::PseudoNthChild ||
1279 type == CSSSelector::PseudoNthOfType ||
1280 type == CSSSelector::PseudoNthLastChild ||
1281 type == CSSSelector::PseudoNthLastOfType) {
1283 p->document()->setUsesSiblingRules(true);
1286 // used by :nth-*(odd/even) and :lang
1287 | ':' FUNCTION maybe_space IDENT maybe_space ')' {
1288 CSSParser *p = static_cast<CSSParser*>(parser);
1289 $$ = p->createFloatingSelector();
1290 $$->m_match = CSSSelector::PseudoClass;
1291 $$->setArgument($4);
1294 CSSSelector::PseudoType type = $$->pseudoType();
1295 if (type == CSSSelector::PseudoUnknown)
1297 else if (type == CSSSelector::PseudoNthChild ||
1298 type == CSSSelector::PseudoNthOfType ||
1299 type == CSSSelector::PseudoNthLastChild ||
1300 type == CSSSelector::PseudoNthLastOfType) {
1302 p->document()->setUsesSiblingRules(true);
1306 | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1307 if (!$4 || !$4->isSimple())
1310 CSSParser* p = static_cast<CSSParser*>(parser);
1311 $$ = p->createFloatingSelector();
1312 $$->m_match = CSSSelector::PseudoClass;
1313 $$->setSimpleSelector(p->sinkFloatingSelector($4));
1324 | decl_list declaration {
1332 | error invalid_block_list error {
1341 | decl_list invalid_block_list {
1347 declaration ';' maybe_space {
1350 | declaration invalid_block_list maybe_space {
1353 | declaration invalid_block_list ';' maybe_space {
1356 | error ';' maybe_space {
1359 | error invalid_block_list error ';' maybe_space {
1362 | decl_list declaration ';' maybe_space {
1367 | decl_list error ';' maybe_space {
1370 | decl_list error invalid_block_list error ';' maybe_space {
1376 property ':' maybe_space expr prio {
1378 CSSParser* p = static_cast<CSSParser*>(parser);
1380 p->m_valueList = p->sinkFloatingValueList($4);
1381 int oldParsedProperties = p->m_numParsedProperties;
1382 $$ = p->parseValue($1, $5);
1384 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1385 delete p->m_valueList;
1390 variable_reference maybe_space {
1391 CSSParser* p = static_cast<CSSParser*>(parser);
1392 p->m_valueList = new CSSParserValueList;
1393 p->m_valueList->addValue(p->sinkFloatingValue($1));
1394 int oldParsedProperties = p->m_numParsedProperties;
1395 $$ = p->parseValue(CSSPropertyWebkitVariableDeclarationBlock, false);
1397 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1398 delete p->m_valueList;
1406 property ':' maybe_space error expr prio {
1407 /* The default movable type template has letter-spacing: .none; Handle this by looking for
1408 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1409 up and deleting the shifted expr. */
1413 property ':' maybe_space expr prio error {
1414 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1418 IMPORTANT_SYM maybe_space {
1419 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1423 property ':' maybe_space {
1424 /* div { font-family: } Just reduce away this property with no value. */
1428 property ':' maybe_space error {
1429 /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1433 property invalid_block {
1434 /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
1441 $$ = cssPropertyID($1);
1446 IMPORTANT_SYM maybe_space { $$ = true; }
1447 | /* empty */ { $$ = false; }
1452 CSSParser* p = static_cast<CSSParser*>(parser);
1453 $$ = p->createFloatingValueList();
1454 $$->addValue(p->sinkFloatingValue($1));
1456 | expr operator term {
1457 CSSParser* p = static_cast<CSSParser*>(parser);
1463 v.unit = CSSParserValue::Operator;
1467 $$->addValue(p->sinkFloatingValue($3));
1470 | expr invalid_block_list {
1473 | expr invalid_block_list error {
1494 unary_term { $$ = $1; }
1495 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1496 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1497 | IDENT maybe_space {
1498 $$.id = cssValueKeywordID($1);
1499 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1502 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1503 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1504 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1505 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1506 | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1507 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1508 | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1509 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1513 | variable_reference maybe_space {
1516 | '%' maybe_space { /* Handle width: %; */
1517 $$.id = 0; $$.unit = 0;
1522 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1523 | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1524 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1525 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1526 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1527 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1528 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1529 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1530 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1531 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1532 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1533 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1534 | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1535 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1536 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1537 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1538 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1539 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1540 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1541 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1542 | REMS maybe_space {
1545 $$.unit = CSSPrimitiveValue::CSS_REMS;
1546 CSSParser* p = static_cast<CSSParser*>(parser);
1547 if (Document* doc = p->document())
1548 doc->setUsesRemUnits(true);
1556 $$.unit = CSSPrimitiveValue::CSS_PARSER_VARIABLE_FUNCTION_SYNTAX;
1561 FUNCTION maybe_space expr ')' maybe_space {
1562 CSSParser* p = static_cast<CSSParser*>(parser);
1563 CSSParserFunction* f = p->createFloatingFunction();
1565 f->args = p->sinkFloatingValueList($3);
1567 $$.unit = CSSParserValue::Function;
1570 FUNCTION maybe_space error {
1571 CSSParser* p = static_cast<CSSParser*>(parser);
1572 CSSParserFunction* f = p->createFloatingFunction();
1576 $$.unit = CSSParserValue::Function;
1581 * There is a constraint on the color that it must
1582 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1583 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1586 HEX maybe_space { $$ = $1; }
1587 | IDSEL maybe_space { $$ = $1; }
1591 /* error handling rules */
1597 | error closing_brace {
1603 ATKEYWORD error invalid_block {
1606 | ATKEYWORD error ';' {
1612 error invalid_block {
1617 Seems like the two rules below are trying too much and violating
1618 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1630 '{' error invalid_block_list error closing_brace {
1631 static_cast<CSSParser*>(parser)->invalidBlockHit();
1633 | '{' error closing_brace {
1634 static_cast<CSSParser*>(parser)->invalidBlockHit();
1640 | invalid_block_list error invalid_block