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