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