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