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"
42 using namespace WebCore;
43 using namespace HTMLNames;
45 #define YYENABLE_NLS 0
46 #define YYLTYPE_IS_TRIVIAL 1
47 #define YYMAXDEPTH 10000
50 // FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x
51 #define YYPARSE_PARAM parser
52 #define YYLEX_PARAM parser
63 CSSParserString string;
66 CSSRuleList* ruleList;
67 CSSSelector* selector;
68 Vector<CSSSelector*>* selectorList;
69 CSSSelector::Relation relation;
71 MediaQuery* mediaQuery;
72 MediaQuery::Restrictor mediaQueryRestrictor;
73 MediaQueryExp* mediaQueryExp;
75 CSSParserValueList* valueList;
76 Vector<MediaQueryExp*>* mediaQueryExpList;
77 WebKitCSSKeyframeRule* keyframeRule;
78 WebKitCSSKeyframesRule* keyframesRule;
84 static inline int cssyyerror(const char*)
89 static int cssyylex(YYSTYPE* yylval, void* parser)
91 return static_cast<CSSParser*>(parser)->lex(yylval);
100 %left UNIMPORTANT_TOK
102 %token WHITESPACE SGML_CD
111 %token <string> STRING
112 %right <string> IDENT
115 %nonassoc <string> HEX
116 %nonassoc <string> IDSEL
120 %nonassoc <string> '*'
130 %token WEBKIT_RULE_SYM
131 %token WEBKIT_DECLS_SYM
132 %token WEBKIT_KEYFRAME_RULE_SYM
133 %token WEBKIT_KEYFRAMES_SYM
134 %token WEBKIT_VALUE_SYM
135 %token WEBKIT_MEDIAQUERY_SYM
136 %token WEBKIT_SELECTOR_SYM
137 %token WEBKIT_VARIABLES_SYM
138 %token WEBKIT_DEFINE_SYM
140 %token WEBKIT_VARIABLES_DECLS_SYM
159 %token <number> GRADS
160 %token <number> TURNS
161 %token <number> MSECS
164 %token <number> KHERZ
165 %token <string> DIMEN
166 %token <number> PERCENTAGE
167 %token <number> FLOATTOKEN
168 %token <number> INTEGER
171 %token <string> FUNCTION
172 %token <string> NOTFUNCTION
174 %token <string> UNICODERANGE
176 %token <string> VARCALL
178 %type <relation> combinator
182 %type <rule> valid_rule_or_import
186 %type <rule> font_face
187 %type <rule> keyframes
188 %type <rule> invalid_rule
189 %type <rule> save_block
190 %type <rule> invalid_at
191 %type <rule> invalid_at_list
192 %type <rule> invalid_import
193 %type <rule> invalid_media
195 %type <rule> valid_rule
196 %type <ruleList> block_rule_list
197 %type <rule> block_rule
198 %type <rule> block_valid_rule
199 %type <rule> variables_rule
200 %type <mediaList> variables_media_list
202 %type <string> maybe_ns_prefix
204 %type <string> namespace_selector
206 %type <string> string_or_uri
207 %type <string> ident_or_string
208 %type <string> medium
209 %type <string> hexcolor
211 %type <string> media_feature
212 %type <mediaList> media_list
213 %type <mediaList> maybe_media_list
214 %type <mediaQuery> media_query
215 %type <mediaQueryRestrictor> maybe_media_restrictor
216 %type <valueList> maybe_media_value
217 %type <mediaQueryExp> media_query_exp
218 %type <mediaQueryExpList> media_query_exp_list
219 %type <mediaQueryExpList> maybe_and_media_query_exp_list
221 %type <string> keyframe_name
222 %type <keyframeRule> keyframe_rule
223 %type <keyframesRule> keyframes_rule
224 %type <valueList> key_list
227 %type <integer> property
229 %type <selector> specifier
230 %type <selector> specifier_list
231 %type <selector> simple_selector
232 %type <selector> selector
233 %type <selectorList> selector_list
234 %type <selector> selector_with_trailing_whitespace
235 %type <selector> class
236 %type <selector> attrib
237 %type <selector> pseudo
239 %type <boolean> declaration_list
240 %type <boolean> decl_list
241 %type <boolean> declaration
245 %type <integer> match
246 %type <integer> unary_operator
247 %type <character> operator
249 %type <valueList> expr
251 %type <value> unary_term
252 %type <value> function
254 %type <string> element_name
255 %type <string> attr_name
257 %type <string> variable_name
258 %type <boolean> variables_declaration_list
259 %type <boolean> variables_decl_list
260 %type <boolean> variables_declaration
261 %type <value> variable_reference
266 maybe_charset maybe_sgml import_list variables_list namespace_list rule_list
267 | webkit_rule maybe_space
268 | webkit_decls maybe_space
269 | webkit_value maybe_space
270 | webkit_mediaquery maybe_space
271 | webkit_selector maybe_space
272 | webkit_variables_decls maybe_space
273 | webkit_keyframe_rule maybe_space
276 valid_rule_or_import:
282 WEBKIT_RULE_SYM '{' maybe_space valid_rule_or_import maybe_space '}' {
283 static_cast<CSSParser*>(parser)->m_rule = $4;
287 webkit_keyframe_rule:
288 WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
289 static_cast<CSSParser*>(parser)->m_keyframe = $4;
294 WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' {
299 webkit_variables_decls:
300 WEBKIT_VARIABLES_DECLS_SYM '{' maybe_space variables_declaration_list '}' {
306 WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
307 CSSParser* p = static_cast<CSSParser*>(parser);
309 p->m_valueList = p->sinkFloatingValueList($4);
310 int oldParsedProperties = p->m_numParsedProperties;
311 if (!p->parseValue(p->m_id, p->m_important))
312 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
313 delete p->m_valueList;
320 WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
321 CSSParser* p = static_cast<CSSParser*>(parser);
322 p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
327 WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
329 CSSParser* p = static_cast<CSSParser*>(parser);
330 if (p->m_selectorListForParseSelector)
331 p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
337 /* empty */ %prec UNIMPORTANT_TOK
338 | maybe_space WHITESPACE
344 | maybe_sgml WHITESPACE
355 | %prec LOWEST_PREC TOKEN_EOF
359 CHARSET_SYM maybe_space STRING maybe_space ';' {
360 CSSParser* p = static_cast<CSSParser*>(parser);
361 $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
362 if ($$ && p->m_styleSheet)
363 p->m_styleSheet->append($$);
365 | CHARSET_SYM error invalid_block {
367 | CHARSET_SYM error ';' {
373 | import_list import maybe_sgml {
374 CSSParser* p = static_cast<CSSParser*>(parser);
375 if ($2 && p->m_styleSheet)
376 p->m_styleSheet->append($2);
384 | variables_list variables_rule maybe_sgml {
385 CSSParser* p = static_cast<CSSParser*>(parser);
386 if ($2 && p->m_styleSheet)
387 p->m_styleSheet->append($2);
393 | namespace_list namespace maybe_sgml
398 | rule_list rule maybe_sgml {
399 CSSParser* p = static_cast<CSSParser*>(parser);
400 if ($2 && p->m_styleSheet)
401 p->m_styleSheet->append($2);
421 /* empty */ { $$ = 0; }
422 | block_rule_list block_rule maybe_sgml {
426 $$ = static_cast<CSSParser*>(parser)->createRuleList();
449 IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
450 $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
452 | IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
455 | IMPORT_SYM error ';' {
458 | IMPORT_SYM error invalid_block {
464 WEBKIT_VARIABLES_SYM maybe_space maybe_media_list '{' maybe_space variables_declaration_list '}' {
465 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, true);
468 WEBKIT_DEFINE_SYM maybe_space variables_media_list '{' maybe_space variables_declaration_list '}' {
469 $$ = static_cast<CSSParser*>(parser)->createVariablesRule($3, false);
473 variables_media_list:
475 $$ = static_cast<CSSParser*>(parser)->createMediaList();
478 VARIABLES_FOR WHITESPACE media_list {
483 variables_declaration_list:
484 variables_declaration {
487 | variables_decl_list variables_declaration {
492 | variables_decl_list {
495 | error invalid_block_list error {
501 | variables_decl_list error {
507 variables_declaration ';' maybe_space {
510 | variables_declaration invalid_block_list ';' maybe_space {
513 | error ';' maybe_space {
516 | error invalid_block_list error ';' maybe_space {
519 | variables_decl_list variables_declaration ';' maybe_space {
524 | variables_decl_list error ';' maybe_space {
527 | variables_decl_list error invalid_block_list error ';' maybe_space {
532 variables_declaration:
533 variable_name ':' maybe_space expr {
534 $$ = static_cast<CSSParser*>(parser)->addVariable($1, $4);
537 variable_name maybe_space '{' maybe_space declaration_list '}' maybe_space {
538 $$ = static_cast<CSSParser*>(parser)->addVariableDeclarationBlock($1);
541 variable_name error {
545 variable_name ':' maybe_space error expr {
549 variable_name ':' maybe_space {
550 /* @variables { varname: } Just reduce away this variable with no value. */
554 variable_name ':' maybe_space error {
555 /* if we come across rules with invalid values like this case: @variables { varname: *; }, just discard the property/value pair */
567 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
568 CSSParser* p = static_cast<CSSParser*>(parser);
570 p->m_styleSheet->addNamespace(p, $3, $4);
572 | NAMESPACE_SYM error invalid_block
573 | NAMESPACE_SYM error ';'
577 /* empty */ { $$.characters = 0; }
578 | IDENT WHITESPACE { $$ = $1; }
596 | ':' maybe_space expr maybe_space {
602 '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
604 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
608 media_query_exp_list:
610 CSSParser* p = static_cast<CSSParser*>(parser);
611 $$ = p->createFloatingMediaQueryExpList();
612 $$->append(p->sinkFloatingMediaQueryExp($1));
614 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
616 $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
620 maybe_and_media_query_exp_list:
622 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
624 | MEDIA_AND maybe_space media_query_exp_list {
629 maybe_media_restrictor:
631 $$ = MediaQuery::None;
634 $$ = MediaQuery::Only;
637 $$ = MediaQuery::Not;
642 media_query_exp_list {
643 CSSParser* p = static_cast<CSSParser*>(parser);
644 $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
647 maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
648 CSSParser* p = static_cast<CSSParser*>(parser);
650 $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
656 $$ = static_cast<CSSParser*>(parser)->createMediaList();
663 CSSParser* p = static_cast<CSSParser*>(parser);
664 $$ = p->createMediaList();
665 $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
667 | media_list ',' maybe_space media_query {
670 $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
678 MEDIA_SYM maybe_space media_list '{' maybe_space block_rule_list save_block {
679 $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
681 | MEDIA_SYM maybe_space '{' maybe_space block_rule_list save_block {
682 $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
693 WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name maybe_space '{' maybe_space keyframes_rule '}' {
695 $7->setNameInternal($3);
705 /* empty */ { $$ = static_cast<CSSParser*>(parser)->createKeyframesRule(); }
706 | keyframes_rule keyframe_rule maybe_space {
714 key_list maybe_space '{' maybe_space declaration_list '}' {
715 $$ = static_cast<CSSParser*>(parser)->createKeyframeRule($1);
721 CSSParser* p = static_cast<CSSParser*>(parser);
722 $$ = p->createFloatingValueList();
723 $$->addValue(p->sinkFloatingValue($1));
725 | key_list maybe_space ',' maybe_space key {
726 CSSParser* p = static_cast<CSSParser*>(parser);
729 $$->addValue(p->sinkFloatingValue($5));
734 PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
736 $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
737 CSSParserString& str = $1;
738 if (equalIgnoringCase(static_cast<const String&>(str), "from"))
740 else if (equalIgnoringCase(static_cast<const String&>(str), "to"))
749 PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space
750 '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
759 PAGE_SYM error invalid_block {
762 | PAGE_SYM error ';' {
768 FONT_FACE_SYM maybe_space
769 '{' maybe_space declaration_list '}' maybe_space {
770 $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
772 | FONT_FACE_SYM error invalid_block {
775 | FONT_FACE_SYM error ';' {
781 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
782 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
783 | '>' maybe_space { $$ = CSSSelector::Child; }
792 selector_list '{' maybe_space declaration_list closing_brace {
793 $$ = static_cast<CSSParser*>(parser)->createStyleRule($1);
798 selector %prec UNIMPORTANT_TOK {
800 CSSParser* p = static_cast<CSSParser*>(parser);
801 $$ = p->reusableSelectorVector();
802 deleteAllValues(*$$);
804 $$->append(p->sinkFloatingSelector($1));
807 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
809 CSSParser* p = static_cast<CSSParser*>(parser);
811 $$->append(p->sinkFloatingSelector($4));
815 | selector_list error {
820 selector_with_trailing_whitespace:
821 selector WHITESPACE {
830 | selector_with_trailing_whitespace
834 | selector_with_trailing_whitespace simple_selector
840 CSSParser* p = static_cast<CSSParser*>(parser);
841 CSSSelector* end = $$;
842 while (end->tagHistory())
843 end = end->tagHistory();
844 end->m_relation = CSSSelector::Descendant;
845 end->setTagHistory(p->sinkFloatingSelector($1));
846 if (Document* doc = p->document())
847 doc->setUsesDescendantRules(true);
850 | selector combinator simple_selector {
855 CSSParser* p = static_cast<CSSParser*>(parser);
856 CSSSelector* end = $$;
857 while (end->tagHistory())
858 end = end->tagHistory();
859 end->m_relation = $2;
860 end->setTagHistory(p->sinkFloatingSelector($1));
861 if ($2 == CSSSelector::Child) {
862 if (Document* doc = p->document())
863 doc->setUsesDescendantRules(true);
864 } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
865 if (Document* doc = p->document())
866 doc->setUsesSiblingRules(true);
876 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
877 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
878 | IDENT '|' { $$ = $1; }
883 CSSParser* p = static_cast<CSSParser*>(parser);
884 $$ = p->createFloatingSelector();
885 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
887 | element_name specifier_list {
890 CSSParser* p = static_cast<CSSParser*>(parser);
891 $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
896 CSSParser* p = static_cast<CSSParser*>(parser);
897 if ($$ && p->m_defaultNamespace != starAtom)
898 $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
900 | namespace_selector element_name {
901 AtomicString namespacePrefix = $1;
902 CSSParser* p = static_cast<CSSParser*>(parser);
903 $$ = p->createFloatingSelector();
905 $$->m_tag = QualifiedName(namespacePrefix, $2,
906 p->m_styleSheet->determineNamespace(namespacePrefix));
907 else // FIXME: Shouldn't this case be an error?
908 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
910 | namespace_selector element_name specifier_list {
913 AtomicString namespacePrefix = $1;
914 CSSParser* p = static_cast<CSSParser*>(parser);
916 $$->m_tag = QualifiedName(namespacePrefix, $2,
917 p->m_styleSheet->determineNamespace(namespacePrefix));
918 else // FIXME: Shouldn't this case be an error?
919 $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
922 | namespace_selector specifier_list {
925 AtomicString namespacePrefix = $1;
926 CSSParser* p = static_cast<CSSParser*>(parser);
928 $$->m_tag = QualifiedName(namespacePrefix, starAtom,
929 p->m_styleSheet->determineNamespace(namespacePrefix));
936 CSSParserString& str = $1;
937 CSSParser* p = static_cast<CSSParser*>(parser);
938 Document* doc = p->document();
939 if (doc && doc->isHTMLDocument())
944 static UChar star = '*';
945 $$.characters = ☆
954 | specifier_list specifier {
959 CSSParser* p = static_cast<CSSParser*>(parser);
960 CSSSelector* end = $1;
961 while (end->tagHistory())
962 end = end->tagHistory();
963 end->m_relation = CSSSelector::SubSelector;
964 end->setTagHistory(p->sinkFloatingSelector($2));
967 | specifier_list error {
974 CSSParser* p = static_cast<CSSParser*>(parser);
975 $$ = p->createFloatingSelector();
976 $$->m_match = CSSSelector::Id;
982 if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
985 CSSParser* p = static_cast<CSSParser*>(parser);
986 $$ = p->createFloatingSelector();
987 $$->m_match = CSSSelector::Id;
1000 CSSParser* p = static_cast<CSSParser*>(parser);
1001 $$ = p->createFloatingSelector();
1002 $$->m_match = CSSSelector::Class;
1011 CSSParserString& str = $1;
1012 CSSParser* p = static_cast<CSSParser*>(parser);
1013 Document* doc = p->document();
1014 if (doc && doc->isHTMLDocument())
1021 '[' maybe_space attr_name ']' {
1022 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1023 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1024 $$->m_match = CSSSelector::Set;
1026 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1027 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1028 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1029 $$->m_match = (CSSSelector::Match)$4;
1032 | '[' maybe_space namespace_selector attr_name ']' {
1033 AtomicString namespacePrefix = $3;
1034 CSSParser* p = static_cast<CSSParser*>(parser);
1035 $$ = p->createFloatingSelector();
1036 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1037 p->m_styleSheet->determineNamespace(namespacePrefix)));
1038 $$->m_match = CSSSelector::Set;
1040 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
1041 AtomicString namespacePrefix = $3;
1042 CSSParser* p = static_cast<CSSParser*>(parser);
1043 $$ = p->createFloatingSelector();
1044 $$->setAttribute(QualifiedName(namespacePrefix, $4,
1045 p->m_styleSheet->determineNamespace(namespacePrefix)));
1046 $$->m_match = (CSSSelector::Match)$5;
1053 $$ = CSSSelector::Exact;
1056 $$ = CSSSelector::List;
1059 $$ = CSSSelector::Hyphen;
1062 $$ = CSSSelector::Begin;
1065 $$ = CSSSelector::End;
1068 $$ = CSSSelector::Contain;
1079 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1080 $$->m_match = CSSSelector::PseudoClass;
1083 CSSSelector::PseudoType type = $$->pseudoType();
1084 if (type == CSSSelector::PseudoUnknown)
1086 else if (type == CSSSelector::PseudoEmpty ||
1087 type == CSSSelector::PseudoFirstChild ||
1088 type == CSSSelector::PseudoFirstOfType ||
1089 type == CSSSelector::PseudoLastChild ||
1090 type == CSSSelector::PseudoLastOfType ||
1091 type == CSSSelector::PseudoOnlyChild ||
1092 type == CSSSelector::PseudoOnlyOfType) {
1093 CSSParser* p = static_cast<CSSParser*>(parser);
1094 Document* doc = p->document();
1096 doc->setUsesSiblingRules(true);
1097 } else if (type == CSSSelector::PseudoFirstLine) {
1098 CSSParser* p = static_cast<CSSParser*>(parser);
1099 if (Document* doc = p->document())
1100 doc->setUsesFirstLineRules(true);
1101 } else if (type == CSSSelector::PseudoBefore ||
1102 type == CSSSelector::PseudoAfter) {
1103 CSSParser* p = static_cast<CSSParser*>(parser);
1104 if (Document* doc = p->document())
1105 doc->setUsesBeforeAfterRules(true);
1109 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1110 $$->m_match = CSSSelector::PseudoElement;
1113 CSSSelector::PseudoType type = $$->pseudoType();
1114 if (type == CSSSelector::PseudoUnknown)
1116 else if (type == CSSSelector::PseudoFirstLine) {
1117 CSSParser* p = static_cast<CSSParser*>(parser);
1118 if (Document* doc = p->document())
1119 doc->setUsesFirstLineRules(true);
1120 } else if (type == CSSSelector::PseudoBefore ||
1121 type == CSSSelector::PseudoAfter) {
1122 CSSParser* p = static_cast<CSSParser*>(parser);
1123 if (Document* doc = p->document())
1124 doc->setUsesBeforeAfterRules(true);
1127 // used by :nth-*(ax+b)
1128 | ':' FUNCTION NTH ')' {
1129 CSSParser *p = static_cast<CSSParser*>(parser);
1130 $$ = p->createFloatingSelector();
1131 $$->m_match = CSSSelector::PseudoClass;
1132 $$->setArgument($3);
1134 CSSSelector::PseudoType type = $$->pseudoType();
1135 if (type == CSSSelector::PseudoUnknown)
1137 else if (type == CSSSelector::PseudoNthChild ||
1138 type == CSSSelector::PseudoNthOfType ||
1139 type == CSSSelector::PseudoNthLastChild ||
1140 type == CSSSelector::PseudoNthLastOfType) {
1142 p->document()->setUsesSiblingRules(true);
1146 | ':' FUNCTION INTEGER ')' {
1147 CSSParser *p = static_cast<CSSParser*>(parser);
1148 $$ = p->createFloatingSelector();
1149 $$->m_match = CSSSelector::PseudoClass;
1150 $$->setArgument(String::number($3));
1152 CSSSelector::PseudoType type = $$->pseudoType();
1153 if (type == CSSSelector::PseudoUnknown)
1155 else if (type == CSSSelector::PseudoNthChild ||
1156 type == CSSSelector::PseudoNthOfType ||
1157 type == CSSSelector::PseudoNthLastChild ||
1158 type == CSSSelector::PseudoNthLastOfType) {
1160 p->document()->setUsesSiblingRules(true);
1163 // used by :nth-*(odd/even) and :lang
1164 | ':' FUNCTION IDENT ')' {
1165 CSSParser *p = static_cast<CSSParser*>(parser);
1166 $$ = p->createFloatingSelector();
1167 $$->m_match = CSSSelector::PseudoClass;
1168 $$->setArgument($3);
1171 CSSSelector::PseudoType type = $$->pseudoType();
1172 if (type == CSSSelector::PseudoUnknown)
1174 else if (type == CSSSelector::PseudoNthChild ||
1175 type == CSSSelector::PseudoNthOfType ||
1176 type == CSSSelector::PseudoNthLastChild ||
1177 type == CSSSelector::PseudoNthLastOfType) {
1179 p->document()->setUsesSiblingRules(true);
1183 | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1184 if (!$4 || $4->simpleSelector() || $4->tagHistory())
1187 CSSParser* p = static_cast<CSSParser*>(parser);
1188 $$ = p->createFloatingSelector();
1189 $$->m_match = CSSSelector::PseudoClass;
1190 $$->setSimpleSelector(p->sinkFloatingSelector($4));
1201 | decl_list declaration {
1209 | error invalid_block_list error {
1218 | decl_list invalid_block_list {
1224 declaration ';' maybe_space {
1227 | declaration invalid_block_list ';' maybe_space {
1230 | error ';' maybe_space {
1233 | error invalid_block_list error ';' maybe_space {
1236 | decl_list declaration ';' maybe_space {
1241 | decl_list error ';' maybe_space {
1244 | decl_list error invalid_block_list error ';' maybe_space {
1250 property ':' maybe_space expr prio {
1252 CSSParser* p = static_cast<CSSParser*>(parser);
1254 p->m_valueList = p->sinkFloatingValueList($4);
1255 int oldParsedProperties = p->m_numParsedProperties;
1256 $$ = p->parseValue($1, $5);
1258 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1259 delete p->m_valueList;
1264 variable_reference maybe_space {
1265 CSSParser* p = static_cast<CSSParser*>(parser);
1266 p->m_valueList = new CSSParserValueList;
1267 p->m_valueList->addValue(p->sinkFloatingValue($1));
1268 int oldParsedProperties = p->m_numParsedProperties;
1269 $$ = p->parseValue(CSSPropertyWebkitVariableDeclarationBlock, false);
1271 p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
1272 delete p->m_valueList;
1280 property ':' maybe_space error expr prio {
1281 /* The default movable type template has letter-spacing: .none; Handle this by looking for
1282 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1283 up and deleting the shifted expr. */
1287 property ':' maybe_space expr prio error {
1288 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1292 IMPORTANT_SYM maybe_space {
1293 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1297 property ':' maybe_space {
1298 /* div { font-family: } Just reduce away this property with no value. */
1302 property ':' maybe_space error {
1303 /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1307 property invalid_block {
1308 /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
1315 $$ = cssPropertyID($1);
1320 IMPORTANT_SYM maybe_space { $$ = true; }
1321 | /* empty */ { $$ = false; }
1326 CSSParser* p = static_cast<CSSParser*>(parser);
1327 $$ = p->createFloatingValueList();
1328 $$->addValue(p->sinkFloatingValue($1));
1330 | expr operator term {
1331 CSSParser* p = static_cast<CSSParser*>(parser);
1337 v.unit = CSSParserValue::Operator;
1341 $$->addValue(p->sinkFloatingValue($3));
1362 unary_term { $$ = $1; }
1363 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1364 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1365 | IDENT maybe_space {
1366 $$.id = cssValueKeywordID($1);
1367 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1370 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1371 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1372 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1373 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1374 | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1375 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1376 | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1377 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1381 | variable_reference maybe_space {
1384 | '%' maybe_space { /* Handle width: %; */
1385 $$.id = 0; $$.unit = 0;
1390 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1391 | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1392 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1393 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1394 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1395 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1396 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1397 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1398 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1399 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1400 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1401 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1402 | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1403 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1404 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1405 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1406 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1407 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1408 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1409 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1416 $$.unit = CSSPrimitiveValue::CSS_PARSER_VARIABLE_FUNCTION_SYNTAX;
1421 FUNCTION maybe_space expr ')' maybe_space {
1422 CSSParser* p = static_cast<CSSParser*>(parser);
1423 CSSParserFunction* f = p->createFloatingFunction();
1425 f->args = p->sinkFloatingValueList($3);
1427 $$.unit = CSSParserValue::Function;
1430 FUNCTION maybe_space error {
1431 CSSParser* p = static_cast<CSSParser*>(parser);
1432 CSSParserFunction* f = p->createFloatingFunction();
1436 $$.unit = CSSParserValue::Function;
1441 * There is a constraint on the color that it must
1442 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1443 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1446 HEX maybe_space { $$ = $1; }
1447 | IDSEL maybe_space { $$ = $1; }
1451 /* error handling rules */
1457 | error closing_brace {
1463 ATKEYWORD error invalid_block {
1466 | ATKEYWORD error ';' {
1472 invalid_at maybe_sgml
1473 | invalid_at_list invalid_at maybe_sgml
1489 error invalid_block {
1494 Seems like the two rules below are trying too much and violating
1495 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1507 '{' error invalid_block_list error closing_brace
1508 | '{' error closing_brace
1513 | invalid_block_list error invalid_block