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