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