• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 %{
2 
3 /*
4  *  Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
5  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7  *  Copyright (C) 2008 Eric Seidel <eric@webkit.org>
8  *  Copyright (C) 2012 Intel Corporation. All rights reserved.
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #include "config.h"
27 
28 #include "CSSPropertyNames.h"
29 #include "HTMLNames.h"
30 #include "core/css/CSSKeyframeRule.h"
31 #include "core/css/CSSKeyframesRule.h"
32 #include "core/css/parser/BisonCSSParser.h"
33 #include "core/css/parser/CSSParserMode.h"
34 #include "core/css/CSSPrimitiveValue.h"
35 #include "core/css/CSSSelector.h"
36 #include "core/css/CSSSelectorList.h"
37 #include "core/css/MediaList.h"
38 #include "core/css/MediaQueryExp.h"
39 #include "core/css/StyleRule.h"
40 #include "core/css/StyleSheetContents.h"
41 #include "core/dom/Document.h"
42 #include "wtf/FastMalloc.h"
43 #include <stdlib.h>
44 #include <string.h>
45 
46 using namespace blink;
47 using namespace HTMLNames;
48 
49 #define YYMALLOC fastMalloc
50 #define YYFREE fastFree
51 
52 #define YYENABLE_NLS 0
53 #define YYLTYPE_IS_TRIVIAL 1
54 #define YYMAXDEPTH 10000
55 #define YYDEBUG 0
56 
57 #if YYDEBUG > 0
58 #define YYPRINT(File,Type,Value) if (isCSSTokenAString(Type)) YYFPRINTF(File, "%s", String((Value).string).utf8().data())
59 #endif
60 
61 %}
62 
63 %pure-parser
64 
65 %parse-param { BisonCSSParser* parser }
66 %lex-param { BisonCSSParser* parser }
67 
68 %union {
69     bool boolean;
70     char character;
71     int integer;
72     double number;
73     CSSParserString string;
74 
75     StyleRuleBase* rule;
76     // The content of the three below HeapVectors are guaranteed to be kept alive by
77     // the corresponding m_parsedRules, m_floatingMediaQueryExpList, and m_parsedKeyFrames
78     // lists in BisonCSSParser.h.
79     WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >* ruleList;
80     WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* mediaQueryExpList;
81     WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeRuleList;
82     CSSParserSelector* selector;
83     Vector<OwnPtr<CSSParserSelector> >* selectorList;
84     CSSSelector::MarginBoxType marginBox;
85     CSSSelector::Relation relation;
86     CSSSelector::AttributeMatchType attributeMatchType;
87     MediaQuerySet* mediaList;
88     MediaQuery* mediaQuery;
89     MediaQuery::Restrictor mediaQueryRestrictor;
90     MediaQueryExp* mediaQueryExp;
91     CSSParserValue value;
92     CSSParserValueList* valueList;
93     StyleKeyframe* keyframe;
94     float val;
95     CSSPropertyID id;
96     CSSParserLocation location;
97 }
98 
99 %{
100 
cssyyerror(void *,const char *)101 static inline int cssyyerror(void*, const char*)
102 {
103     return 1;
104 }
105 
106 #if YYDEBUG > 0
isCSSTokenAString(int yytype)107 static inline bool isCSSTokenAString(int yytype)
108 {
109     switch (yytype) {
110     case IDENT:
111     case STRING:
112     case NTH:
113     case HEX:
114     case IDSEL:
115     case DIMEN:
116     case INVALIDDIMEN:
117     case URI:
118     case FUNCTION:
119     case ANYFUNCTION:
120     case HOSTFUNCTION:
121     case HOSTCONTEXTFUNCTION:
122     case NOTFUNCTION:
123     case CALCFUNCTION:
124     case UNICODERANGE:
125         return true;
126     default:
127         return false;
128     }
129 }
130 #endif
131 
makeOperatorValue(int value)132 inline static CSSParserValue makeOperatorValue(int value)
133 {
134     CSSParserValue v;
135     v.id = CSSValueInvalid;
136     v.isInt = false;
137     v.unit = CSSParserValue::Operator;
138     v.iValue = value;
139     return v;
140 }
141 
makeIdentValue(CSSParserString string)142 inline static CSSParserValue makeIdentValue(CSSParserString string)
143 {
144     CSSParserValue v;
145     v.id = cssValueKeywordID(string);
146     v.isInt = false;
147     v.unit = CSSPrimitiveValue::CSS_IDENT;
148     v.string = string;
149     return v;
150 }
151 
152 %}
153 
154 %expect 0
155 
156 %nonassoc LOWEST_PREC
157 
158 %left UNIMPORTANT_TOK
159 
160 %token WHITESPACE SGML_CD
161 %token TOKEN_EOF 0
162 
163 %token INCLUDES
164 %token DASHMATCH
165 %token BEGINSWITH
166 %token ENDSWITH
167 %token CONTAINS
168 
169 %token <string> STRING
170 %right <string> IDENT
171 %token <string> NTH
172 
173 %nonassoc <string> HEX
174 %nonassoc <string> IDSEL
175 %nonassoc ':'
176 %nonassoc '.'
177 %nonassoc '['
178 %nonassoc <string> '*'
179 %nonassoc error
180 %left '|'
181 
182 %token IMPORT_SYM
183 %token PAGE_SYM
184 %token MEDIA_SYM
185 %token SUPPORTS_SYM
186 %token FONT_FACE_SYM
187 %token CHARSET_SYM
188 %token NAMESPACE_SYM
189 %token VIEWPORT_RULE_SYM
190 %token INTERNAL_DECLS_SYM
191 %token INTERNAL_RULE_SYM
192 %token INTERNAL_SELECTOR_SYM
193 %token INTERNAL_VALUE_SYM
194 %token INTERNAL_KEYFRAME_RULE_SYM
195 %token INTERNAL_KEYFRAME_KEY_LIST_SYM
196 %token INTERNAL_SUPPORTS_CONDITION_SYM
197 %token KEYFRAMES_SYM
198 %token WEBKIT_KEYFRAMES_SYM
199 %token <marginBox> TOPLEFTCORNER_SYM
200 %token <marginBox> TOPLEFT_SYM
201 %token <marginBox> TOPCENTER_SYM
202 %token <marginBox> TOPRIGHT_SYM
203 %token <marginBox> TOPRIGHTCORNER_SYM
204 %token <marginBox> BOTTOMLEFTCORNER_SYM
205 %token <marginBox> BOTTOMLEFT_SYM
206 %token <marginBox> BOTTOMCENTER_SYM
207 %token <marginBox> BOTTOMRIGHT_SYM
208 %token <marginBox> BOTTOMRIGHTCORNER_SYM
209 %token <marginBox> LEFTTOP_SYM
210 %token <marginBox> LEFTMIDDLE_SYM
211 %token <marginBox> LEFTBOTTOM_SYM
212 %token <marginBox> RIGHTTOP_SYM
213 %token <marginBox> RIGHTMIDDLE_SYM
214 %token <marginBox> RIGHTBOTTOM_SYM
215 
216 %token ATKEYWORD
217 
218 %token IMPORTANT_SYM
219 %token MEDIA_ONLY
220 %token MEDIA_NOT
221 %token MEDIA_AND
222 %token MEDIA_OR
223 
224 %token SUPPORTS_NOT
225 %token SUPPORTS_AND
226 %token SUPPORTS_OR
227 
228 %token <number> REMS
229 %token <number> CHS
230 %token <number> QEMS
231 %token <number> EMS
232 %token <number> EXS
233 %token <number> PXS
234 %token <number> CMS
235 %token <number> MMS
236 %token <number> INS
237 %token <number> PTS
238 %token <number> PCS
239 %token <number> DEGS
240 %token <number> RADS
241 %token <number> GRADS
242 %token <number> TURNS
243 %token <number> MSECS
244 %token <number> SECS
245 %token <number> HERTZ
246 %token <number> KHERTZ
247 %token <string> DIMEN
248 %token <string> INVALIDDIMEN
249 %token <number> PERCENTAGE
250 %token <number> FLOATTOKEN
251 %token <number> INTEGER
252 %token <number> VW
253 %token <number> VH
254 %token <number> VMIN
255 %token <number> VMAX
256 %token <number> DPPX
257 %token <number> DPI
258 %token <number> DPCM
259 %token <number> FR
260 
261 %token <string> URI
262 %token <string> FUNCTION
263 %token <string> ANYFUNCTION
264 %token <string> CUEFUNCTION
265 %token <string> NOTFUNCTION
266 %token <string> DISTRIBUTEDFUNCTION
267 %token <string> CALCFUNCTION
268 %token <string> HOSTFUNCTION
269 %token <string> HOSTCONTEXTFUNCTION
270 
271 %token <string> UNICODERANGE
272 
273 %type <relation> combinator
274 
275 %type <rule> ruleset
276 %type <rule> media
277 %type <rule> import
278 %type <rule> namespace
279 %type <rule> page
280 %type <rule> margin_box
281 %type <rule> font_face
282 %type <rule> keyframes
283 %type <rule> rule
284 %type <rule> valid_rule
285 %type <ruleList> block_rule_body
286 %type <ruleList> block_rule_list
287 %type <rule> block_rule
288 %type <rule> block_valid_rule
289 %type <rule> supports
290 %type <rule> viewport
291 %type <boolean> keyframes_rule_start
292 
293 %type <string> maybe_ns_prefix
294 
295 %type <string> namespace_selector
296 
297 %type <string> string_or_uri
298 %type <string> ident_or_string
299 %type <string> medium
300 %type <marginBox> margin_sym
301 
302 %type <mediaList> media_list
303 %type <mediaList> maybe_media_list
304 %type <mediaList> mq_list
305 %type <mediaQuery> media_query
306 %type <mediaQuery> valid_media_query
307 %type <mediaQueryRestrictor> maybe_media_restrictor
308 %type <valueList> maybe_media_value
309 %type <mediaQueryExp> media_query_exp
310 %type <mediaQueryExpList> media_query_exp_list
311 %type <mediaQueryExpList> maybe_and_media_query_exp_list
312 
313 %type <boolean> supports_condition
314 %type <boolean> supports_condition_in_parens
315 %type <boolean> supports_negation
316 %type <boolean> supports_conjunction
317 %type <boolean> supports_disjunction
318 %type <boolean> supports_declaration_condition
319 
320 %type <string> keyframe_name
321 %type <keyframe> keyframe_rule
322 %type <keyframeRuleList> keyframes_rule
323 %type <keyframeRuleList> keyframe_rule_list
324 %type <valueList> key_list
325 %type <value> key
326 
327 %type <id> property
328 
329 %type <selector> specifier
330 %type <selector> specifier_list
331 %type <selector> simple_selector
332 %type <selector> selector
333 %type <selectorList> selector_list
334 %type <selectorList> simple_selector_list
335 %type <selector> class
336 %type <selector> attrib
337 %type <selector> pseudo
338 %type <selector> pseudo_page
339 %type <selector> page_selector
340 
341 %type <boolean> declaration_list
342 %type <boolean> decl_list
343 %type <boolean> declaration
344 %type <boolean> declarations_and_margins
345 
346 %type <boolean> prio
347 
348 %type <integer> match
349 %type <integer> unary_operator
350 %type <integer> maybe_unary_operator
351 %type <character> operator
352 
353 %type <valueList> expr
354 %type <value> term
355 %type <value> unary_term
356 %type <value> function
357 %type <value> calc_func_term
358 %type <character> calc_func_operator
359 %type <valueList> calc_func_expr
360 %type <valueList> calc_func_paren_expr
361 %type <value> calc_function
362 
363 %type <string> element_name
364 %type <string> attr_name
365 
366 %type <attributeMatchType> attr_match_type
367 %type <attributeMatchType> maybe_attr_match_type
368 
369 %type <location> error_location
370 
371 %type <valueList> ident_list
372 %type <value> track_names_list
373 
374 %%
375 
376 stylesheet:
377     maybe_charset maybe_sgml rule_list
378   | internal_decls
379   | internal_rule
380   | internal_selector
381   | internal_value
382   | internal_keyframe_rule
383   | internal_keyframe_key_list
384   | internal_supports_condition
385   ;
386 
387 internal_rule:
388     INTERNAL_RULE_SYM maybe_space valid_rule maybe_space TOKEN_EOF {
389         parser->m_rule = $3;
390     }
391 ;
392 
393 internal_keyframe_rule:
394     INTERNAL_KEYFRAME_RULE_SYM maybe_space keyframe_rule maybe_space TOKEN_EOF {
395         parser->m_keyframe = $3;
396     }
397 ;
398 
399 internal_keyframe_key_list:
400     INTERNAL_KEYFRAME_KEY_LIST_SYM maybe_space key_list TOKEN_EOF {
401         parser->m_valueList = parser->sinkFloatingValueList($3);
402     }
403 ;
404 
405 internal_decls:
406     INTERNAL_DECLS_SYM maybe_space_before_declaration declaration_list TOKEN_EOF {
407         /* can be empty */
408     }
409 ;
410 
411 internal_value:
412     INTERNAL_VALUE_SYM maybe_space expr TOKEN_EOF {
413         parser->m_valueList = parser->sinkFloatingValueList($3);
414         int oldParsedProperties = parser->m_parsedProperties.size();
415         if (!parser->parseValue(parser->m_id, parser->m_important))
416             parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
417         parser->m_valueList = nullptr;
418     }
419 ;
420 
421 internal_selector:
422     INTERNAL_SELECTOR_SYM maybe_space selector_list TOKEN_EOF {
423         if (parser->m_selectorListForParseSelector)
424             parser->m_selectorListForParseSelector->adoptSelectorVector(*$3);
425     }
426 ;
427 
428 internal_supports_condition:
429     INTERNAL_SUPPORTS_CONDITION_SYM maybe_space supports_condition TOKEN_EOF {
430         parser->m_supportsCondition = $3;
431     }
432 ;
433 
434 space:
435     WHITESPACE
436   | space WHITESPACE
437   ;
438 
439 maybe_space:
440     /* empty */ %prec UNIMPORTANT_TOK
441   | space
442   ;
443 
444 maybe_sgml:
445     /* empty */
446   | maybe_sgml SGML_CD
447   | maybe_sgml WHITESPACE
448   ;
449 
450 closing_brace:
451     '}'
452   | %prec LOWEST_PREC TOKEN_EOF
453   ;
454 
455 closing_parenthesis:
456     ')'
457   | %prec LOWEST_PREC TOKEN_EOF
458   ;
459 
460 closing_square_bracket:
461     ']'
462   | %prec LOWEST_PREC TOKEN_EOF
463   ;
464 
465 semi_or_eof:
466     ';'
467   | TOKEN_EOF
468   ;
469 
470 before_charset_rule:
471   /* empty */ {
472       parser->startRule();
473       parser->startRuleHeader(CSSRuleSourceData::CHARSET_RULE);
474   }
475 
476 maybe_charset:
477     /* empty */
478   | before_charset_rule CHARSET_SYM maybe_space STRING maybe_space semi_or_eof {
479        if (parser->m_styleSheet)
480            parser->m_styleSheet->parserSetEncodingFromCharsetRule($4);
481        parser->endRuleHeader();
482        parser->startRuleBody();
483        parser->endRule(true);
484     }
485   | before_charset_rule CHARSET_SYM at_rule_recovery {
486        parser->endRule(false);
487   }
488   ;
489 
490 rule_list:
491    /* empty */
492  | rule_list rule maybe_sgml {
493      if ($2 && parser->m_styleSheet)
494          parser->m_styleSheet->parserAppendRule($2);
495  }
496  ;
497 
498 valid_rule:
499     ruleset
500   | media
501   | page
502   | font_face
503   | keyframes
504   | namespace
505   | import
506   | supports
507   | viewport
508   ;
509 
510 before_rule:
511     /* empty */ {
512         parser->startRule();
513     }
514   ;
515 
516 rule:
517     before_rule valid_rule {
518         $$ = $2;
519         parser->m_hadSyntacticallyValidCSSRule = true;
520         parser->endRule(!!$$);
521     }
522   | before_rule invalid_rule {
523         $$ = 0;
524         parser->endRule(false);
525     }
526   ;
527 
528 block_rule_body:
529     block_rule_list
530   | block_rule_list block_rule_recovery
531     ;
532 
533 block_rule_list:
534     /* empty */ { $$ = 0; }
535   | block_rule_list block_rule maybe_sgml {
536       $$ = parser->appendRule($1, $2);
537     }
538     ;
539 
540 block_rule_recovery:
541     before_rule invalid_rule_header {
542         parser->endRule(false);
543     }
544   ;
545 
546 block_valid_rule:
547     ruleset
548   | page
549   | font_face
550   | media
551   | keyframes
552   | supports
553   | viewport
554   | namespace
555   ;
556 
557 block_rule:
558     before_rule block_valid_rule {
559         $$ = $2;
560         parser->endRule(!!$$);
561     }
562   | before_rule invalid_rule {
563         $$ = 0;
564         parser->endRule(false);
565     }
566   ;
567 
568 before_import_rule:
569     /* empty */ {
570         parser->startRuleHeader(CSSRuleSourceData::IMPORT_RULE);
571     }
572     ;
573 
574 import_rule_start:
575     before_import_rule IMPORT_SYM maybe_space {
576         parser->endRuleHeader();
577         parser->startRuleBody();
578     }
579   ;
580 
581 import:
582     import_rule_start string_or_uri maybe_space location_label maybe_media_list semi_or_eof {
583         $$ = parser->createImportRule($2, $5);
584     }
585   | import_rule_start string_or_uri maybe_space location_label maybe_media_list invalid_block {
586         $$ = 0;
587     }
588   ;
589 
590 namespace:
591     NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space semi_or_eof {
592         parser->addNamespace($3, $4);
593         $$ = 0;
594     }
595   ;
596 
597 maybe_ns_prefix:
598 /* empty */ { $$.clear(); }
599 | IDENT maybe_space
600 ;
601 
602 string_or_uri:
603 STRING
604 | URI
605 ;
606 
607 maybe_media_value:
608     /*empty*/ {
609         $$ = 0;
610     }
611     | ':' maybe_space expr {
612         $$ = $3;
613     }
614     ;
615 
616 media_query_exp:
617     '(' maybe_space IDENT maybe_space maybe_media_value closing_parenthesis {
618         parser->tokenToLowerCase($3);
619         $$ = parser->createFloatingMediaQueryExp($3, $5);
620         if (!$$)
621             YYERROR;
622     }
623     | '(' error error_recovery closing_parenthesis {
624         YYERROR;
625     }
626     ;
627 
628 media_query_exp_list:
629     media_query_exp {
630         $$ = parser->createFloatingMediaQueryExpList();
631         $$->append(parser->sinkFloatingMediaQueryExp($1));
632     }
633     | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
634         $$ = $1;
635         $$->append(parser->sinkFloatingMediaQueryExp($5));
636     }
637     ;
638 
639 maybe_and_media_query_exp_list:
640     maybe_space {
641         $$ = parser->createFloatingMediaQueryExpList();
642     }
643     | maybe_space MEDIA_AND maybe_space media_query_exp_list maybe_space {
644         $$ = $4;
645     }
646     ;
647 
648 maybe_media_restrictor:
649     /*empty*/ {
650         $$ = MediaQuery::None;
651     }
652     | MEDIA_ONLY maybe_space {
653         $$ = MediaQuery::Only;
654     }
655     | MEDIA_NOT maybe_space {
656         $$ = MediaQuery::Not;
657     }
658     ;
659 
660 valid_media_query:
661     media_query_exp_list maybe_space {
662         $$ = parser->createFloatingMediaQuery(parser->sinkFloatingMediaQueryExpList($1));
663     }
664     | maybe_media_restrictor medium maybe_and_media_query_exp_list {
665         parser->tokenToLowerCase($2);
666         $$ = parser->createFloatingMediaQuery($1, $2, parser->sinkFloatingMediaQueryExpList($3));
667     }
668     ;
669 
670 media_query:
671     valid_media_query
672     | valid_media_query error error_location rule_error_recovery {
673         parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError);
674         $$ = parser->createFloatingNotAllQuery();
675     }
676     | error error_location rule_error_recovery {
677         parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError);
678         $$ = parser->createFloatingNotAllQuery();
679     }
680     ;
681 
682 maybe_media_list:
683     /* empty */ {
684         $$ = parser->createMediaQuerySet();
685     }
686     | media_list
687     ;
688 
689 media_list:
690     media_query {
691         $$ = parser->createMediaQuerySet();
692         $$->addMediaQuery(parser->sinkFloatingMediaQuery($1));
693     }
694     | mq_list media_query {
695         $$ = $1;
696         $$->addMediaQuery(parser->sinkFloatingMediaQuery($2));
697     }
698     | mq_list {
699         $$ = $1;
700         $$->addMediaQuery(parser->sinkFloatingMediaQuery(parser->createFloatingNotAllQuery()));
701     }
702     ;
703 
704 mq_list:
705     media_query ',' maybe_space location_label {
706         $$ = parser->createMediaQuerySet();
707         $$->addMediaQuery(parser->sinkFloatingMediaQuery($1));
708     }
709     | mq_list media_query ',' maybe_space location_label {
710         $$ = $1;
711         $$->addMediaQuery(parser->sinkFloatingMediaQuery($2));
712     }
713     ;
714 
715 at_rule_body_start:
716     /* empty */ {
717         parser->startRuleBody();
718     }
719     ;
720 
721 before_media_rule:
722     /* empty */ {
723         parser->startRuleHeader(CSSRuleSourceData::MEDIA_RULE);
724     }
725     ;
726 
727 at_rule_header_end_maybe_space:
728     maybe_space {
729         parser->endRuleHeader();
730     }
731     ;
732 
733 media_rule_start:
734     before_media_rule MEDIA_SYM maybe_space;
735 
736 media:
737     media_rule_start maybe_media_list '{' at_rule_header_end at_rule_body_start maybe_space block_rule_body closing_brace {
738         $$ = parser->createMediaRule($2, $7);
739     }
740     ;
741 
742 medium:
743   IDENT
744   ;
745 
746 supports:
747     before_supports_rule SUPPORTS_SYM maybe_space supports_condition at_supports_rule_header_end '{' at_rule_body_start maybe_space block_rule_body closing_brace {
748         $$ = parser->createSupportsRule($4, $9);
749     }
750     ;
751 
752 before_supports_rule:
753     /* empty */ {
754         parser->startRuleHeader(CSSRuleSourceData::SUPPORTS_RULE);
755         parser->markSupportsRuleHeaderStart();
756     }
757     ;
758 
759 at_supports_rule_header_end:
760     /* empty */ {
761         parser->endRuleHeader();
762         parser->markSupportsRuleHeaderEnd();
763     }
764     ;
765 
766 supports_condition:
767     supports_condition_in_parens
768     | supports_negation
769     | supports_conjunction
770     | supports_disjunction
771     ;
772 
773 supports_negation:
774     SUPPORTS_NOT maybe_space supports_condition_in_parens {
775         $$ = !$3;
776     }
777     ;
778 
779 supports_conjunction:
780     supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens {
781         $$ = $1 && $4;
782     }
783     | supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens {
784         $$ = $1 && $4;
785     }
786     ;
787 
788 supports_disjunction:
789     supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens {
790         $$ = $1 || $4;
791     }
792     | supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens {
793         $$ = $1 || $4;
794     }
795     ;
796 
797 supports_condition_in_parens:
798     '(' maybe_space supports_condition closing_parenthesis maybe_space {
799         $$ = $3;
800     }
801     | supports_declaration_condition
802     | '(' error error_location error_recovery closing_parenthesis maybe_space {
803         parser->reportError($3, InvalidSupportsConditionCSSError);
804         $$ = false;
805     }
806     ;
807 
808 supports_declaration_condition:
809     '(' maybe_space IDENT maybe_space ':' maybe_space expr prio closing_parenthesis maybe_space {
810         $$ = false;
811         CSSPropertyID id = cssPropertyID($3);
812         if (id != CSSPropertyInvalid) {
813             parser->m_valueList = parser->sinkFloatingValueList($7);
814             int oldParsedProperties = parser->m_parsedProperties.size();
815             $$ = parser->parseValue(id, $8);
816             // We just need to know if the declaration is supported as it is written. Rollback any additions.
817             if ($$)
818                 parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
819         }
820         parser->m_valueList = nullptr;
821         parser->endProperty($8, false);
822     }
823     | '(' maybe_space IDENT maybe_space ':' maybe_space error error_recovery closing_parenthesis maybe_space {
824         $$ = false;
825         parser->endProperty(false, false, GeneralCSSError);
826     }
827     ;
828 
829 before_keyframes_rule:
830     /* empty */ {
831         parser->startRuleHeader(CSSRuleSourceData::KEYFRAMES_RULE);
832     }
833     ;
834 
835 keyframes_rule_start:
836     before_keyframes_rule KEYFRAMES_SYM maybe_space {
837         $$ = false;
838     }
839   | before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space {
840         $$ = true;
841     }
842     ;
843 
844 keyframes:
845     keyframes_rule_start keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space location_label keyframes_rule closing_brace {
846         $$ = parser->createKeyframesRule($2, parser->sinkFloatingKeyframeVector($8), $1 /* isPrefixed */);
847     }
848     ;
849 
850 keyframe_name:
851     IDENT
852     | STRING
853     ;
854 
855 keyframes_rule:
856     keyframe_rule_list
857     | keyframe_rule_list keyframes_error_recovery {
858         parser->clearProperties();
859     };
860 
861 keyframe_rule_list:
862     /* empty */ {
863         $$ = parser->createFloatingKeyframeVector();
864         parser->resumeErrorLogging();
865     }
866     |  keyframe_rule_list keyframe_rule maybe_space location_label {
867         $$ = $1;
868         $$->append($2);
869     }
870     | keyframe_rule_list keyframes_error_recovery invalid_block maybe_space location_label {
871         parser->clearProperties();
872         parser->resumeErrorLogging();
873     }
874     ;
875 
876 keyframe_rule:
877     key_list '{' maybe_space declaration_list closing_brace {
878         $$ = parser->createKeyframe($1);
879     }
880     ;
881 
882 key_list:
883     key maybe_space {
884         $$ = parser->createFloatingValueList();
885         $$->addValue(parser->sinkFloatingValue($1));
886     }
887     | key_list ',' maybe_space key maybe_space {
888         $$ = $1;
889         $$->addValue(parser->sinkFloatingValue($4));
890     }
891     ;
892 
893 key:
894     maybe_unary_operator PERCENTAGE {
895         $$.setFromNumber($1 * $2);
896     }
897     | IDENT {
898         if ($1.equalIgnoringCase("from"))
899             $$.setFromNumber(0);
900         else if ($1.equalIgnoringCase("to"))
901             $$.setFromNumber(100);
902         else {
903             YYERROR;
904         }
905     }
906     ;
907 
908 keyframes_error_recovery:
909     error rule_error_recovery {
910         parser->reportError(parser->lastLocationLabel(), InvalidKeyframeSelectorCSSError);
911     }
912     ;
913 
914 before_page_rule:
915     /* empty */ {
916         parser->startRuleHeader(CSSRuleSourceData::PAGE_RULE);
917     }
918     ;
919 
920 page:
921     before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end
922     '{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace {
923         if ($4)
924             $$ = parser->createPageRule(parser->sinkFloatingSelector($4));
925         else {
926             // Clear properties in the invalid @page rule.
927             parser->clearProperties();
928             // Also clear margin at-rules here once we fully implement margin at-rules parsing.
929             $$ = 0;
930         }
931     }
932     ;
933 
934 page_selector:
935     IDENT maybe_space {
936         $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
937         $$->setForPage();
938     }
939     | IDENT pseudo_page maybe_space {
940         $$ = $2;
941         $$->prependTagSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
942         $$->setForPage();
943     }
944     | pseudo_page maybe_space {
945         $$ = $1;
946         $$->setForPage();
947     }
948     | /* empty */ {
949         $$ = parser->createFloatingSelector();
950         $$->setForPage();
951     }
952     ;
953 
954 declarations_and_margins:
955     declaration_list
956     | declarations_and_margins margin_box maybe_space declaration_list
957     ;
958 
959 margin_box:
960     margin_sym {
961         parser->startDeclarationsForMarginBox();
962     } maybe_space '{' maybe_space declaration_list closing_brace {
963         $$ = parser->createMarginAtRule($1);
964     }
965     ;
966 
967 margin_sym :
968     TOPLEFTCORNER_SYM {
969         $$ = CSSSelector::TopLeftCornerMarginBox;
970     }
971     | TOPLEFT_SYM {
972         $$ = CSSSelector::TopLeftMarginBox;
973     }
974     | TOPCENTER_SYM {
975         $$ = CSSSelector::TopCenterMarginBox;
976     }
977     | TOPRIGHT_SYM {
978         $$ = CSSSelector::TopRightMarginBox;
979     }
980     | TOPRIGHTCORNER_SYM {
981         $$ = CSSSelector::TopRightCornerMarginBox;
982     }
983     | BOTTOMLEFTCORNER_SYM {
984         $$ = CSSSelector::BottomLeftCornerMarginBox;
985     }
986     | BOTTOMLEFT_SYM {
987         $$ = CSSSelector::BottomLeftMarginBox;
988     }
989     | BOTTOMCENTER_SYM {
990         $$ = CSSSelector::BottomCenterMarginBox;
991     }
992     | BOTTOMRIGHT_SYM {
993         $$ = CSSSelector::BottomRightMarginBox;
994     }
995     | BOTTOMRIGHTCORNER_SYM {
996         $$ = CSSSelector::BottomRightCornerMarginBox;
997     }
998     | LEFTTOP_SYM {
999         $$ = CSSSelector::LeftTopMarginBox;
1000     }
1001     | LEFTMIDDLE_SYM {
1002         $$ = CSSSelector::LeftMiddleMarginBox;
1003     }
1004     | LEFTBOTTOM_SYM {
1005         $$ = CSSSelector::LeftBottomMarginBox;
1006     }
1007     | RIGHTTOP_SYM {
1008         $$ = CSSSelector::RightTopMarginBox;
1009     }
1010     | RIGHTMIDDLE_SYM {
1011         $$ = CSSSelector::RightMiddleMarginBox;
1012     }
1013     | RIGHTBOTTOM_SYM {
1014         $$ = CSSSelector::RightBottomMarginBox;
1015     }
1016     ;
1017 
1018 before_font_face_rule:
1019     /* empty */ {
1020         parser->startRuleHeader(CSSRuleSourceData::FONT_FACE_RULE);
1021     }
1022     ;
1023 
1024 font_face:
1025     before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space
1026     '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1027         $$ = parser->createFontFaceRule();
1028     }
1029     ;
1030 
1031 before_viewport_rule:
1032     /* empty */ {
1033         parser->markViewportRuleBodyStart();
1034         parser->startRuleHeader(CSSRuleSourceData::VIEWPORT_RULE);
1035     }
1036     ;
1037 
1038 viewport:
1039     before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_end_maybe_space
1040     '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1041         $$ = parser->createViewportRule();
1042         parser->markViewportRuleBodyEnd();
1043     }
1044 ;
1045 
1046 combinator:
1047     '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
1048     | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
1049     | '>' maybe_space { $$ = CSSSelector::Child; }
1050     | '/' IDENT '/' maybe_space {
1051         if ($2.equalIgnoringCase("deep"))
1052             $$ = CSSSelector::ShadowDeep;
1053         else
1054             YYERROR;
1055     }
1056     ;
1057 
1058 maybe_unary_operator:
1059     unary_operator
1060     | /* empty */ { $$ = 1; }
1061     ;
1062 
1063 unary_operator:
1064     '-' { $$ = -1; }
1065   | '+' { $$ = 1; }
1066   ;
1067 
1068 maybe_space_before_declaration:
1069     maybe_space {
1070         parser->startProperty();
1071     }
1072   ;
1073 
1074 before_selector_list:
1075     /* empty */ {
1076         parser->startRuleHeader(CSSRuleSourceData::STYLE_RULE);
1077         parser->startSelector();
1078     }
1079   ;
1080 
1081 at_rule_header_end:
1082     /* empty */ {
1083         parser->endRuleHeader();
1084     }
1085   ;
1086 
1087 at_selector_end:
1088     /* empty */ {
1089         parser->endSelector();
1090     }
1091   ;
1092 
1093 ruleset:
1094     before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
1095         $$ = parser->createStyleRule($2);
1096     }
1097   ;
1098 
1099 before_selector_group_item:
1100     /* empty */ {
1101         parser->startSelector();
1102     }
1103 
1104 selector_list:
1105     selector %prec UNIMPORTANT_TOK {
1106         $$ = parser->reusableSelectorVector();
1107         $$->shrink(0);
1108         $$->append(parser->sinkFloatingSelector($1));
1109     }
1110     | selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK {
1111         $$ = $1;
1112         $$->append(parser->sinkFloatingSelector($6));
1113     }
1114    ;
1115 
1116 selector:
1117     simple_selector
1118     | selector WHITESPACE
1119     | selector WHITESPACE simple_selector
1120     {
1121         $$ = $3;
1122         CSSParserSelector* end = $$;
1123         while (end->tagHistory())
1124             end = end->tagHistory();
1125         end->setRelation(CSSSelector::Descendant);
1126         if ($1->isContentPseudoElement())
1127             end->setRelationIsAffectedByPseudoContent();
1128         end->setTagHistory(parser->sinkFloatingSelector($1));
1129     }
1130     | selector combinator simple_selector {
1131         $$ = $3;
1132         CSSParserSelector* end = $$;
1133         while (end->tagHistory())
1134             end = end->tagHistory();
1135         end->setRelation($2);
1136         if ($1->isContentPseudoElement())
1137             end->setRelationIsAffectedByPseudoContent();
1138         end->setTagHistory(parser->sinkFloatingSelector($1));
1139     }
1140     ;
1141 
1142 namespace_selector:
1143     /* empty */ '|' { $$.clear(); }
1144     | '*' '|' { static const LChar star = '*'; $$.init(&star, 1); }
1145     | IDENT '|'
1146     ;
1147 
1148 simple_selector:
1149     element_name {
1150         $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));
1151     }
1152     | element_name specifier_list {
1153         $$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $2);
1154         if (!$$)
1155             YYERROR;
1156     }
1157     | specifier_list {
1158         $$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($1);
1159         if (!$$)
1160             YYERROR;
1161     }
1162     | namespace_selector element_name {
1163         $$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2));
1164         if (!$$)
1165             YYERROR;
1166     }
1167     | namespace_selector element_name specifier_list {
1168         $$ = parser->rewriteSpecifiersWithElementName($1, $2, $3);
1169         if (!$$)
1170             YYERROR;
1171     }
1172     | namespace_selector specifier_list {
1173         $$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $2);
1174         if (!$$)
1175             YYERROR;
1176     }
1177   ;
1178 
1179 simple_selector_list:
1180     simple_selector %prec UNIMPORTANT_TOK {
1181         $$ = parser->createFloatingSelectorVector();
1182         $$->append(parser->sinkFloatingSelector($1));
1183     }
1184     | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK {
1185         $$ = $1;
1186         $$->append(parser->sinkFloatingSelector($5));
1187     }
1188   ;
1189 
1190 element_name:
1191     IDENT {
1192         if (parser->m_context.isHTMLDocument())
1193             parser->tokenToLowerCase($1);
1194         $$ = $1;
1195     }
1196     | '*' {
1197         static const LChar star = '*';
1198         $$.init(&star, 1);
1199     }
1200   ;
1201 
1202 specifier_list:
1203     specifier
1204     | specifier_list specifier {
1205         $$ = parser->rewriteSpecifiers($1, $2);
1206     }
1207 ;
1208 
1209 specifier:
1210     IDSEL {
1211         $$ = parser->createFloatingSelector();
1212         $$->setMatch(CSSSelector::Id);
1213         if (isQuirksModeBehavior(parser->m_context.mode()))
1214             parser->tokenToLowerCase($1);
1215         $$->setValue($1);
1216     }
1217   | HEX {
1218         if ($1[0] >= '0' && $1[0] <= '9') {
1219             YYERROR;
1220         } else {
1221             $$ = parser->createFloatingSelector();
1222             $$->setMatch(CSSSelector::Id);
1223             if (isQuirksModeBehavior(parser->m_context.mode()))
1224                 parser->tokenToLowerCase($1);
1225             $$->setValue($1);
1226         }
1227     }
1228   | class
1229   | attrib
1230   | pseudo
1231     ;
1232 
1233 class:
1234     '.' IDENT {
1235         $$ = parser->createFloatingSelector();
1236         $$->setMatch(CSSSelector::Class);
1237         if (isQuirksModeBehavior(parser->m_context.mode()))
1238             parser->tokenToLowerCase($2);
1239         $$->setValue($2);
1240     }
1241   ;
1242 
1243 attr_name:
1244     IDENT maybe_space {
1245         if (parser->m_context.isHTMLDocument())
1246             parser->tokenToLowerCase($1);
1247         $$ = $1;
1248     }
1249     ;
1250 
1251 attr_match_type:
1252     IDENT maybe_space {
1253         CSSSelector::AttributeMatchType attrMatchType = CSSSelector::CaseSensitive;
1254         if (!parser->parseAttributeMatchType(attrMatchType, $1))
1255             YYERROR;
1256         $$ = attrMatchType;
1257     }
1258     ;
1259 
1260 maybe_attr_match_type:
1261     attr_match_type
1262     | /* empty */ { $$ = CSSSelector::CaseSensitive; }
1263     ;
1264 
1265 attrib:
1266     '[' maybe_space attr_name closing_square_bracket {
1267         $$ = parser->createFloatingSelector();
1268         $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom), CSSSelector::CaseSensitive);
1269         $$->setMatch(CSSSelector::Set);
1270     }
1271     | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space maybe_attr_match_type closing_square_bracket {
1272         $$ = parser->createFloatingSelector();
1273         $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom), $8);
1274         $$->setMatch((CSSSelector::Match)$4);
1275         $$->setValue($6);
1276     }
1277     | '[' maybe_space namespace_selector attr_name closing_square_bracket {
1278         $$ = parser->createFloatingSelector();
1279         $$->setAttribute(parser->determineNameInNamespace($3, $4), CSSSelector::CaseSensitive);
1280         $$->setMatch(CSSSelector::Set);
1281     }
1282     | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space maybe_attr_match_type closing_square_bracket {
1283         $$ = parser->createFloatingSelector();
1284         $$->setAttribute(parser->determineNameInNamespace($3, $4), $9);
1285         $$->setMatch((CSSSelector::Match)$5);
1286         $$->setValue($7);
1287     }
1288     | '[' selector_recovery closing_square_bracket {
1289         YYERROR;
1290     }
1291   ;
1292 
1293 match:
1294     '=' {
1295         $$ = CSSSelector::Exact;
1296     }
1297     | INCLUDES {
1298         $$ = CSSSelector::List;
1299     }
1300     | DASHMATCH {
1301         $$ = CSSSelector::Hyphen;
1302     }
1303     | BEGINSWITH {
1304         $$ = CSSSelector::Begin;
1305     }
1306     | ENDSWITH {
1307         $$ = CSSSelector::End;
1308     }
1309     | CONTAINS {
1310         $$ = CSSSelector::Contain;
1311     }
1312     ;
1313 
1314 ident_or_string:
1315     IDENT
1316   | STRING
1317     ;
1318 
1319 pseudo_page:
1320     ':' IDENT {
1321         if ($2.isFunction())
1322             YYERROR;
1323         $$ = parser->createFloatingSelector();
1324         $$->setMatch(CSSSelector::PagePseudoClass);
1325         parser->tokenToLowerCase($2);
1326         $$->setValue($2);
1327         CSSSelector::PseudoType type = $$->pseudoType();
1328         if (type == CSSSelector::PseudoUnknown)
1329             YYERROR;
1330     }
1331 
1332 pseudo:
1333     ':' error_location IDENT {
1334         if ($3.isFunction())
1335             YYERROR;
1336         $$ = parser->createFloatingSelector();
1337         $$->setMatch(CSSSelector::PseudoClass);
1338         parser->tokenToLowerCase($3);
1339         $$->setValue($3);
1340         CSSSelector::PseudoType type = $$->pseudoType();
1341         if (type == CSSSelector::PseudoUnknown) {
1342             parser->reportError($2, InvalidSelectorPseudoCSSError);
1343             YYERROR;
1344         }
1345     }
1346     | ':' ':' error_location IDENT {
1347         if ($4.isFunction())
1348             YYERROR;
1349         $$ = parser->createFloatingSelector();
1350         $$->setMatch(CSSSelector::PseudoElement);
1351         parser->tokenToLowerCase($4);
1352         $$->setValue($4);
1353         // FIXME: This call is needed to force selector to compute the pseudoType early enough.
1354         CSSSelector::PseudoType type = $$->pseudoType();
1355         if (type == CSSSelector::PseudoUnknown) {
1356             parser->reportError($3, InvalidSelectorPseudoCSSError);
1357             YYERROR;
1358         }
1359     }
1360     // used by ::cue(:past/:future)
1361     | ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
1362         $$ = parser->createFloatingSelector();
1363         $$->setMatch(CSSSelector::PseudoElement);
1364         $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($5));
1365         $$->setValue($3);
1366         CSSSelector::PseudoType type = $$->pseudoType();
1367         if (type != CSSSelector::PseudoCue)
1368             YYERROR;
1369     }
1370     | ':' ':' CUEFUNCTION selector_recovery closing_parenthesis {
1371         YYERROR;
1372     }
1373     // use by :-webkit-any.
1374     // FIXME: should we support generic selectors here or just simple_selectors?
1375     // Use simple_selector_list for now to match -moz-any.
1376     // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some
1377     // related discussion with respect to :not.
1378     | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
1379         $$ = parser->createFloatingSelector();
1380         $$->setMatch(CSSSelector::PseudoClass);
1381         $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
1382         parser->tokenToLowerCase($2);
1383         $$->setValue($2);
1384         CSSSelector::PseudoType type = $$->pseudoType();
1385         if (type != CSSSelector::PseudoAny)
1386             YYERROR;
1387     }
1388     | ':' ANYFUNCTION selector_recovery closing_parenthesis {
1389         YYERROR;
1390     }
1391     // used by :nth-*(ax+b)
1392     | ':' FUNCTION maybe_space NTH maybe_space closing_parenthesis {
1393         $$ = parser->createFloatingSelector();
1394         $$->setMatch(CSSSelector::PseudoClass);
1395         $$->setArgument($4);
1396         $$->setValue($2);
1397         CSSSelector::PseudoType type = $$->pseudoType();
1398         if (type == CSSSelector::PseudoUnknown)
1399             YYERROR;
1400     }
1401     // used by :nth-*
1402     | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space closing_parenthesis {
1403         $$ = parser->createFloatingSelector();
1404         $$->setMatch(CSSSelector::PseudoClass);
1405         $$->setArgument(AtomicString::number($4 * $5));
1406         $$->setValue($2);
1407         CSSSelector::PseudoType type = $$->pseudoType();
1408         if (type == CSSSelector::PseudoUnknown)
1409             YYERROR;
1410     }
1411     // used by :nth-*(odd/even) and :lang
1412     | ':' FUNCTION maybe_space IDENT maybe_space closing_parenthesis {
1413         $$ = parser->createFloatingSelector();
1414         $$->setMatch(CSSSelector::PseudoClass);
1415         $$->setArgument($4);
1416         parser->tokenToLowerCase($2);
1417         $$->setValue($2);
1418         CSSSelector::PseudoType type = $$->pseudoType();
1419         if (type == CSSSelector::PseudoUnknown)
1420             YYERROR;
1421         else if (type == CSSSelector::PseudoNthChild ||
1422                  type == CSSSelector::PseudoNthOfType ||
1423                  type == CSSSelector::PseudoNthLastChild ||
1424                  type == CSSSelector::PseudoNthLastOfType) {
1425             if (!isValidNthToken($4))
1426                 YYERROR;
1427         }
1428     }
1429     | ':' FUNCTION selector_recovery closing_parenthesis {
1430         YYERROR;
1431     }
1432     // used by :not
1433     | ':' NOTFUNCTION maybe_space simple_selector maybe_space closing_parenthesis {
1434         if (!$4->isSimple())
1435             YYERROR;
1436         else {
1437             $$ = parser->createFloatingSelector();
1438             $$->setMatch(CSSSelector::PseudoClass);
1439 
1440             Vector<OwnPtr<CSSParserSelector> > selectorVector;
1441             selectorVector.append(parser->sinkFloatingSelector($4));
1442             $$->adoptSelectorVector(selectorVector);
1443 
1444             parser->tokenToLowerCase($2);
1445             $$->setValue($2);
1446         }
1447     }
1448     | ':' NOTFUNCTION selector_recovery closing_parenthesis {
1449         YYERROR;
1450     }
1451     | ':' HOSTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
1452         $$ = parser->createFloatingSelector();
1453         $$->setMatch(CSSSelector::PseudoClass);
1454         $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
1455         parser->tokenToLowerCase($2);
1456         $$->setValue($2);
1457         CSSSelector::PseudoType type = $$->pseudoType();
1458         if (type != CSSSelector::PseudoHost)
1459             YYERROR;
1460     }
1461     | ':' HOSTFUNCTION selector_recovery closing_parenthesis {
1462         YYERROR;
1463     }
1464     //  used by :host-context()
1465     | ':' HOSTCONTEXTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis {
1466         $$ = parser->createFloatingSelector();
1467         $$->setMatch(CSSSelector::PseudoClass);
1468         $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4));
1469         parser->tokenToLowerCase($2);
1470         $$->setValue($2);
1471         CSSSelector::PseudoType type = $$->pseudoType();
1472         if (type != CSSSelector::PseudoHostContext)
1473             YYERROR;
1474     }
1475     | ':' HOSTCONTEXTFUNCTION selector_recovery closing_parenthesis {
1476         YYERROR;
1477     }
1478   ;
1479 
1480 selector_recovery:
1481     error error_location error_recovery;
1482 
1483 declaration_list:
1484     /* empty */ { $$ = false; }
1485     | declaration
1486     | decl_list declaration {
1487         $$ = $1 || $2;
1488     }
1489     | decl_list
1490     ;
1491 
1492 decl_list:
1493     declaration ';' maybe_space {
1494         parser->startProperty();
1495         $$ = $1;
1496     }
1497     | decl_list declaration ';' maybe_space {
1498         parser->startProperty();
1499         $$ = $1 || $2;
1500     }
1501     ;
1502 
1503 declaration:
1504     property ':' maybe_space error_location expr prio {
1505         $$ = false;
1506         bool isPropertyParsed = false;
1507         if ($1 != CSSPropertyInvalid) {
1508             parser->m_valueList = parser->sinkFloatingValueList($5);
1509             int oldParsedProperties = parser->m_parsedProperties.size();
1510             $$ = parser->parseValue($1, $6);
1511             if (!$$) {
1512                 parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
1513                 parser->reportError($4, InvalidPropertyValueCSSError);
1514             } else
1515                 isPropertyParsed = true;
1516             parser->m_valueList = nullptr;
1517         }
1518         parser->endProperty($6, isPropertyParsed);
1519     }
1520     |
1521     property ':' maybe_space error_location expr prio error error_recovery {
1522         /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
1523         parser->reportError($4, InvalidPropertyValueCSSError);
1524         parser->endProperty(false, false);
1525         $$ = false;
1526     }
1527     |
1528     property ':' maybe_space error_location error error_recovery {
1529         parser->reportError($4, InvalidPropertyValueCSSError);
1530         parser->endProperty(false, false);
1531         $$ = false;
1532     }
1533     |
1534     property error error_location error_recovery {
1535         parser->reportError($3, PropertyDeclarationCSSError);
1536         parser->endProperty(false, false, GeneralCSSError);
1537         $$ = false;
1538     }
1539     |
1540     error error_location error_recovery {
1541         parser->reportError($2, PropertyDeclarationCSSError);
1542         $$ = false;
1543     }
1544   ;
1545 
1546 property:
1547     error_location IDENT maybe_space {
1548         $$ = cssPropertyID($2);
1549         parser->setCurrentProperty($$);
1550         if ($$ == CSSPropertyInvalid)
1551             parser->reportError($1, InvalidPropertyCSSError);
1552     }
1553   ;
1554 
1555 prio:
1556     IMPORTANT_SYM maybe_space { $$ = true; }
1557     | /* empty */ { $$ = false; }
1558   ;
1559 
1560 ident_list:
1561     IDENT maybe_space {
1562         $$ = parser->createFloatingValueList();
1563         $$->addValue(makeIdentValue($1));
1564     }
1565     | ident_list IDENT maybe_space {
1566         $$ = $1;
1567         $$->addValue(makeIdentValue($2));
1568     }
1569     ;
1570 
1571 track_names_list:
1572     '(' maybe_space closing_parenthesis {
1573         $$.setFromValueList(parser->sinkFloatingValueList(parser->createFloatingValueList()));
1574     }
1575     | '(' maybe_space ident_list closing_parenthesis {
1576         $$.setFromValueList(parser->sinkFloatingValueList($3));
1577     }
1578     | '(' maybe_space expr_recovery closing_parenthesis {
1579         YYERROR;
1580     }
1581   ;
1582 
1583 expr:
1584     term {
1585         $$ = parser->createFloatingValueList();
1586         $$->addValue(parser->sinkFloatingValue($1));
1587     }
1588     | expr operator term {
1589         $$ = $1;
1590         $$->addValue(makeOperatorValue($2));
1591         $$->addValue(parser->sinkFloatingValue($3));
1592     }
1593     | expr term {
1594         $$ = $1;
1595         $$->addValue(parser->sinkFloatingValue($2));
1596     }
1597   ;
1598 
1599 expr_recovery:
1600     error error_location error_recovery {
1601         parser->reportError($2, PropertyDeclarationCSSError);
1602     }
1603   ;
1604 
1605 operator:
1606     '/' maybe_space {
1607         $$ = '/';
1608     }
1609   | ',' maybe_space {
1610         $$ = ',';
1611     }
1612   ;
1613 
1614 term:
1615   unary_term maybe_space
1616   | unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; }
1617   | STRING maybe_space { $$.id = CSSValueInvalid; $$.isInt = false; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1618   | IDENT maybe_space { $$ = makeIdentValue($1); }
1619   /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1620   | DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1621   | unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
1622   | URI maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_URI; }
1623   | UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
1624   | HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
1625   | '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
1626   /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1627   | function maybe_space
1628   | calc_function maybe_space
1629   | '%' maybe_space { /* Handle width: %; */
1630       $$.id = CSSValueInvalid; $$.isInt = false; $$.unit = 0;
1631   }
1632   | track_names_list maybe_space
1633   ;
1634 
1635 unary_term:
1636   INTEGER { $$.setFromNumber($1); $$.isInt = true; }
1637   | FLOATTOKEN { $$.setFromNumber($1); }
1638   | PERCENTAGE { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PERCENTAGE); }
1639   | PXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PX); }
1640   | CMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CM); }
1641   | MMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MM); }
1642   | INS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_IN); }
1643   | PTS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PT); }
1644   | PCS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PC); }
1645   | DEGS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DEG); }
1646   | RADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_RAD); }
1647   | GRADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_GRAD); }
1648   | TURNS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_TURN); }
1649   | MSECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MS); }
1650   | SECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_S); }
1651   | HERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_HZ); }
1652   | KHERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_KHZ); }
1653   | EMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EMS); }
1654   | QEMS { $$.setFromNumber($1, CSSParserValue::Q_EMS); }
1655   | EXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EXS); }
1656   | REMS {
1657       $$.setFromNumber($1, CSSPrimitiveValue::CSS_REMS);
1658       if (parser->m_styleSheet)
1659           parser->m_styleSheet->parserSetUsesRemUnits(true);
1660   }
1661   | CHS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CHS); }
1662   | VW { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VW); }
1663   | VH { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VH); }
1664   | VMIN { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMIN); }
1665   | VMAX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMAX); }
1666   | DPPX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPPX); }
1667   | DPI { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPI); }
1668   | DPCM { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPCM); }
1669   | FR { $$.setFromNumber($1, CSSPrimitiveValue::CSS_FR); }
1670   ;
1671 
1672 function:
1673     FUNCTION maybe_space expr closing_parenthesis {
1674         $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3)));
1675     } |
1676     FUNCTION maybe_space closing_parenthesis {
1677         $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList(parser->createFloatingValueList())));
1678     } |
1679     FUNCTION maybe_space expr_recovery closing_parenthesis {
1680         YYERROR;
1681     }
1682   ;
1683 
1684 calc_func_term:
1685   unary_term
1686   | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1687   ;
1688 
1689 calc_func_operator:
1690     space '+' space {
1691         $$ = '+';
1692     }
1693     | space '-' space {
1694         $$ = '-';
1695     }
1696     | calc_maybe_space '*' maybe_space {
1697         $$ = '*';
1698     }
1699     | calc_maybe_space '/' maybe_space {
1700         $$ = '/';
1701     }
1702   ;
1703 
1704 calc_maybe_space:
1705     /* empty */
1706     | WHITESPACE
1707   ;
1708 
1709 calc_func_paren_expr:
1710     '(' maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
1711         $$ = $3;
1712         $$->insertValueAt(0, makeOperatorValue('('));
1713         $$->addValue(makeOperatorValue(')'));
1714     }
1715     | '(' maybe_space expr_recovery closing_parenthesis {
1716         YYERROR;
1717     }
1718   ;
1719 
1720 calc_func_expr:
1721     calc_func_term {
1722         $$ = parser->createFloatingValueList();
1723         $$->addValue(parser->sinkFloatingValue($1));
1724     }
1725     | calc_func_expr calc_func_operator calc_func_term {
1726         $$ = $1;
1727         $$->addValue(makeOperatorValue($2));
1728         $$->addValue(parser->sinkFloatingValue($3));
1729     }
1730     | calc_func_expr calc_func_operator calc_func_paren_expr {
1731         $$ = $1;
1732         $$->addValue(makeOperatorValue($2));
1733         $$->stealValues(*($3));
1734     }
1735     | calc_func_paren_expr
1736   ;
1737 
1738 calc_function:
1739     CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis {
1740         $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3)));
1741     }
1742     | CALCFUNCTION maybe_space expr_recovery closing_parenthesis {
1743         YYERROR;
1744     }
1745     ;
1746 
1747 
1748 invalid_at:
1749     ATKEYWORD
1750   | margin_sym
1751     ;
1752 
1753 at_rule_recovery:
1754     at_rule_header_recovery at_invalid_rule_header_end at_rule_end
1755     ;
1756 
1757 at_rule_header_recovery:
1758     error error_location rule_error_recovery {
1759         parser->reportError($2, InvalidRuleCSSError);
1760     }
1761     ;
1762 
1763 at_rule_end:
1764     at_invalid_rule_header_end semi_or_eof
1765   | at_invalid_rule_header_end invalid_block
1766     ;
1767 
1768 regular_invalid_at_rule_header:
1769     keyframes_rule_start at_rule_header_recovery
1770   | before_page_rule PAGE_SYM at_rule_header_recovery
1771   | before_font_face_rule FONT_FACE_SYM at_rule_header_recovery
1772   | before_supports_rule SUPPORTS_SYM error error_location rule_error_recovery {
1773         parser->reportError($4, InvalidSupportsConditionCSSError);
1774         parser->popSupportsRuleData();
1775     }
1776   | before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_recovery {
1777         parser->markViewportRuleBodyEnd();
1778     }
1779   | import_rule_start at_rule_header_recovery
1780   | NAMESPACE_SYM at_rule_header_recovery
1781   | error_location invalid_at at_rule_header_recovery {
1782         parser->resumeErrorLogging();
1783         parser->reportError($1, InvalidRuleCSSError);
1784     }
1785   ;
1786 
1787 invalid_rule:
1788     error error_location rule_error_recovery at_invalid_rule_header_end invalid_block {
1789         parser->reportError($2, InvalidRuleCSSError);
1790     }
1791   | regular_invalid_at_rule_header at_invalid_rule_header_end ';'
1792   | regular_invalid_at_rule_header at_invalid_rule_header_end invalid_block
1793   | media_rule_start maybe_media_list ';'
1794     ;
1795 
1796 invalid_rule_header:
1797     error error_location rule_error_recovery at_invalid_rule_header_end {
1798         parser->reportError($2, InvalidRuleCSSError);
1799     }
1800   | regular_invalid_at_rule_header at_invalid_rule_header_end
1801   | media_rule_start maybe_media_list
1802     ;
1803 
1804 at_invalid_rule_header_end:
1805    /* empty */ {
1806        parser->endInvalidRuleHeader();
1807    }
1808    ;
1809 
1810 invalid_block:
1811     '{' error_recovery closing_brace {
1812         parser->invalidBlockHit();
1813     }
1814     ;
1815 
1816 invalid_square_brackets_block:
1817     '[' error_recovery closing_square_bracket
1818     ;
1819 
1820 invalid_parentheses_block:
1821     opening_parenthesis error_recovery closing_parenthesis;
1822 
1823 opening_parenthesis:
1824     '(' | FUNCTION | CALCFUNCTION | ANYFUNCTION | NOTFUNCTION | CUEFUNCTION | DISTRIBUTEDFUNCTION | HOSTFUNCTION
1825     ;
1826 
1827 error_location: {
1828         $$ = parser->currentLocation();
1829     }
1830     ;
1831 
1832 location_label: {
1833         parser->setLocationLabel(parser->currentLocation());
1834     }
1835     ;
1836 
1837 error_recovery:
1838     /* empty */
1839   | error_recovery error
1840   | error_recovery invalid_block
1841   | error_recovery invalid_square_brackets_block
1842   | error_recovery invalid_parentheses_block
1843     ;
1844 
1845 rule_error_recovery:
1846     /* empty */
1847   | rule_error_recovery error
1848   | rule_error_recovery invalid_square_brackets_block
1849   | rule_error_recovery invalid_parentheses_block
1850     ;
1851 
1852 %%
1853