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