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