OSDN Git Service

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