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