OSDN Git Service

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