4 * This file is part of the KDE libraries
5 * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
6 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
7 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "CSSMediaRule.h"
28 #include "CSSPrimitiveValue.h"
30 #include "CSSRuleList.h"
31 #include "CSSSelector.h"
32 #include "CSSStyleSheet.h"
34 #include "HTMLNames.h"
35 #include "MediaList.h"
36 #include "MediaQuery.h"
37 #include "MediaQueryExp.h"
38 #include "PlatformString.h"
39 #include "cssparser.h"
45 #include "ksvgcssproperties.h"
46 #include "ksvgcssvalues.h"
49 using namespace WebCore;
50 using namespace HTMLNames;
52 // The following file defines the function
53 // const struct props *findProp(const char *word, int len)
55 // with 'props->id' a CSS property in the range from CSS_PROP_MIN to
56 // (and including) CSS_PROP_TOTAL-1
58 #include "CSSPropertyNames.c"
59 #include "CSSValueKeywords.c"
63 int getPropertyID(const char* tagStr, int len)
65 DeprecatedString prop;
67 if (len && tagStr[0] == '-') {
68 prop = DeprecatedString(tagStr, len);
69 if (prop.startsWith("-apple-")) {
70 prop = "-webkit-" + prop.mid(7);
71 tagStr = prop.ascii();
73 } else if (prop.startsWith("-khtml-")) {
74 prop = "-webkit-" + prop.mid(7);
76 tagStr = prop.ascii();
79 // Honor the use of old-style opacity (for Safari 1.1).
80 if (prop == "-webkit-opacity") {
81 const char * const opacity = "opacity";
83 len = strlen(opacity);
87 const struct props* propsPtr = findProp(tagStr, len);
96 static inline int getValueID(const char* tagStr, int len)
98 DeprecatedString prop;
99 if (len && tagStr[0] == '-') {
100 prop = DeprecatedString(tagStr, len);
101 if (prop.startsWith("-apple-")) {
102 prop = "-webkit-" + prop.mid(7);
103 tagStr = prop.ascii();
105 } else if (prop.startsWith("-khtml-")) {
106 prop = "-webkit-" + prop.mid(7);
108 tagStr = prop.ascii();
112 const struct css_value *val = findValue(tagStr, len);
119 #define YYENABLE_NLS 0
120 #define YYLTYPE_IS_TRIVIAL 1
121 #define YYMAXDEPTH 10000
123 #define YYPARSE_PARAM parser
131 CSSSelector* selector;
133 MediaList *mediaList;
134 CSSMediaRule* mediaRule;
135 CSSRuleList* ruleList;
140 CSSSelector::Relation relation;
145 ValueList* valueList;
147 MediaQuery* mediaQuery;
148 MediaQueryExp* mediaQueryExp;
149 Vector<MediaQueryExp*>* mediaQueryExpList;
150 MediaQuery::Restrictor mediaQueryRestrictor;
155 static inline int cssyyerror(const char *) { return 1; }
156 static int cssyylex(YYSTYPE *yylval) { return CSSParser::current()->lex(yylval); }
162 %left UNIMPORTANT_TOK
164 %token WHITESPACE SGML_CD
172 %token <string> STRING
174 %right <string> IDENT
176 %nonassoc <string> HASH
180 %nonassoc <string> '*'
190 %token WEBKIT_RULE_SYM
191 %token WEBKIT_DECLS_SYM
192 %token WEBKIT_VALUE_SYM
193 %token WEBKIT_MEDIAQUERY_SYM
216 %token <string> DIMEN
217 %token <val> PERCENTAGE
222 %token <string> FUNCTION
223 %token <string> NOTFUNCTION
225 %token <string> UNICODERANGE
227 %type <relation> combinator
234 %type <rule> font_face
235 %type <rule> invalid_rule
236 %type <rule> invalid_at
237 %type <rule> invalid_import
240 %type <string> maybe_ns_prefix
242 %type <string> namespace_selector
244 %type <string> string_or_uri
245 %type <string> ident_or_string
246 %type <string> medium
247 %type <string> hexcolor
249 %type <string> media_feature
250 %type <mediaList> media_list
251 %type <mediaList> maybe_media_list
252 %type <mediaQuery> media_query
253 %type <mediaQueryRestrictor> maybe_media_restrictor
254 %type <valueList> maybe_media_value
255 %type <mediaQueryExp> media_query_exp
256 %type <mediaQueryExpList> media_query_exp_list
257 %type <mediaQueryExpList> maybe_media_query_exp_list
259 %type <ruleList> ruleset_list
261 %type <prop_id> property
263 %type <selector> specifier
264 %type <selector> specifier_list
265 %type <selector> simple_selector
266 %type <selector> selector
267 %type <selector> selector_list
268 %type <selector> class
269 %type <selector> attrib
270 %type <selector> pseudo
272 %type <ok> declaration_list
274 %type <ok> declaration
279 %type <i> unary_operator
282 %type <valueList> expr
284 %type <value> unary_term
285 %type <value> function
287 %type <string> element_name
288 %type <string> attr_name
293 maybe_charset maybe_sgml import_list namespace_list rule_list
294 | webkit_rule maybe_space
295 | webkit_decls maybe_space
296 | webkit_value maybe_space
297 | webkit_mediaquery maybe_space
301 WEBKIT_RULE_SYM '{' maybe_space ruleset maybe_space '}' {
302 static_cast<CSSParser*>(parser)->rule = $4;
307 WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' {
313 WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
314 CSSParser *p = static_cast<CSSParser *>(parser);
316 p->valueList = p->sinkFloatingValueList($4);
317 int oldParsedProperties = p->numParsedProperties;
318 if (!p->parseValue(p->id, p->important))
319 p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties);
327 WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
328 CSSParser* p = static_cast<CSSParser*>(parser);
329 p->mediaQuery = p->sinkFloatingMediaQuery($4);
334 /* empty */ %prec UNIMPORTANT_TOK
335 | maybe_space WHITESPACE
341 | maybe_sgml WHITESPACE
351 CHARSET_SYM maybe_space STRING maybe_space ';' {
352 CSSParser* p = static_cast<CSSParser*>(parser);
353 $$ = static_cast<CSSParser *>(parser)->createCharsetRule($3);
354 if ($$ && p->styleElement && p->styleElement->isCSSStyleSheet())
355 p->styleElement->append($$);
357 | CHARSET_SYM error invalid_block {
359 | CHARSET_SYM error ';' {
365 | import_list import maybe_sgml {
366 CSSParser* p = static_cast<CSSParser*>(parser);
367 if ($2 && p->styleElement && p->styleElement->isCSSStyleSheet())
368 p->styleElement->append($2);
374 | namespace_list namespace maybe_sgml
379 | rule_list rule maybe_sgml {
380 CSSParser* p = static_cast<CSSParser*>(parser);
381 if ($2 && p->styleElement && p->styleElement->isCSSStyleSheet())
382 p->styleElement->append($2);
397 IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
398 $$ = static_cast<CSSParser *>(parser)->createImportRule($3, $5);
400 | IMPORT_SYM error invalid_block {
403 | IMPORT_SYM error ';' {
409 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
410 CSSParser *p = static_cast<CSSParser *>(parser);
411 if (p->styleElement && p->styleElement->isCSSStyleSheet())
412 static_cast<CSSStyleSheet*>(p->styleElement)->addNamespace(p, atomicString($3), atomicString($4));
414 | NAMESPACE_SYM error invalid_block
415 | NAMESPACE_SYM error ';'
419 /* empty */ { $$.characters = 0; }
420 | IDENT WHITESPACE { $$ = $1; }
438 | ':' maybe_space expr maybe_space {
444 MEDIA_AND maybe_space '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
446 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp(atomicString($5), $7);
450 media_query_exp_list:
452 CSSParser* p = static_cast<CSSParser*>(parser);
453 $$ = p->createFloatingMediaQueryExpList();
454 $$->append(p->sinkFloatingMediaQueryExp($1));
456 | media_query_exp_list media_query_exp {
458 $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($2));
462 maybe_media_query_exp_list:
464 $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
466 | media_query_exp_list
469 maybe_media_restrictor:
471 $$ = MediaQuery::None;
474 $$ = MediaQuery::Only;
477 $$ = MediaQuery::Not;
482 maybe_media_restrictor maybe_space medium maybe_media_query_exp_list {
483 CSSParser* p = static_cast<CSSParser*>(parser);
485 $$ = p->createFloatingMediaQuery($1, domString($3), p->sinkFloatingMediaQueryExpList($4));
491 $$ = static_cast<CSSParser*>(parser)->createMediaList();
498 CSSParser* p = static_cast<CSSParser*>(parser);
499 $$ = p->createMediaList();
500 $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
502 | media_list ',' maybe_space media_query {
505 $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
513 MEDIA_SYM maybe_space media_list '{' maybe_space ruleset_list '}' {
514 $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
516 | MEDIA_SYM maybe_space '{' maybe_space ruleset_list '}' {
517 $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
522 /* empty */ { $$ = 0; }
523 | ruleset_list ruleset maybe_space {
527 $$ = static_cast<CSSParser*>(parser)->createRuleList();
541 PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space
542 '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
550 : FONT_FACE_SYM maybe_space
551 '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
556 PAGE_SYM error invalid_block {
559 | PAGE_SYM error ';' {
565 FONT_FACE_SYM error invalid_block {
568 | FONT_FACE_SYM error ';' {
574 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
575 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
576 | '>' maybe_space { $$ = CSSSelector::Child; }
577 | /* empty */ { $$ = CSSSelector::Descendant; }
586 selector_list '{' maybe_space declaration_list '}' {
587 $$ = static_cast<CSSParser*>(parser)->createStyleRule($1);
592 selector %prec UNIMPORTANT_TOK {
595 | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
597 CSSParser* p = static_cast<CSSParser*>(parser);
599 $$->append(p->sinkFloatingSelector($4));
604 | selector_list error {
613 | selector combinator simple_selector {
619 CSSParser* p = static_cast<CSSParser*>(parser);
620 CSSSelector* end = $$;
621 while (end->tagHistory)
622 end = end->tagHistory;
623 end->m_relation = $2;
624 end->tagHistory = p->sinkFloatingSelector($1);
625 if ($2 == CSSSelector::Descendant || $2 == CSSSelector::Child) {
626 if (Document* doc = p->document())
627 doc->setUsesDescendantRules(true);
628 } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
629 if (Document* doc = p->document())
630 doc->setUsesSiblingRules(true);
640 /* empty */ '|' { $$.characters = 0; $$.length = 0; }
641 | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; }
642 | IDENT '|' { $$ = $1; }
646 element_name maybe_space {
647 CSSParser *p = static_cast<CSSParser *>(parser);
648 $$ = p->createFloatingSelector();
649 $$->tag = QualifiedName(nullAtom, atomicString($1), p->defaultNamespace);
651 | element_name specifier_list maybe_space {
654 CSSParser *p = static_cast<CSSParser *>(parser);
655 $$->tag = QualifiedName(nullAtom, atomicString($1), p->defaultNamespace);
658 | specifier_list maybe_space {
660 CSSParser *p = static_cast<CSSParser *>(parser);
661 if ($$ && p->defaultNamespace != starAtom)
662 $$->tag = QualifiedName(nullAtom, starAtom, p->defaultNamespace);
664 | namespace_selector element_name maybe_space {
665 AtomicString namespacePrefix = atomicString($1);
666 CSSParser *p = static_cast<CSSParser *>(parser);
667 $$ = p->createFloatingSelector();
668 if (p->styleElement && p->styleElement->isCSSStyleSheet())
669 $$->tag = QualifiedName(namespacePrefix,
671 static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
672 else // FIXME: Shouldn't this case be an error?
673 $$->tag = QualifiedName(nullAtom, atomicString($2), p->defaultNamespace);
675 | namespace_selector element_name specifier_list maybe_space {
678 AtomicString namespacePrefix = atomicString($1);
679 CSSParser *p = static_cast<CSSParser *>(parser);
680 if (p->styleElement && p->styleElement->isCSSStyleSheet())
681 $$->tag = QualifiedName(namespacePrefix,
683 static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
684 else // FIXME: Shouldn't this case be an error?
685 $$->tag = QualifiedName(nullAtom, atomicString($2), p->defaultNamespace);
688 | namespace_selector specifier_list maybe_space {
691 AtomicString namespacePrefix = atomicString($1);
692 CSSParser *p = static_cast<CSSParser *>(parser);
693 if (p->styleElement && p->styleElement->isCSSStyleSheet())
694 $$->tag = QualifiedName(namespacePrefix,
696 static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
703 ParseString& str = $1;
704 CSSParser *p = static_cast<CSSParser *>(parser);
705 Document *doc = p->document();
706 if (doc && doc->isHTMLDocument())
711 static UChar star = '*';
712 $$.characters = ☆
721 | specifier_list specifier {
724 CSSParser* p = static_cast<CSSParser*>(parser);
725 CSSSelector* end = $1;
726 while (end->tagHistory)
727 end = end->tagHistory;
728 end->m_relation = CSSSelector::SubSelector;
729 end->tagHistory = p->sinkFloatingSelector($2);
732 | specifier_list error {
739 CSSParser *p = static_cast<CSSParser *>(parser);
740 $$ = p->createFloatingSelector();
741 $$->match = CSSSelector::Id;
745 $$->value = atomicString($1);
754 CSSParser *p = static_cast<CSSParser *>(parser);
755 $$ = p->createFloatingSelector();
756 $$->match = CSSSelector::Class;
759 $$->attr = classAttr;
760 $$->value = atomicString($2);
766 ParseString& str = $1;
767 CSSParser *p = static_cast<CSSParser *>(parser);
768 Document *doc = p->document();
769 if (doc && doc->isHTMLDocument())
776 '[' maybe_space attr_name ']' {
777 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
778 $$->attr = QualifiedName(nullAtom, atomicString($3), nullAtom);
779 $$->match = CSSSelector::Set;
781 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
782 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
783 $$->attr = QualifiedName(nullAtom, atomicString($3), nullAtom);
784 $$->match = (CSSSelector::Match)$4;
785 $$->value = atomicString($6);
787 | '[' maybe_space namespace_selector attr_name ']' {
788 AtomicString namespacePrefix = atomicString($3);
789 CSSParser *p = static_cast<CSSParser *>(parser);
790 $$ = p->createFloatingSelector();
791 $$->attr = QualifiedName(namespacePrefix,
793 static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
794 $$->match = CSSSelector::Set;
796 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
797 AtomicString namespacePrefix = atomicString($3);
798 CSSParser *p = static_cast<CSSParser *>(parser);
799 $$ = p->createFloatingSelector();
800 $$->attr = QualifiedName(namespacePrefix,
802 static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
803 $$->match = (CSSSelector::Match)$5;
804 $$->value = atomicString($7);
810 $$ = CSSSelector::Exact;
813 $$ = CSSSelector::List;
816 $$ = CSSSelector::Hyphen;
819 $$ = CSSSelector::Begin;
822 $$ = CSSSelector::End;
825 $$ = CSSSelector::Contain;
836 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
837 $$->match = CSSSelector::PseudoClass;
839 $$->value = atomicString($2);
840 if ($$->value == "empty" || $$->value == "only-child" ||
841 $$->value == "first-child" || $$->value == "last-child") {
842 CSSParser *p = static_cast<CSSParser *>(parser);
843 Document *doc = p->document();
845 doc->setUsesSiblingRules(true);
849 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
850 $$->match = CSSSelector::PseudoElement;
852 $$->value = atomicString($3);
855 | ':' FUNCTION IDENT ')' {
856 $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
857 $$->match = CSSSelector::PseudoClass;
858 $$->argument = atomicString($3);
860 $$->value = atomicString($2);
863 | ':' NOTFUNCTION maybe_space simple_selector ')' {
864 CSSParser* p = static_cast<CSSParser*>(parser);
865 $$ = p->createFloatingSelector();
866 $$->match = CSSSelector::PseudoClass;
867 $$->simpleSelector = p->sinkFloatingSelector($4);
869 $$->value = atomicString($2);
877 | decl_list declaration {
885 | error invalid_block_list error {
897 declaration ';' maybe_space {
900 | declaration invalid_block_list ';' maybe_space {
903 | error ';' maybe_space {
906 | error invalid_block_list error ';' maybe_space {
909 | decl_list declaration ';' maybe_space {
914 | decl_list error ';' maybe_space {
917 | decl_list error invalid_block_list error ';' maybe_space {
923 property ':' maybe_space expr prio {
925 CSSParser *p = static_cast<CSSParser *>(parser);
927 p->valueList = p->sinkFloatingValueList($4);
928 int oldParsedProperties = p->numParsedProperties;
929 $$ = p->parseValue($1, $5);
931 p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties);
941 property ':' maybe_space error expr prio {
942 /* The default movable type template has letter-spacing: .none; Handle this by looking for
943 error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
944 up and deleting the shifted expr. */
948 IMPORTANT_SYM maybe_space {
949 /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
953 property ':' maybe_space {
954 /* div { font-family: } Just reduce away this property with no value. */
962 DeprecatedString str = deprecatedString($1);
963 const char* s = str.ascii();
964 int l = str.length();
965 $$ = getPropertyID(s, l);
968 $$ = SVG::getSVGCSSPropertyID(s, l);
974 IMPORTANT_SYM maybe_space { $$ = true; }
975 | /* empty */ { $$ = false; }
980 CSSParser* p = static_cast<CSSParser*>(parser);
981 $$ = p->createFloatingValueList();
982 $$->addValue(p->sinkFloatingValue($1));
984 | expr operator term {
985 CSSParser* p = static_cast<CSSParser*>(parser);
991 v.unit = Value::Operator;
995 $$->addValue(p->sinkFloatingValue($3));
1016 unary_term { $$ = $1; }
1017 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
1018 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
1019 | IDENT maybe_space {
1020 DeprecatedString str = deprecatedString($1);
1021 $$.id = getValueID(str.lower().latin1(), str.length());
1024 $$.id = SVG::getSVGCSSValueID(str.lower().latin1(), str.length());
1026 $$.unit = CSSPrimitiveValue::CSS_IDENT;
1029 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1030 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION }
1031 | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION }
1032 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
1033 | UNICODERANGE maybe_space { $$.id = 0; $$.iValue = 0; $$.unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ }
1034 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; }
1035 | '#' maybe_space { $$.id = 0; $$.string = ParseString(); $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; } /* Handle error case: "color: #;" */
1036 /* ### according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1043 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1044 | FLOAT maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
1045 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
1046 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
1047 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
1048 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
1049 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
1050 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
1051 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
1052 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
1053 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
1054 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
1055 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
1056 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
1057 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
1058 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
1059 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
1060 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS; }
1061 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
1066 FUNCTION maybe_space expr ')' maybe_space {
1067 CSSParser* p = static_cast<CSSParser*>(parser);
1068 Function* f = p->createFloatingFunction();
1070 f->args = p->sinkFloatingValueList($3);
1072 $$.unit = Value::Function;
1075 FUNCTION maybe_space error {
1076 CSSParser* p = static_cast<CSSParser*>(parser);
1077 Function* f = p->createFloatingFunction();
1081 $$.unit = Value::Function;
1086 * There is a constraint on the color that it must
1087 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1088 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1091 HASH maybe_space { $$ = $1; }
1095 /* error handling rules */
1098 '@' error invalid_block {
1113 error invalid_block {
1117 Seems like the two rules below are trying too much and violating
1118 http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1130 '{' error invalid_block_list error '}'
1136 | invalid_block_list error invalid_block