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