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