4 * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "CSSParser.h"
28 #include "CSSParserMode.h"
29 #include "CSSPrimitiveValue.h"
30 #include "CSSPropertyNames.h"
31 #include "CSSSelector.h"
32 #include "CSSSelectorList.h"
34 #include "HTMLNames.h"
35 #include "MediaList.h"
36 #include "MediaQueryExp.h"
37 #include "StyleRule.h"
38 #include "StyleSheetContents.h"
39 #include "WebKitCSSKeyframeRule.h"
40 #include "WebKitCSSKeyframesRule.h"
41 #include <wtf/FastMalloc.h>
45 using namespace WebCore;
46 using namespace HTMLNames;
48 #define YYMALLOC fastMalloc
49 #define YYFREE fastFree
51 #define YYENABLE_NLS 0
52 #define YYLTYPE_IS_TRIVIAL 1
53 #define YYMAXDEPTH 10000
56 // FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x
57 #define YYPARSE_PARAM parser
58 #define YYLEX_PARAM parser
69 CSSParserString string;
72 Vector<RefPtr<StyleRuleBase> >* ruleList;
73 CSSParserSelector* selector;
74 Vector<OwnPtr<CSSParserSelector> >* selectorList;
75 CSSSelector::MarginBoxType marginBox;
76 CSSSelector::Relation relation;
77 MediaQuerySet* mediaList;
78 MediaQuery* mediaQuery;
79 MediaQuery::Restrictor mediaQueryRestrictor;
80 MediaQueryExp* mediaQueryExp;
82 CSSParserValueList* valueList;
83 Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList;
84 StyleKeyframe* keyframe;
85 Vector<RefPtr<StyleKeyframe> >* keyframeRuleList;
92 static inline int cssyyerror(const char*)
97 static int cssyylex(YYSTYPE* yylval, void* parser)
99 return static_cast<CSSParser*>(parser)->lex(yylval);
106 %nonassoc LOWEST_PREC
108 %left UNIMPORTANT_TOK
110 %token WHITESPACE SGML_CD
119 %token <string> STRING
120 %right <string> IDENT
123 %nonassoc <string> HEX
124 %nonassoc <string> IDSEL
128 %nonassoc <string> '*'
139 %token WEBKIT_RULE_SYM
140 %token WEBKIT_DECLS_SYM
141 %token WEBKIT_KEYFRAME_RULE_SYM
142 %token WEBKIT_KEYFRAMES_SYM
143 %token WEBKIT_VALUE_SYM
144 %token WEBKIT_MEDIAQUERY_SYM
145 %token WEBKIT_SELECTOR_SYM
146 %token WEBKIT_REGION_RULE_SYM
147 %token <marginBox> TOPLEFTCORNER_SYM
148 %token <marginBox> TOPLEFT_SYM
149 %token <marginBox> TOPCENTER_SYM
150 %token <marginBox> TOPRIGHT_SYM
151 %token <marginBox> TOPRIGHTCORNER_SYM
152 %token <marginBox> BOTTOMLEFTCORNER_SYM
153 %token <marginBox> BOTTOMLEFT_SYM
154 %token <marginBox> BOTTOMCENTER_SYM
155 %token <marginBox> BOTTOMRIGHT_SYM
156 %token <marginBox> BOTTOMRIGHTCORNER_SYM
157 %token <marginBox> LEFTTOP_SYM
158 %token <marginBox> LEFTMIDDLE_SYM
159 %token <marginBox> LEFTBOTTOM_SYM
160 %token <marginBox> RIGHTTOP_SYM
161 %token <marginBox> RIGHTMIDDLE_SYM
162 %token <marginBox> RIGHTBOTTOM_SYM
183 %token <number> GRADS
184 %token <number> TURNS
185 %token <number> MSECS
187 %token <number> HERTZ
188 %token <number> KHERTZ
189 %token <string> DIMEN
190 %token <string> INVALIDDIMEN
191 %token <number> PERCENTAGE
192 %token <number> FLOATTOKEN
193 %token <number> INTEGER
202 %token <string> FUNCTION
203 %token <string> ANYFUNCTION
204 %token <string> NOTFUNCTION
205 %token <string> CALCFUNCTION
206 %token <string> MINFUNCTION
207 %token <string> MAXFUNCTION
208 %token <string> VAR_DEFINITION
210 %token <string> UNICODERANGE
212 %type <relation> combinator
215 %type <rule> ignored_charset
219 %type <rule> namespace
221 %type <rule> margin_box
222 %type <rule> font_face
223 %type <rule> keyframes
224 %type <rule> invalid_rule
225 %type <rule> save_block
226 %type <rule> invalid_at
228 %type <rule> valid_rule
229 %type <ruleList> block_rule_list
230 %type <rule> block_rule
231 %type <rule> block_valid_rule
234 %type <string> maybe_ns_prefix
236 %type <string> namespace_selector
238 %type <string> string_or_uri
239 %type <string> ident_or_string
240 %type <string> medium
241 %type <marginBox> margin_sym
243 %type <string> media_feature
244 %type <mediaList> media_list
245 %type <mediaList> maybe_media_list
246 %type <mediaQuery> media_query
247 %type <mediaQueryRestrictor> maybe_media_restrictor
248 %type <valueList> maybe_media_value
249 %type <mediaQueryExp> media_query_exp
250 %type <mediaQueryExpList> media_query_exp_list
251 %type <mediaQueryExpList> maybe_and_media_query_exp_list
253 %type <string> keyframe_name
254 %type <keyframe> keyframe_rule
255 %type <keyframeRuleList> keyframes_rule
256 %type <valueList> key_list
261 %type <selector> specifier
262 %type <selector> specifier_list
263 %type <selector> simple_selector
264 %type <selector> selector
265 %type <selectorList> selector_list
266 %type <selectorList> simple_selector_list
267 %type <selectorList> region_selector
268 %type <selector> selector_with_trailing_whitespace
269 %type <selector> class
270 %type <selector> attrib
271 %type <selector> pseudo
272 %type <selector> pseudo_page
273 %type <selector> page_selector
275 %type <boolean> declaration_list
276 %type <boolean> decl_list
277 %type <boolean> declaration
278 %type <boolean> declarations_and_margins
282 %type <integer> match
283 %type <integer> unary_operator
284 %type <integer> maybe_unary_operator
285 %type <character> operator
287 %type <valueList> expr
289 %type <value> unary_term
290 %type <value> function
291 %type <value> calc_func_term
292 %type <character> calc_func_operator
293 %type <valueList> calc_func_expr
294 %type <valueList> calc_func_expr_list
295 %type <valueList> calc_func_paren_expr
296 %type <value> calc_function
297 %type <string> min_or_max
298 %type <value> min_or_max_function
300 %type <string> element_name
301 %type <string> attr_name
306 maybe_space maybe_charset maybe_sgml rule_list
307 | webkit_rule maybe_space
308 | webkit_decls maybe_space
309 | webkit_value maybe_space
310 | webkit_mediaquery maybe_space
311 | webkit_selector maybe_space
312 | webkit_keyframe_rule maybe_space
316 WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
317 static_cast<CSSParser*>(parser)->m_rule = $4;
321 webkit_keyframe_rule:
322 WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
323 static_cast<CSSParser*>(parser)->m_keyframe = $4;
328 WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' {
334 WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
335 CSSParser* p = static_cast<CSSParser*>(parser);
337 p->m_valueList = p->sinkFloatingValueList($4);
338 int oldParsedProperties = p->m_parsedProperties.size();
339 if (!p->parseValue(p->m_id, p->m_important))
340 p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties);
341 p->m_valueList = nullptr;
347 WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
348 CSSParser* p = static_cast<CSSParser*>(parser);
349 p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
354 WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
356 CSSParser* p = static_cast<CSSParser*>(parser);
357 if (p->m_selectorListForParseSelector)
358 p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
364 /* empty */ %prec UNIMPORTANT_TOK
365 | maybe_space WHITESPACE
371 | maybe_sgml WHITESPACE
382 | %prec LOWEST_PREC TOKEN_EOF
386 CHARSET_SYM maybe_space STRING maybe_space ';' {
387 CSSParser* p = static_cast<CSSParser*>(parser);
389 p->m_styleSheet->parserSetEncodingFromCharsetRule($3);
390 if (p->isExtractingSourceData() && p->m_currentRuleDataStack->isEmpty() && p->m_ruleSourceDataResult)
391 p->addNewRuleToSourceTree(CSSRuleSourceData::createUnknown());
394 | CHARSET_SYM error invalid_block {
396 | CHARSET_SYM error ';' {
401 CHARSET_SYM maybe_space STRING maybe_space ';' {
402 // Ignore any @charset rule not at the beginning of the style sheet.
405 | CHARSET_SYM maybe_space ';' {
412 | rule_list rule maybe_sgml {
413 CSSParser* p = static_cast<CSSParser*>(parser);
414 if ($2 && p->m_styleSheet)
415 p->m_styleSheet->parserAppendRule($2);
432 static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
440 /* empty */ { $$ = 0; }
441 | block_rule_list block_rule maybe_sgml {
445 $$ = static_cast<CSSParser*>(parser)->createRuleList();
467 at_import_header_end_maybe_space:
469 CSSParser* p = static_cast<CSSParser*>(parser);
470 p->markRuleHeaderEnd();
471 p->markRuleBodyStart();
477 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::IMPORT_RULE);
482 before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list ';' {
483 $$ = static_cast<CSSParser*>(parser)->createImportRule($4, $6);
485 | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list TOKEN_EOF {
486 $$ = static_cast<CSSParser*>(parser)->createImportRule($4, $6);
488 | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
490 static_cast<CSSParser*>(parser)->popRuleData();
492 | before_import_rule IMPORT_SYM error ';' {
494 static_cast<CSSParser*>(parser)->popRuleData();
496 | before_import_rule IMPORT_SYM error invalid_block {
498 static_cast<CSSParser*>(parser)->popRuleData();
503 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
504 static_cast<CSSParser*>(parser)->addNamespace($3, $4);
507 | NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
510 | NAMESPACE_SYM error invalid_block {
513 | NAMESPACE_SYM error ';' {
519 /* empty */ { $$.characters = 0; }
520 | IDENT maybe_space { $$ = $1; }
538 | ':' maybe_space expr maybe_space {
544 '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
546 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
550 media_query_exp_list:
552 CSSParser* p = static_cast<CSSParser*>(parser);
553 $$ = p->createFloatingMediaQueryExpList();
554 $$->append(p->sinkFloatingMediaQueryExp($1));
556 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
558 $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
562 maybe_and_media_query_exp_list:
564 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
566 | MEDIA_AND maybe_space media_query_exp_list {
571 maybe_media_restrictor:
573 $$ = MediaQuery::None;
576 $$ = MediaQuery::Only;
579 $$ = MediaQuery::Not;
584 media_query_exp_list {
585 CSSParser* p = static_cast<CSSParser*>(parser);
586 $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
589 maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
590 CSSParser* p = static_cast<CSSParser*>(parser);
592 $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
598 $$ = static_cast<CSSParser*>(parser)->createMediaQuerySet();
605 CSSParser* p = static_cast<CSSParser*>(parser);
606 $$ = p->createMediaQuerySet();
607 $$->addMediaQuery(p->sinkFloatingMediaQuery($1));
608 p->updateLastMediaLine($$);
610 | media_list ',' maybe_space media_query {
613 CSSParser* p = static_cast<CSSParser*>(parser);
614 $$->addMediaQuery(p->sinkFloatingMediaQuery($4));
615 p->updateLastMediaLine($$);
625 static_cast<CSSParser*>(parser)->markRuleBodyStart();
631 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::MEDIA_RULE);
635 at_rule_header_end_maybe_space:
637 static_cast<CSSParser*>(parser)->markRuleHeaderEnd();
642 before_media_rule MEDIA_SYM maybe_space media_list at_rule_header_end '{' at_rule_body_start maybe_space block_rule_list save_block {
643 $$ = static_cast<CSSParser*>(parser)->createMediaRule($4, $9);
645 | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space block_rule_list save_block {
646 $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $7);
648 | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space ';' {
650 static_cast<CSSParser*>(parser)->popRuleData();
660 before_keyframes_rule:
662 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::KEYFRAMES_RULE);
667 before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space keyframes_rule closing_brace {
668 $$ = static_cast<CSSParser*>(parser)->createKeyframesRule($4, static_cast<CSSParser*>(parser)->sinkFloatingKeyframeVector($9));
678 /* empty */ { $$ = static_cast<CSSParser*>(parser)->createFloatingKeyframeVector(); }
679 | keyframes_rule keyframe_rule maybe_space {
687 key_list maybe_space '{' maybe_space declaration_list '}' {
688 $$ = static_cast<CSSParser*>(parser)->createKeyframe($1);
694 CSSParser* p = static_cast<CSSParser*>(parser);
695 $$ = p->createFloatingValueList();
696 $$->addValue(p->sinkFloatingValue($1));
698 | key_list maybe_space ',' maybe_space key {
699 CSSParser* p = static_cast<CSSParser*>(parser);
702 $$->addValue(p->sinkFloatingValue($5));
707 PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
709 $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
710 CSSParserString& str = $1;
711 if (equalIgnoringCase("from", str.characters, str.length))
713 else if (equalIgnoringCase("to", str.characters, str.length))
722 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::PAGE_RULE);
727 before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end_maybe_space
728 '{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace {
729 CSSParser* p = static_cast<CSSParser*>(parser);
731 $$ = p->createPageRule(p->sinkFloatingSelector($4));
733 // Clear properties in the invalid @page rule.
734 p->clearProperties();
735 // Also clear margin at-rules here once we fully implement margin at-rules parsing.
737 static_cast<CSSParser*>(parser)->popRuleData();
740 | before_page_rule PAGE_SYM error invalid_block {
741 static_cast<CSSParser*>(parser)->popRuleData();
744 | before_page_rule PAGE_SYM error ';' {
745 static_cast<CSSParser*>(parser)->popRuleData();
752 CSSParser* p = static_cast<CSSParser*>(parser);
753 $$ = p->createFloatingSelector();
754 $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
757 | IDENT pseudo_page {
758 CSSParser* p = static_cast<CSSParser*>(parser);
761 $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
771 CSSParser* p = static_cast<CSSParser*>(parser);
772 $$ = p->createFloatingSelector();
777 declarations_and_margins:
779 | declarations_and_margins margin_box maybe_space declaration_list
784 static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
785 } maybe_space '{' maybe_space declaration_list closing_brace {
786 $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
792 $$ = CSSSelector::TopLeftCornerMarginBox;
795 $$ = CSSSelector::TopLeftMarginBox;
798 $$ = CSSSelector::TopCenterMarginBox;
801 $$ = CSSSelector::TopRightMarginBox;
803 | TOPRIGHTCORNER_SYM {
804 $$ = CSSSelector::TopRightCornerMarginBox;
806 | BOTTOMLEFTCORNER_SYM {
807 $$ = CSSSelector::BottomLeftCornerMarginBox;
810 $$ = CSSSelector::BottomLeftMarginBox;
813 $$ = CSSSelector::BottomCenterMarginBox;
816 $$ = CSSSelector::BottomRightMarginBox;
818 | BOTTOMRIGHTCORNER_SYM {
819 $$ = CSSSelector::BottomRightCornerMarginBox;
822 $$ = CSSSelector::LeftTopMarginBox;
825 $$ = CSSSelector::LeftMiddleMarginBox;
828 $$ = CSSSelector::LeftBottomMarginBox;
831 $$ = CSSSelector::RightTopMarginBox;
834 $$ = CSSSelector::RightMiddleMarginBox;
837 $$ = CSSSelector::RightBottomMarginBox;
841 before_font_face_rule:
843 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::FONT_FACE_RULE);
848 before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space
849 '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
850 $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
852 | before_font_face_rule FONT_FACE_SYM error invalid_block {
854 static_cast<CSSParser*>(parser)->popRuleData();
856 | before_font_face_rule FONT_FACE_SYM error ';' {
858 static_cast<CSSParser*>(parser)->popRuleData();
865 static_cast<CSSParser*>(parser)->setReusableRegionSelectorVector($1);
866 $$ = static_cast<CSSParser*>(parser)->reusableRegionSelectorVector();
874 WEBKIT_REGION_RULE_SYM WHITESPACE region_selector '{' maybe_space block_rule_list save_block {
876 $$ = static_cast<CSSParser*>(parser)->createRegionRule($3, $6);
883 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
884 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
885 | '>' maybe_space { $$ = CSSSelector::Child; }
888 maybe_unary_operator:
889 unary_operator { $$ = $1; }
898 maybe_space_before_declaration:
900 static_cast<CSSParser*>(parser)->markPropertyStart();
904 before_selector_list:
906 static_cast<CSSParser*>(parser)->markRuleHeaderStart(CSSRuleSourceData::STYLE_RULE);
912 static_cast<CSSParser*>(parser)->markRuleHeaderEnd();
917 before_selector_list selector_list at_rule_header_end '{' maybe_space_before_declaration declaration_list closing_brace {
918 CSSParser* p = static_cast<CSSParser*>(parser);
919 $$ = p->createStyleRule($2);
924 selector %prec UNIMPORTANT_TOK {
926 CSSParser* p = static_cast<CSSParser*>(parser);
927 $$ = p->reusableSelectorVector();
929 $$->append(p->sinkFloatingSelector($1));
930 p->updateLastSelectorLineAndPosition();
933 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
935 CSSParser* p = static_cast<CSSParser*>(parser);
937 $$->append(p->sinkFloatingSelector($4));
938 p->updateLastSelectorLineAndPosition();
942 | selector_list error {
947 selector_with_trailing_whitespace:
948 selector WHITESPACE {
957 | selector_with_trailing_whitespace
961 | selector_with_trailing_whitespace simple_selector
967 CSSParser* p = static_cast<CSSParser*>(parser);
968 CSSParserSelector* end = $$;
969 while (end->tagHistory())
970 end = end->tagHistory();
971 end->setRelation(CSSSelector::Descendant);
972 end->setTagHistory(p->sinkFloatingSelector($1));
975 | selector combinator simple_selector {
980 CSSParser* p = static_cast<CSSParser*>(parser);
981 CSSParserSelector* end = $$;
982 while (end->tagHistory())
983 end = end->tagHistory();
984 end->setRelation($2);
985 end->setTagHistory(p->sinkFloatingSelector($1));
994 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
995 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
996 | IDENT '|' { $$ = $1; }
1001 CSSParser* p = static_cast<CSSParser*>(parser);
1002 $$ = p->createFloatingSelector();
1003 $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
1005 | element_name specifier_list {
1008 static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, $1, $$);
1013 static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, starAtom, $$);
1015 | namespace_selector element_name {
1016 CSSParser* p = static_cast<CSSParser*>(parser);
1017 $$ = p->createFloatingSelector();
1018 $$->setTag(p->determineNameInNamespace($1, $2));
1020 | namespace_selector element_name specifier_list {
1023 static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, $2, $$);
1025 | namespace_selector specifier_list {
1028 static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, starAtom, $$);
1032 simple_selector_list:
1033 simple_selector %prec UNIMPORTANT_TOK {
1035 CSSParser* p = static_cast<CSSParser*>(parser);
1036 $$ = p->createFloatingSelectorVector();
1037 $$->append(p->sinkFloatingSelector($1));
1041 | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK {
1043 CSSParser* p = static_cast<CSSParser*>(parser);
1045 $$->append(p->sinkFloatingSelector($5));
1049 | simple_selector_list error {
1056 CSSParserString& str = $1;
1057 CSSParser* p = static_cast<CSSParser*>(parser);
1058 if (p->m_context.isHTMLDocument)
1063 static UChar star = '*';
1064 $$.characters = ☆
1073 | specifier_list specifier {
1077 $$ = static_cast<CSSParser*>(parser)->updateSpecifiers($1, $2);
1079 | specifier_list error {
1086 CSSParser* p = static_cast<CSSParser*>(parser);
1087 $$ = p->createFloatingSelector();
1088 $$->setMatch(CSSSelector::Id);
1089 if (p->m_context.mode == CSSQuirksMode)
1094 if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
1097 CSSParser* p = static_cast<CSSParser*>(parser);
1098 $$ = p->createFloatingSelector();
1099 $$->setMatch(CSSSelector::Id);
1100 if (p->m_context.mode == CSSQuirksMode)
1112 CSSParser* p = static_cast<CSSParser*>(parser);
1113 $$ = p->createFloatingSelector();
1114 $$->setMatch(CSSSelector::Class);
1115 if (p->m_context.mode == CSSQuirksMode)
1123 CSSParserString& str = $1;
1124 CSSParser* p = static_cast<CSSParser*>(parser);
1125 if (p->m_context.isHTMLDocument)
1132 '[' maybe_space attr_name ']' {
1133 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1134 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1135 $$->setMatch(CSSSelector::Set);
1137 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
1138 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1139 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
1140 $$->setMatch((CSSSelector::Match)$4);
1143 | '[' maybe_space namespace_selector attr_name ']' {
1144 CSSParser* p = static_cast<CSSParser*>(parser);
1145 $$ = p->createFloatingSelector();
1146 $$->setAttribute(p->determineNameInNamespace($3, $4));
1147 $$->setMatch(CSSSelector::Set);
1149 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
1150 CSSParser* p = static_cast<CSSParser*>(parser);
1151 $$ = p->createFloatingSelector();
1152 $$->setAttribute(p->determineNameInNamespace($3, $4));
1153 $$->setMatch((CSSSelector::Match)$5);
1160 $$ = CSSSelector::Exact;
1163 $$ = CSSSelector::List;
1166 $$ = CSSSelector::Hyphen;
1169 $$ = CSSSelector::Begin;
1172 $$ = CSSSelector::End;
1175 $$ = CSSSelector::Contain;
1186 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1187 $$->setMatch(CSSSelector::PagePseudoClass);
1190 CSSSelector::PseudoType type = $$->pseudoType();
1191 if (type == CSSSelector::PseudoUnknown)
1197 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1198 $$->setMatch(CSSSelector::PseudoClass);
1201 CSSSelector::PseudoType type = $$->pseudoType();
1202 if (type == CSSSelector::PseudoUnknown)
1206 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
1207 $$->setMatch(CSSSelector::PseudoElement);
1210 // FIXME: This call is needed to force selector to compute the pseudoType early enough.
1213 // use by :-webkit-any.
1214 // FIXME: should we support generic selectors here or just simple_selectors?
1215 // Use simple_selector_list for now to match -moz-any.
1216 // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some
1217 // related discussion with respect to :not.
1218 | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' {
1220 CSSParser *p = static_cast<CSSParser*>(parser);
1221 $$ = p->createFloatingSelector();
1222 $$->setMatch(CSSSelector::PseudoClass);
1223 $$->adoptSelectorVector(*p->sinkFloatingSelectorVector($4));
1226 CSSSelector::PseudoType type = $$->pseudoType();
1227 if (type != CSSSelector::PseudoAny)
1232 // used by :nth-*(ax+b)
1233 | ':' FUNCTION maybe_space NTH maybe_space ')' {
1234 CSSParser *p = static_cast<CSSParser*>(parser);
1235 $$ = p->createFloatingSelector();
1236 $$->setMatch(CSSSelector::PseudoClass);
1237 $$->setArgument($4);
1239 CSSSelector::PseudoType type = $$->pseudoType();
1240 if (type == CSSSelector::PseudoUnknown)
1244 | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
1245 CSSParser *p = static_cast<CSSParser*>(parser);
1246 $$ = p->createFloatingSelector();
1247 $$->setMatch(CSSSelector::PseudoClass);
1248 $$->setArgument(String::number($4 * $5));
1250 CSSSelector::PseudoType type = $$->pseudoType();
1251 if (type == CSSSelector::PseudoUnknown)
1254 // used by :nth-*(odd/even) and :lang
1255 | ':' FUNCTION maybe_space IDENT maybe_space ')' {
1256 CSSParser *p = static_cast<CSSParser*>(parser);
1257 $$ = p->createFloatingSelector();
1258 $$->setMatch(CSSSelector::PseudoClass);
1259 $$->setArgument($4);
1262 CSSSelector::PseudoType type = $$->pseudoType();
1263 if (type == CSSSelector::PseudoUnknown)
1265 else if (type == CSSSelector::PseudoNthChild ||
1266 type == CSSSelector::PseudoNthOfType ||
1267 type == CSSSelector::PseudoNthLastChild ||
1268 type == CSSSelector::PseudoNthLastOfType) {
1269 if (!isValidNthToken($4))
1274 | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
1275 if (!$4 || !$4->isSimple())
1278 CSSParser* p = static_cast<CSSParser*>(parser);
1279 $$ = p->createFloatingSelector();
1280 $$->setMatch(CSSSelector::PseudoClass);
1282 Vector<OwnPtr<CSSParserSelector> > selectorVector;
1283 selectorVector.append(p->sinkFloatingSelector($4));
1284 $$->adoptSelectorVector(selectorVector);
1296 | decl_list declaration {
1304 | error invalid_block_list error {
1313 | decl_list invalid_block_list {
1319 declaration ';' maybe_space {
1320 CSSParser* p = static_cast<CSSParser*>(parser);
1321 p->markPropertyStart();
1324 | declaration invalid_block_list maybe_space {
1327 | declaration invalid_block_list ';' maybe_space {
1330 | error ';' maybe_space {
1331 CSSParser* p = static_cast<CSSParser*>(parser);
1332 p->markPropertyStart();
1335 | error invalid_block_list error ';' maybe_space {
1338 | decl_list declaration ';' maybe_space {
1339 CSSParser* p = static_cast<CSSParser*>(parser);
1340 p->markPropertyStart();
1345 | decl_list error ';' maybe_space {
1346 CSSParser* p = static_cast<CSSParser*>(parser);
1347 p->markPropertyStart();
1350 | decl_list error invalid_block_list error ';' maybe_space {
1351 CSSParser* p = static_cast<CSSParser*>(parser);
1352 p->markPropertyStart();
1358 VAR_DEFINITION ':' maybe_space expr prio {
1359 #if ENABLE(CSS_VARIABLES)
1360 CSSParser* p = static_cast<CSSParser*>(parser);
1361 p->storeVariableDeclaration($1, p->sinkFloatingValueList($4), $5);
1363 p->markPropertyEnd($5, true);
1369 property ':' maybe_space expr prio {
1371 CSSParser* p = static_cast<CSSParser*>(parser);
1372 bool isPropertyParsed = false;
1374 p->m_valueList = p->sinkFloatingValueList($4);
1375 int oldParsedProperties = p->m_parsedProperties.size();
1376 $$ = p->parseValue(static_cast<CSSPropertyID>($1), $5);
1378 p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties);
1380 isPropertyParsed = true;
1381 p->m_valueList = nullptr;
1383 p->markPropertyEnd($5, isPropertyParsed);
1390 property ':' maybe_space error expr prio {
1391 /* The default movable type template has letter-spacing: .none; Handle this by looking for
1392 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1393 up and deleting the shifted expr. */
1394 CSSParser* p = static_cast<CSSParser*>(parser);
1395 p->markPropertyEnd(false, false);
1399 property ':' maybe_space expr prio error {
1400 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1401 CSSParser* p = static_cast<CSSParser*>(parser);
1402 p->markPropertyEnd(false, false);
1406 IMPORTANT_SYM maybe_space {
1407 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1411 property ':' maybe_space {
1412 /* div { font-family: } Just reduce away this property with no value. */
1413 CSSParser* p = static_cast<CSSParser*>(parser);
1414 p->markPropertyEnd(false, false);
1418 property ':' maybe_space error {
1419 /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1420 CSSParser* p = static_cast<CSSParser*>(parser);
1421 p->markPropertyEnd(false, false);
1425 property invalid_block {
1426 /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
1433 $$ = cssPropertyID($1);
1438 IMPORTANT_SYM maybe_space { $$ = true; }
1439 | /* empty */ { $$ = false; }
1444 CSSParser* p = static_cast<CSSParser*>(parser);
1445 $$ = p->createFloatingValueList();
1446 $$->addValue(p->sinkFloatingValue($1));
1448 | expr operator term {
1449 CSSParser* p = static_cast<CSSParser*>(parser);
1455 v.unit = CSSParserValue::Operator;
1459 $$->addValue(p->sinkFloatingValue($3));
1462 | expr invalid_block_list {
1465 | expr invalid_block_list error {
1486 unary_term { $$ = $1; }
1487 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1488 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1489 | IDENT maybe_space {
1490 $$.id = cssValueKeywordID($1);
1491 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1494 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1495 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1496 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1497 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1498 | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1499 | HEX maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1500 | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1501 | VARFUNCTION maybe_space IDENT ')' maybe_space {
1502 #if ENABLE(CSS_VARIABLES)
1505 $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME;
1508 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1515 | min_or_max_function {
1518 | '%' maybe_space { /* Handle width: %; */
1519 $$.id = 0; $$.unit = 0;
1524 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1525 | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1526 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1527 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1528 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1529 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1530 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1531 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1532 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1533 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1534 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1535 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1536 | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
1537 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1538 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1539 | HERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1540 | KHERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1541 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1542 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
1543 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1544 | REMS maybe_space {
1547 $$.unit = CSSPrimitiveValue::CSS_REMS;
1548 CSSParser* p = static_cast<CSSParser*>(parser);
1549 if (p->m_styleSheet)
1550 p->m_styleSheet->parserSetUsesRemUnits(true);
1552 | VW maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VW; }
1553 | VH maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VH; }
1554 | VMIN maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VMIN; }
1555 | DPPX maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPPX; }
1556 | DPI maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPI; }
1557 | DPCM maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPCM; }
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 expr TOKEN_EOF {
1571 CSSParser* p = static_cast<CSSParser*>(parser);
1572 CSSParserFunction* f = p->createFloatingFunction();
1574 f->args = p->sinkFloatingValueList($3);
1576 $$.unit = CSSParserValue::Function;
1579 FUNCTION maybe_space ')' maybe_space {
1580 CSSParser* p = static_cast<CSSParser*>(parser);
1581 CSSParserFunction* f = p->createFloatingFunction();
1583 CSSParserValueList* valueList = p->createFloatingValueList();
1584 f->args = p->sinkFloatingValueList(valueList);
1586 $$.unit = CSSParserValue::Function;
1589 FUNCTION maybe_space error {
1590 CSSParser* p = static_cast<CSSParser*>(parser);
1591 CSSParserFunction* f = p->createFloatingFunction();
1595 $$.unit = CSSParserValue::Function;
1601 unary_term { $$ = $1; }
1602 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1620 calc_func_paren_expr:
1621 '(' maybe_space calc_func_expr maybe_space ')' maybe_space {
1626 v.unit = CSSParserValue::Operator;
1628 $$->insertValueAt(0, v);
1636 calc_func_term maybe_space {
1637 CSSParser* p = static_cast<CSSParser*>(parser);
1638 $$ = p->createFloatingValueList();
1639 $$->addValue(p->sinkFloatingValue($1));
1641 | calc_func_expr calc_func_operator calc_func_term {
1642 CSSParser* p = static_cast<CSSParser*>(parser);
1647 v.unit = CSSParserValue::Operator;
1650 $$->addValue(p->sinkFloatingValue($3));
1655 | calc_func_expr calc_func_operator calc_func_paren_expr {
1656 if ($1 && $2 && $3) {
1660 v.unit = CSSParserValue::Operator;
1667 | calc_func_paren_expr
1668 | calc_func_expr error {
1673 calc_func_expr_list:
1677 | calc_func_expr_list ',' maybe_space calc_func_expr {
1682 v.unit = CSSParserValue::Operator;
1692 CALCFUNCTION maybe_space calc_func_expr ')' maybe_space {
1693 CSSParser* p = static_cast<CSSParser*>(parser);
1694 CSSParserFunction* f = p->createFloatingFunction();
1696 f->args = p->sinkFloatingValueList($3);
1698 $$.unit = CSSParserValue::Function;
1701 | CALCFUNCTION maybe_space error {
1716 min_or_max_function:
1717 min_or_max maybe_space calc_func_expr_list ')' maybe_space {
1718 CSSParser* p = static_cast<CSSParser*>(parser);
1719 CSSParserFunction* f = p->createFloatingFunction();
1721 f->args = p->sinkFloatingValueList($3);
1723 $$.unit = CSSParserValue::Function;
1726 | min_or_max maybe_space error {
1731 /* error handling rules */
1737 | error closing_brace {
1743 ATKEYWORD error invalid_block {
1746 | ATKEYWORD error ';' {
1752 error invalid_block {
1757 Seems like the two rules below are trying too much and violating
1758 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1770 '{' error invalid_block_list error closing_brace {
1771 static_cast<CSSParser*>(parser)->invalidBlockHit();
1773 | '{' error closing_brace {
1774 static_cast<CSSParser*>(parser)->invalidBlockHit();
1780 | invalid_block_list error invalid_block