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