Warning, /frameworks/khtml/src/css/parser.y is written in an unsupported language. File is not indexed.
0001 %{ 0002 0003 /* 0004 * This file is part of the KDE libraries 0005 * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org) 0006 * Copyright (c) 2003 Apple Computer 0007 * Copyright (C) 2003 Dirk Mueller (mueller@kde.org) 0008 * Copyright (C) 2008 Germain Garand (germain@ebooksfrance.org) 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Lesser General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2 of the License, or (at your option) any later version. 0014 * 0015 * This library is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 * Lesser General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Lesser General Public 0021 * License along with this library; if not, write to the Free Software 0022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0023 * 0024 */ 0025 0026 #include <string.h> 0027 #include <stdlib.h> 0028 0029 #include <dom/dom_string.h> 0030 #include <xml/dom_docimpl.h> 0031 #include <css/cssstyleselector.h> 0032 #include <css/css_ruleimpl.h> 0033 #include <css/css_stylesheetimpl.h> 0034 #include <css/css_valueimpl.h> 0035 #include <css/css_mediaquery.h> 0036 #include "cssparser.h" 0037 0038 0039 0040 #include <assert.h> 0041 #include <QDebug> 0042 0043 //#define CSS_DEBUG 0044 0045 using namespace DOM; 0046 0047 // 0048 // The following file defines the function 0049 // const struct props *findProp(const char *word, int len) 0050 // 0051 // with 'props->id' a CSS property in the range from CSS_PROP_MIN to 0052 // (and including) CSS_PROP_TOTAL-1 0053 0054 // Turn off gnu90 inlining to avoid linker errors 0055 #undef __GNUC_STDC_INLINE__ 0056 #undef __GNUC_GNU_INLINE__ 0057 #include "cssproperties.c" 0058 #include "cssvalues.c" 0059 0060 int DOM::getPropertyID(const char *tagStr, int len) 0061 { 0062 { // HTML CSS Properties 0063 const struct css_prop *prop = findProp(tagStr, len); 0064 if (!prop) { 0065 return 0; 0066 } 0067 0068 return prop->id; 0069 } 0070 } 0071 0072 int DOM::getValueID(const char *tagStr, int len) 0073 { 0074 { // HTML CSS Values 0075 const struct css_value *val = findValue(tagStr, len); 0076 if (!val) { 0077 return 0; 0078 } 0079 0080 return val->id; 0081 } 0082 } 0083 0084 #define YYDEBUG 0 0085 #define YYMAXDEPTH 10000 0086 #define YYPARSE_PARAM parser 0087 #define YYENABLE_NLS 0 0088 #define YYLTYPE_IS_TRIVIAL 1 0089 %} 0090 0091 %expect 41 0092 0093 %pure_parser 0094 0095 %union { 0096 CSSRuleImpl *rule; 0097 CSSSelector *selector; 0098 QList<CSSSelector *> *selectorList; 0099 bool ok; 0100 MediaListImpl *mediaList; 0101 CSSMediaRuleImpl *mediaRule; 0102 CSSRuleListImpl *ruleList; 0103 ParseString string; 0104 double val; 0105 int prop_id; 0106 unsigned int attribute; 0107 unsigned int element; 0108 CSSSelector::Relation relation; 0109 CSSSelector::Match match; 0110 bool b; 0111 char tok; 0112 Value value; 0113 ValueList *valueList; 0114 0115 khtml::MediaQuery *mediaQuery; 0116 khtml::MediaQueryExp *mediaQueryExp; 0117 QList<khtml::MediaQueryExp *> *mediaQueryExpList; 0118 khtml::MediaQuery::Restrictor mediaQueryRestrictor; 0119 } 0120 0121 %{ 0122 0123 static inline int cssyyerror(const char *x) 0124 { 0125 #ifdef CSS_DEBUG 0126 qDebug("%s", x); 0127 #else 0128 Q_UNUSED(x); 0129 #endif 0130 return 1; 0131 } 0132 0133 static int cssyylex(YYSTYPE *yylval) { 0134 return CSSParser::current()->lex(yylval); 0135 } 0136 0137 #define null 1 0138 0139 %} 0140 0141 %destructor { delete $$; $$ = 0; } maybe_media_value expr; 0142 %destructor { delete $$; $$ = 0; } maybe_media_list media_list; 0143 %destructor { delete $$; $$ = 0; } maybe_and_media_query_exp_list media_query_exp_list; 0144 %destructor { if ($$) qDeleteAll(*$$); delete $$; $$ = 0; } selector_list; 0145 %destructor { delete $$; $$ = 0; } ruleset_list; 0146 %destructor { delete $$; $$ = 0; } specifier specifier_list simple_selector simple_css3_selector selector class attrib pseudo; 0147 %destructor { if ($$.function) delete $$.function->args; delete $$.function; $$.function = 0; } function; 0148 0149 %no-lines 0150 %verbose 0151 0152 %left REDUCE 0153 0154 %token S SGML_CD 0155 0156 %token INCLUDES 0157 %token DASHMATCH 0158 %token BEGINSWITH 0159 %token ENDSWITH 0160 %token CONTAINS 0161 0162 %token <string> STRING 0163 0164 %right <string> IDENT 0165 0166 %token <string> NTH 0167 0168 %nonassoc <string> HASH 0169 %nonassoc <string> HEXCOLOR 0170 %nonassoc ':' 0171 %nonassoc '.' 0172 %nonassoc '[' 0173 %nonassoc '*' 0174 %nonassoc error 0175 %left '|' 0176 0177 %left IMPORT_SYM 0178 %token PAGE_SYM 0179 %token MEDIA_SYM 0180 %token FONT_FACE_SYM 0181 %token CHARSET_SYM 0182 %token NAMESPACE_SYM 0183 %token KHTML_RULE_SYM 0184 %token KHTML_DECLS_SYM 0185 %token KHTML_VALUE_SYM 0186 %token KHTML_MEDIAQUERY_SYM 0187 %token KHTML_SELECTORS_SYM 0188 0189 %token IMPORTANT_SYM 0190 %token MEDIA_ONLY 0191 %token MEDIA_NOT 0192 %token MEDIA_AND 0193 0194 %token <val> QEMS 0195 %token <val> EMS 0196 %token <val> EXS 0197 %token <val> CHS 0198 %token <val> REMS 0199 %token <val> PXS 0200 %token <val> CMS 0201 %token <val> MMS 0202 %token <val> INS 0203 %token <val> PTS 0204 %token <val> PCS 0205 %token <val> DEGS 0206 %token <val> RADS 0207 %token <val> GRADS 0208 %token <val> MSECS 0209 %token <val> SECS 0210 %token <val> HERZ 0211 %token <val> KHERZ 0212 %token <val> DPI 0213 %token <val> DPCM 0214 %token <string> DIMEN 0215 %token <val> PERCENTAGE 0216 %token <val> FLOAT 0217 %token <val> INTEGER 0218 0219 %token <string> URI 0220 %token <string> FUNCTION 0221 %token <string> NOTFUNCTION 0222 0223 %token <string> UNICODERANGE 0224 0225 %type <relation> combinator 0226 0227 %type <rule> charset 0228 %type <rule> ruleset 0229 %type <rule> safe_ruleset 0230 %type <rule> ruleset_or_import_or_namespace 0231 %type <rule> media 0232 %type <rule> import 0233 %type <rule> page 0234 %type <rule> font_face 0235 %type <rule> invalid_rule 0236 %type <rule> namespace_rule 0237 %type <rule> invalid_at 0238 %type <rule> rule 0239 0240 %type <string> namespace_selector 0241 0242 %type <string> string_or_uri 0243 %type <string> ident_or_string 0244 %type <string> medium 0245 %type <string> hexcolor 0246 %type <string> maybe_ns_prefix 0247 0248 %type <string> media_feature 0249 %type <mediaList> media_list 0250 %type <mediaList> maybe_media_list 0251 %type <mediaQuery> media_query 0252 %type <mediaQueryRestrictor> maybe_media_restrictor 0253 %type <valueList> maybe_media_value 0254 %type <mediaQueryExp> media_query_exp 0255 %type <mediaQueryExpList> media_query_exp_list 0256 %type <mediaQueryExpList> maybe_and_media_query_exp_list 0257 0258 %type <ruleList> ruleset_list 0259 0260 %type <prop_id> property 0261 0262 %type <selector> specifier 0263 %type <selector> specifier_list 0264 %type <selector> simple_selector 0265 %type <selector> simple_css3_selector 0266 %type <selector> selector 0267 %type <selectorList> selector_list 0268 %type <selector> class 0269 %type <selector> attrib 0270 %type <selector> pseudo 0271 0272 %type <ok> declaration_block 0273 %type <ok> declaration_list 0274 %type <ok> declaration 0275 0276 %type <b> prio 0277 0278 %type <match> match 0279 %type <val> unary_operator 0280 %type <tok> operator 0281 0282 %type <valueList> expr 0283 %type <value> term 0284 %type <value> unary_term 0285 %type <value> function 0286 0287 %type <element> element_name 0288 0289 %type <attribute> attrib_id 0290 0291 %% 0292 0293 stylesheet: 0294 maybe_space maybe_charset maybe_sgml import_list namespace_list rule_list 0295 | khtml_rule maybe_space 0296 | khtml_decls maybe_space 0297 | khtml_value maybe_space 0298 | khtml_mediaquery maybe_space 0299 | khtml_selectors maybe_space 0300 ; 0301 0302 ruleset_or_import_or_namespace: 0303 ruleset | 0304 import | 0305 namespace_rule 0306 ; 0307 0308 khtml_rule: 0309 KHTML_RULE_SYM '{' maybe_space ruleset_or_import_or_namespace maybe_space '}' { 0310 CSSParser *p = static_cast<CSSParser *>(parser); 0311 p->rule = $4; 0312 } 0313 ; 0314 0315 khtml_decls: 0316 KHTML_DECLS_SYM declaration_block { 0317 /* can be empty */ 0318 } 0319 ; 0320 0321 khtml_value: 0322 KHTML_VALUE_SYM '{' maybe_space expr '}' { 0323 CSSParser *p = static_cast<CSSParser *>(parser); 0324 if ( $4 ) { 0325 p->valueList = $4; 0326 #ifdef CSS_DEBUG 0327 qDebug() << " got property for " << p->id << 0328 (p->important?" important":""); 0329 bool ok = 0330 #endif 0331 p->parseValue( p->id, p->important ); 0332 #ifdef CSS_DEBUG 0333 if ( !ok ) 0334 qDebug() << " couldn't parse value!"; 0335 #endif 0336 } 0337 #ifdef CSS_DEBUG 0338 else 0339 qDebug() << " no value found!"; 0340 #endif 0341 delete p->valueList; 0342 p->valueList = 0; 0343 } 0344 ; 0345 0346 khtml_selectors: 0347 KHTML_SELECTORS_SYM '{' maybe_space selector_list '}' { 0348 CSSParser *p = static_cast<CSSParser *>(parser); 0349 if ($4) { 0350 p->selectors = *$4; 0351 delete $4; 0352 $4 = 0; 0353 } else 0354 p->selectors.clear(); // parse error 0355 } 0356 ; 0357 0358 khtml_mediaquery: 0359 KHTML_MEDIAQUERY_SYM S maybe_space media_query '}' { 0360 CSSParser *p = static_cast<CSSParser *>(parser); 0361 p->mediaQuery = $4; 0362 } 0363 ; 0364 0365 maybe_plus: 0366 /* empty */ 0367 | '+' 0368 ; 0369 0370 maybe_space: 0371 /* empty */ %prec REDUCE 0372 | maybe_space S 0373 ; 0374 0375 maybe_sgml: 0376 /* empty */ 0377 | maybe_sgml SGML_CD 0378 | maybe_sgml S 0379 ; 0380 0381 maybe_charset: 0382 /* empty */ 0383 | charset 0384 ; 0385 charset: 0386 CHARSET_SYM maybe_space STRING maybe_space ';' { 0387 #ifdef CSS_DEBUG 0388 qDebug() << "charset rule: " << qString($3); 0389 #endif 0390 CSSParser* p = static_cast<CSSParser*>(parser); 0391 if (p->styleElement && p->styleElement->isCSSStyleSheet()) { 0392 p->styleElement->append( new CSSCharsetRuleImpl(p->styleElement, domString($3)) ); 0393 } 0394 } 0395 | CHARSET_SYM error invalid_block { 0396 } 0397 | CHARSET_SYM error ';' { 0398 } 0399 ; 0400 0401 import_list: 0402 /* empty */ 0403 | import_list import maybe_sgml { 0404 CSSParser *p = static_cast<CSSParser *>(parser); 0405 if ( $2 && p->styleElement && p->styleElement->isCSSStyleSheet() ) { 0406 p->styleElement->append( $2 ); 0407 } else { 0408 delete $2; 0409 } 0410 } 0411 ; 0412 0413 import: 0414 IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' { 0415 #ifdef CSS_DEBUG 0416 qDebug() << "@import: " << qString($3); 0417 #endif 0418 CSSParser *p = static_cast<CSSParser *>(parser); 0419 if ( $5 && p->styleElement && p->styleElement->isCSSStyleSheet() ) 0420 $$ = new CSSImportRuleImpl( p->styleElement, domString($3), $5 ); 0421 else 0422 $$ = 0; 0423 } 0424 | IMPORT_SYM error invalid_block { 0425 $$ = 0; 0426 } 0427 | IMPORT_SYM error ';' { 0428 $$ = 0; 0429 } 0430 ; 0431 0432 namespace_list: 0433 /* empty */ %prec REDUCE 0434 | namespace_list namespace maybe_sgml 0435 ; 0436 0437 namespace_rule: 0438 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri { 0439 #ifdef CSS_DEBUG 0440 qDebug() << "@namespace: " << qString($3) << qString($4); 0441 #endif 0442 CSSParser *p = static_cast<CSSParser *>(parser); 0443 $$ = new CSSNamespaceRuleImpl(p->styleElement, domString($3), domString($4)); 0444 } 0445 ; 0446 0447 namespace: 0448 namespace_rule maybe_space ';' { 0449 CSSParser *p = static_cast<CSSParser *>(parser); 0450 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0451 static_cast<CSSStyleSheetImpl*>(p->styleElement)->appendNamespaceRule 0452 (static_cast<CSSNamespaceRuleImpl*>($1)); 0453 // can't use ->append since it 0454 // wouldn't keep track of dirtiness 0455 } 0456 | NAMESPACE_SYM error invalid_block 0457 | NAMESPACE_SYM error ';' 0458 ; 0459 0460 maybe_ns_prefix: 0461 /* empty */ { $$.string = 0; } 0462 | IDENT S { $$ = $1; } 0463 ; 0464 0465 rule_list: 0466 /* empty */ 0467 | rule_list rule maybe_sgml { 0468 CSSParser *p = static_cast<CSSParser *>(parser); 0469 if ( $2 && p->styleElement && p->styleElement->isCSSStyleSheet() ) { 0470 p->styleElement->append( $2 ); 0471 } else { 0472 delete $2; 0473 } 0474 } 0475 ; 0476 0477 rule: 0478 ruleset 0479 | media 0480 | page 0481 | font_face 0482 | invalid_rule 0483 | invalid_at 0484 | import error { delete $1; $$ = 0; } 0485 ; 0486 0487 safe_ruleset: 0488 ruleset 0489 | invalid_rule 0490 | invalid_at 0491 | import error { delete $1; $$ = 0; } 0492 ; 0493 0494 string_or_uri: 0495 STRING 0496 | URI 0497 ; 0498 0499 media_feature: 0500 IDENT maybe_space { 0501 $$ = $1; 0502 } 0503 ; 0504 0505 maybe_media_value: 0506 /*empty*/ { 0507 $$ = 0; 0508 } 0509 | ':' maybe_space expr maybe_space { 0510 $$ = $3; 0511 } 0512 ; 0513 0514 media_query_exp: 0515 '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space { 0516 $$ = new khtml::MediaQueryExp(domString($3).lower(), $5); 0517 } 0518 ; 0519 0520 media_query_exp_list: 0521 media_query_exp { 0522 $$ = new QList<khtml::MediaQueryExp*>; 0523 $$->append($1); 0524 } 0525 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp { 0526 $$ = $1; 0527 $$->append($5); 0528 } 0529 ; 0530 0531 maybe_and_media_query_exp_list: 0532 /*empty*/ { 0533 $$ = new QList<khtml::MediaQueryExp*>; 0534 } 0535 | MEDIA_AND maybe_space media_query_exp_list { 0536 $$ = $3; 0537 } 0538 ; 0539 0540 maybe_media_restrictor: 0541 /*empty*/ { 0542 $$ = khtml::MediaQuery::None; 0543 } 0544 | MEDIA_ONLY { 0545 $$ = khtml::MediaQuery::Only; 0546 } 0547 | MEDIA_NOT { 0548 $$ = khtml::MediaQuery::Not; 0549 } 0550 ; 0551 0552 media_query: 0553 media_query_exp_list { 0554 $$ = new khtml::MediaQuery(khtml::MediaQuery::None, "all", $1); 0555 } 0556 | maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list { 0557 $$ = new khtml::MediaQuery($1, domString($3).lower(), $4); 0558 } 0559 ; 0560 0561 maybe_media_list: 0562 /* empty */ { 0563 $$ = new MediaListImpl(); 0564 } 0565 | media_list 0566 ; 0567 0568 0569 media_list: 0570 media_query { 0571 $$ = new MediaListImpl(); 0572 $$->appendMediaQuery($1); 0573 } 0574 | media_list ',' maybe_space media_query { 0575 $$ = $1; 0576 if ($$) 0577 $$->appendMediaQuery( $4 ); 0578 } 0579 | media_list error { 0580 delete $1; 0581 $$ = 0; 0582 } 0583 ; 0584 0585 media: 0586 MEDIA_SYM maybe_space media_list '{' maybe_space ruleset_list '}' { 0587 CSSParser *p = static_cast<CSSParser *>(parser); 0588 if ( $3 && $6 && 0589 p->styleElement && p->styleElement->isCSSStyleSheet() ) { 0590 $$ = new CSSMediaRuleImpl( static_cast<CSSStyleSheetImpl*>(p->styleElement), $3, $6 ); 0591 } else { 0592 $$ = 0; 0593 delete $3; 0594 delete $6; 0595 } 0596 } 0597 | MEDIA_SYM maybe_space '{' maybe_space ruleset_list '}' { 0598 CSSParser *p = static_cast<CSSParser *>(parser); 0599 if ($5 && p->styleElement && p->styleElement->isCSSStyleSheet() ) { 0600 $$ = new CSSMediaRuleImpl( static_cast<CSSStyleSheetImpl*>(p->styleElement), 0, $5); 0601 } else { 0602 $$ = 0; 0603 delete $5; 0604 } 0605 } 0606 ; 0607 0608 ruleset_list: 0609 /* empty */ { $$ = 0; } 0610 | ruleset_list safe_ruleset maybe_space { 0611 $$ = $1; 0612 if ( $2 ) { 0613 if ( !$$ ) $$ = new CSSRuleListImpl(); 0614 $$->append( $2 ); 0615 } 0616 } 0617 ; 0618 0619 medium: 0620 IDENT maybe_space { 0621 $$ = $1; 0622 } 0623 ; 0624 0625 /* 0626 page: 0627 PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space 0628 '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space 0629 ; 0630 0631 pseudo_page 0632 : ':' IDENT 0633 ; 0634 0635 */ 0636 0637 page: 0638 PAGE_SYM error invalid_block { 0639 $$ = 0; 0640 } 0641 | PAGE_SYM error ';' { 0642 $$ = 0; 0643 } 0644 ; 0645 0646 font_face: 0647 FONT_FACE_SYM maybe_space declaration_block { 0648 CSSParser *p = static_cast<CSSParser *>(parser); 0649 CSSFontFaceRuleImpl *rule = new CSSFontFaceRuleImpl( p->styleElement ); 0650 CSSStyleDeclarationImpl *decl = p->createFontFaceStyleDeclaration( rule ); 0651 rule->setDeclaration(decl); 0652 $$ = rule; 0653 } 0654 | FONT_FACE_SYM error invalid_block { 0655 $$ = 0; 0656 } 0657 | FONT_FACE_SYM error ';' { 0658 $$ = 0; 0659 } 0660 ; 0661 0662 combinator: 0663 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; } 0664 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; } 0665 | '>' maybe_space { $$ = CSSSelector::Child; } 0666 ; 0667 0668 unary_operator: 0669 '-' { $$ = -1; } 0670 | '+' { $$ = 1; } 0671 ; 0672 0673 ruleset: 0674 selector_list declaration_block { 0675 #ifdef CSS_DEBUG 0676 qDebug() << "got ruleset" << endl << " selector:"; 0677 #endif 0678 CSSParser *p = static_cast<CSSParser *>(parser); 0679 if ( $1 ) { 0680 CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement ); 0681 CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule ); 0682 rule->setSelector( $1 ); 0683 rule->setDeclaration(decl); 0684 $$ = rule; 0685 } else { 0686 $$ = 0; 0687 if ($1) qDeleteAll(*$1); 0688 delete $1; 0689 $1 = 0; 0690 p->clearProperties(); 0691 } 0692 } 0693 ; 0694 0695 selector_list: 0696 selector %prec REDUCE { 0697 if ( $1 ) { 0698 $$ = new QList<CSSSelector*>; 0699 #ifdef CSS_DEBUG 0700 qDebug() << " got simple selector:"; 0701 $1->print(); 0702 #endif 0703 $$->append( $1 ); 0704 khtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), $1); 0705 } else { 0706 $$ = 0; 0707 } 0708 } 0709 | selector_list ',' maybe_space selector %prec REDUCE { 0710 if ( $1 && $4 ) { 0711 $$ = $1; 0712 $$->append( $4 ); 0713 khtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), $4); 0714 #ifdef CSS_DEBUG 0715 qDebug() << " got simple selector:"; 0716 $4->print(); 0717 #endif 0718 } else { 0719 if ($1) qDeleteAll(*$1); 0720 delete $1; 0721 $1=0; 0722 0723 delete $4; 0724 $$ = 0; 0725 } 0726 } 0727 | selector_list error { 0728 if ($1) qDeleteAll(*$1); 0729 delete $1; 0730 $1 = 0; 0731 $$ = 0; 0732 } 0733 ; 0734 0735 0736 selector: 0737 simple_selector { 0738 $$ = $1; 0739 } 0740 | selector S { 0741 $$ = $1; 0742 } 0743 | selector S simple_selector { 0744 if ( !$1 || !$3 ) { 0745 delete $1; 0746 delete $3; 0747 $$ = 0; 0748 } else { 0749 $$ = $3; 0750 CSSSelector *end = $$; 0751 while( end->tagHistory ) 0752 end = end->tagHistory; 0753 end->relation = CSSSelector::Descendant; 0754 end->tagHistory = $1; 0755 } 0756 } 0757 | selector combinator simple_selector { 0758 if ( !$1 || !$3 ) { 0759 delete $1; 0760 delete $3; 0761 $$ = 0; 0762 } else { 0763 $$ = $3; 0764 CSSSelector *end = $3; 0765 while( end->tagHistory ) 0766 end = end->tagHistory; 0767 end->relation = $2; 0768 end->tagHistory = $1; 0769 } 0770 } 0771 | selector error { 0772 delete $1; 0773 $$ = 0; 0774 } 0775 ; 0776 0777 namespace_selector: 0778 /* empty */ '|' { $$.string = 0; $$.length = 0; } 0779 | '*' '|' { static unsigned short star = '*'; $$.string = ☆ $$.length = 1; } 0780 | IDENT '|' { $$ = $1; } 0781 ; 0782 0783 simple_selector: 0784 element_name { 0785 $$ = new CSSSelector(); 0786 $$->tagLocalName = LocalName::fromId(localNamePart($1)); 0787 $$->tagNamespace = NamespaceName::fromId(namespacePart($1)); 0788 } 0789 | element_name specifier_list { 0790 $$ = $2; 0791 if ( $$ ) { 0792 $$->tagLocalName = LocalName::fromId(localNamePart($1)); 0793 $$->tagNamespace = NamespaceName::fromId(namespacePart($1)); 0794 } 0795 } 0796 | specifier_list { 0797 $$ = $1; 0798 if ( $$ ) { 0799 $$->tagLocalName = LocalName::fromId(anyLocalName); 0800 $$->tagNamespace = NamespaceName::fromId(static_cast<CSSParser*>(parser)->defaultNamespace()); 0801 } 0802 } 0803 | namespace_selector element_name { 0804 $$ = new CSSSelector(); 0805 $$->tagLocalName = LocalName::fromId(localNamePart($2)); 0806 $$->tagNamespace = NamespaceName::fromId(namespacePart($2)); 0807 CSSParser *p = static_cast<CSSParser *>(parser); 0808 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0809 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tagNamespace, domString($1)); 0810 } 0811 | namespace_selector element_name specifier_list { 0812 $$ = $3; 0813 if ($$) { 0814 $$->tagLocalName = LocalName::fromId(localNamePart($2)); 0815 $$->tagNamespace = NamespaceName::fromId(namespacePart($2)); 0816 CSSParser *p = static_cast<CSSParser *>(parser); 0817 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0818 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tagNamespace, domString($1)); 0819 } 0820 } 0821 | namespace_selector specifier_list { 0822 $$ = $2; 0823 if ($$) { 0824 $$->tagLocalName = LocalName::fromId(anyLocalName); 0825 $$->tagNamespace = NamespaceName::fromId(anyNamespace); 0826 CSSParser *p = static_cast<CSSParser *>(parser); 0827 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0828 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tagNamespace, domString($1)); 0829 } 0830 } 0831 ; 0832 0833 simple_css3_selector: 0834 element_name { 0835 $$ = new CSSSelector(); 0836 $$->tagLocalName = LocalName::fromId(localNamePart($1)); 0837 $$->tagNamespace = NamespaceName::fromId(namespacePart($1)); 0838 } 0839 | specifier { 0840 $$ = $1; 0841 if ( $$ ) { 0842 $$->tagLocalName = LocalName::fromId(anyLocalName); 0843 $$->tagNamespace = NamespaceName::fromId(static_cast<CSSParser*>(parser)->defaultNamespace()); 0844 } 0845 } 0846 | namespace_selector element_name { 0847 $$ = new CSSSelector(); 0848 $$->tagLocalName = LocalName::fromId(localNamePart($2)); 0849 $$->tagNamespace = NamespaceName::fromId(namespacePart($2)); 0850 CSSParser *p = static_cast<CSSParser *>(parser); 0851 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0852 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tagNamespace, domString($1)); 0853 } 0854 | namespace_selector specifier { 0855 $$ = $2; 0856 if ($$) { 0857 $$->tagLocalName = LocalName::fromId(anyLocalName); 0858 $$->tagNamespace = NamespaceName::fromId(anyNamespace); 0859 CSSParser *p = static_cast<CSSParser *>(parser); 0860 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0861 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tagNamespace, domString($1)); 0862 } 0863 } 0864 ; 0865 0866 element_name: 0867 IDENT { 0868 CSSParser *p = static_cast<CSSParser *>(parser); 0869 $$ = makeId(p->defaultNamespace(), p->getLocalNameId(domString($1))); 0870 } 0871 | '*' { 0872 $$ = makeId(static_cast<CSSParser*>(parser)->defaultNamespace(), anyLocalName); 0873 } 0874 ; 0875 0876 specifier_list: 0877 specifier { 0878 $$ = $1; 0879 } 0880 | specifier_list specifier { 0881 $$ = $1; 0882 if ( $$ ) { 0883 CSSSelector *end = $1; 0884 while( end->tagHistory ) 0885 end = end->tagHistory; 0886 end->relation = CSSSelector::SubSelector; 0887 end->tagHistory = $2; 0888 } 0889 } 0890 | specifier_list error { 0891 delete $1; 0892 $$ = 0; 0893 } 0894 ; 0895 0896 specifier: 0897 HASH { 0898 CSSParser *p = static_cast<CSSParser *>(parser); 0899 0900 $$ = new CSSSelector(); 0901 $$->match = CSSSelector::Id; 0902 $$->attrLocalName = LocalName::fromId(localNamePart(ATTR_ID)); 0903 $$->attrNamespace = NamespaceName::fromId(namespacePart(ATTR_ID)); 0904 0905 bool caseSensitive = p->document()->htmlMode() == DocumentImpl::XHtml || !p->document()->inCompatMode(); 0906 if (caseSensitive) 0907 $$->value = domString($1); 0908 else 0909 $$->value = domString($1).lower(); 0910 } 0911 | class 0912 | attrib 0913 | pseudo 0914 ; 0915 0916 class: 0917 '.' IDENT { 0918 CSSParser *p = static_cast<CSSParser *>(parser); 0919 0920 $$ = new CSSSelector(); 0921 $$->match = CSSSelector::Class; 0922 $$->attrLocalName = LocalName::fromId(localNamePart(ATTR_CLASS)); 0923 $$->attrNamespace = NamespaceName::fromId(namespacePart(ATTR_CLASS)); 0924 0925 bool caseSensitive = p->document()->htmlMode() == DocumentImpl::XHtml || !p->document()->inCompatMode(); 0926 if (caseSensitive) 0927 $$->value = domString($2); 0928 else 0929 $$->value = domString($2).lower(); 0930 } 0931 ; 0932 0933 attrib_id: 0934 IDENT maybe_space { 0935 CSSParser *p = static_cast<CSSParser *>(parser); 0936 $$ = makeId(emptyNamespace, p->getLocalNameId(domString($1))); 0937 } 0938 ; 0939 0940 attrib: 0941 '[' maybe_space attrib_id ']' { 0942 $$ = new CSSSelector(); 0943 $$->attrLocalName = LocalName::fromId(localNamePart($3)); 0944 $$->attrNamespace = NamespaceName::fromId(namespacePart($3)); 0945 $$->match = CSSSelector::Set; 0946 } 0947 | '[' maybe_space attrib_id match maybe_space ident_or_string maybe_space ']' { 0948 $$ = new CSSSelector(); 0949 $$->attrLocalName = LocalName::fromId(localNamePart($3)); 0950 $$->attrNamespace = NamespaceName::fromId(namespacePart($3)); 0951 $$->match = $4; 0952 $$->value = domString($6); 0953 } 0954 | '[' maybe_space namespace_selector attrib_id ']' { 0955 $$ = new CSSSelector(); 0956 $$->attrLocalName = LocalName::fromId(localNamePart($4)); 0957 $$->attrNamespace = NamespaceName::fromId(namespacePart($4)); 0958 $$->match = CSSSelector::Set; 0959 CSSParser *p = static_cast<CSSParser *>(parser); 0960 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0961 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attrNamespace, domString($3)); 0962 } 0963 | '[' maybe_space namespace_selector attrib_id match maybe_space ident_or_string maybe_space ']' { 0964 $$ = new CSSSelector(); 0965 $$->attrLocalName = LocalName::fromId(localNamePart($4)); 0966 $$->attrNamespace = NamespaceName::fromId(namespacePart($4)); 0967 $$->match = (CSSSelector::Match)$5; 0968 $$->value = domString($7); 0969 CSSParser *p = static_cast<CSSParser *>(parser); 0970 if (p->styleElement && p->styleElement->isCSSStyleSheet()) 0971 static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attrNamespace, domString($3)); 0972 } 0973 ; 0974 0975 match: 0976 '=' { 0977 $$ = CSSSelector::Exact; 0978 } 0979 | INCLUDES { 0980 $$ = CSSSelector::List; 0981 } 0982 | DASHMATCH { 0983 $$ = CSSSelector::Hyphen; 0984 } 0985 | BEGINSWITH { 0986 $$ = CSSSelector::Begin; 0987 } 0988 | ENDSWITH { 0989 $$ = CSSSelector::End; 0990 } 0991 | CONTAINS { 0992 $$ = CSSSelector::Contain; 0993 } 0994 ; 0995 0996 ident_or_string: 0997 IDENT 0998 | STRING 0999 ; 1000 1001 pseudo: 1002 ':' IDENT { 1003 $$ = new CSSSelector(); 1004 $$->match = CSSSelector::PseudoClass; 1005 $$->value = domString($2); 1006 } 1007 | 1008 ':' ':' IDENT { 1009 $$ = new CSSSelector(); 1010 $$->match = CSSSelector::PseudoElement; 1011 $$->value = domString($3); 1012 } 1013 // used by :nth-* 1014 | ':' FUNCTION maybe_space NTH maybe_space ')' { 1015 $$ = new CSSSelector(); 1016 $$->match = CSSSelector::PseudoClass; 1017 $$->string_arg = domString($4); 1018 $$->value = domString($2); 1019 } 1020 // used by :nth-* 1021 | ':' FUNCTION maybe_space maybe_plus INTEGER maybe_space ')' { 1022 $$ = new CSSSelector(); 1023 $$->match = CSSSelector::PseudoClass; 1024 $$->string_arg = QString::number($5); 1025 $$->value = domString($2); 1026 } 1027 // used by :nth-* and :lang 1028 | ':' FUNCTION maybe_space IDENT maybe_space ')' { 1029 $$ = new CSSSelector(); 1030 $$->match = CSSSelector::PseudoClass; 1031 $$->string_arg = domString($4); 1032 $$->value = domString($2); 1033 } 1034 // used by :contains and :lang 1035 | ':' FUNCTION maybe_space STRING maybe_space ')' { 1036 $$ = new CSSSelector(); 1037 $$->match = CSSSelector::PseudoClass; 1038 $$->string_arg = domString($4); 1039 $$->value = domString($2); 1040 } 1041 // used only by :not 1042 | ':' NOTFUNCTION maybe_space simple_css3_selector maybe_space ')' { 1043 $$ = new CSSSelector(); 1044 $$->match = CSSSelector::PseudoClass; 1045 $$->simpleSelector = $4; 1046 $$->value = domString($2); 1047 } 1048 ; 1049 1050 declaration_block: 1051 '{' maybe_space declaration '}' { 1052 $$ = $3; 1053 } 1054 | '{' maybe_space error '}' { 1055 $$ = false; 1056 } 1057 | '{' maybe_space declaration_list '}' { 1058 $$ = $3; 1059 } 1060 | '{' maybe_space declaration_list declaration '}' { 1061 $$ = $3; 1062 if ( $4 ) 1063 $$ = $4; 1064 } 1065 | '{' maybe_space declaration_list error '}' { 1066 $$ = $3; 1067 } 1068 ; 1069 1070 declaration_list: 1071 declaration ';' maybe_space { 1072 $$ = $1; 1073 } 1074 | 1075 error ';' maybe_space { 1076 $$ = false; 1077 } 1078 | declaration_list declaration ';' maybe_space { 1079 $$ = $1; 1080 if ( $2 ) 1081 $$ = $2; 1082 } 1083 | declaration_list error ';' maybe_space { 1084 $$ = $1; 1085 } 1086 ; 1087 1088 declaration: 1089 property ':' maybe_space expr prio { 1090 $$ = false; 1091 CSSParser *p = static_cast<CSSParser *>(parser); 1092 if ( $1 && $4 ) { 1093 p->valueList = $4; 1094 #ifdef CSS_DEBUG 1095 qDebug() << " got property: " << $1 << 1096 ($5?" important":""); 1097 #endif 1098 bool ok = p->parseValue( $1, $5 ); 1099 if ( ok ) 1100 $$ = ok; 1101 #ifdef CSS_DEBUG 1102 else 1103 qDebug() << " couldn't parse value!"; 1104 #endif 1105 } else { 1106 delete $4; 1107 } 1108 delete p->valueList; 1109 p->valueList = 0; 1110 } 1111 | error invalid_block { 1112 $$ = false; 1113 } 1114 ; 1115 1116 property: 1117 IDENT maybe_space { 1118 QString str = qString($1); 1119 $$ = getPropertyID(str.toLower().toLatin1(), str.length()); 1120 } 1121 ; 1122 1123 prio: 1124 IMPORTANT_SYM maybe_space { $$ = true; } 1125 | /* empty */ { $$ = false; } 1126 ; 1127 1128 expr: 1129 term { 1130 $$ = new ValueList; 1131 $$->addValue( $1 ); 1132 } 1133 | expr operator term { 1134 $$ = $1; 1135 if ( $$ ) { 1136 if ( $2 ) { 1137 Value v; 1138 v.id = 0; 1139 v.unit = Value::Operator; 1140 v.iValue = $2; 1141 $$->addValue( v ); 1142 } 1143 $$->addValue( $3 ); 1144 } 1145 } 1146 ; 1147 1148 operator: 1149 '/' maybe_space { 1150 $$ = '/'; 1151 } 1152 | ',' maybe_space { 1153 $$ = ','; 1154 } 1155 | /* empty */ { 1156 $$ = 0; 1157 } 1158 ; 1159 1160 term: 1161 unary_term { $$ = $1; } 1162 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } 1163 /* DIMEN is an unary_term, but since we store the string we must not modify fValue */ 1164 | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } 1165 | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } 1166 | IDENT maybe_space { 1167 QString str = qString( $1 ); 1168 $$.id = getValueID( str.toLower().toLatin1(), str.length() ); 1169 $$.unit = CSSPrimitiveValue::CSS_IDENT; 1170 $$.string = $1; 1171 } 1172 | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; } 1173 | UNICODERANGE maybe_space { $$.id = 0; $$.iValue = 0; $$.unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ } 1174 | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; } 1175 /* ### according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ 1176 | function { 1177 $$ = $1; 1178 } 1179 ; 1180 1181 unary_term: 1182 INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; } 1183 | FLOAT maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; } 1184 | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; } 1185 | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; } 1186 | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; } 1187 | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; } 1188 | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; } 1189 | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; } 1190 | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; } 1191 | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; } 1192 | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; } 1193 | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; } 1194 | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; } 1195 | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; } 1196 | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; } 1197 | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; } 1198 | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; } 1199 | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS; } 1200 | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; } 1201 | CHS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CHS; } 1202 | REMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_REMS; } 1203 | DPI maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPI; } 1204 | DPCM maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPCM; } 1205 ; 1206 1207 1208 function: 1209 FUNCTION maybe_space expr ')' maybe_space { 1210 Function *f = new Function; 1211 f->name = $1; 1212 f->args = $3; 1213 $$.id = 0; 1214 $$.unit = Value::Function; 1215 $$.function = f; 1216 } 1217 | FUNCTION maybe_space error { 1218 Function *f = new Function; 1219 f->name = $1; 1220 f->args = 0; 1221 $$.id = 0; 1222 $$.unit = Value::Function; 1223 $$.function = f; 1224 } 1225 1226 ; 1227 /* 1228 * There is a constraint on the color that it must 1229 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) 1230 * after the "#"; e.g., "#000" is OK, but "#abcd" is not. 1231 */ 1232 hexcolor: 1233 HEXCOLOR maybe_space { $$ = $1; } 1234 ; 1235 1236 1237 /* error handling rules */ 1238 1239 invalid_at: 1240 '@' error invalid_block { 1241 $$ = 0; 1242 #ifdef CSS_DEBUG 1243 qDebug() << "skipped invalid @-rule"; 1244 #endif 1245 } 1246 | '@' error ';' { 1247 $$ = 0; 1248 #ifdef CSS_DEBUG 1249 qDebug() << "skipped invalid @-rule"; 1250 #endif 1251 } 1252 ; 1253 1254 invalid_rule: 1255 error invalid_block { 1256 $$ = 0; 1257 #ifdef CSS_DEBUG 1258 qDebug() << "skipped invalid rule"; 1259 #endif 1260 } 1261 /* 1262 Seems like the two rules below are trying too much and violating 1263 https://www.hixie.ch/tests/evil/mixed/csserrorhandling.html 1264 1265 | error ';' { 1266 $$ = 0; 1267 #ifdef CSS_DEBUG 1268 qDebug() << "skipped invalid rule"; 1269 #endif 1270 } 1271 | error '}' { 1272 $$ = 0; 1273 #ifdef CSS_DEBUG 1274 qDebug() << "skipped invalid rule"; 1275 #endif 1276 } 1277 */ 1278 ; 1279 1280 invalid_block: 1281 '{' error invalid_block_list error '}' 1282 | '{' error '}' 1283 ; 1284 1285 invalid_block_list: 1286 invalid_block 1287 | invalid_block_list error invalid_block 1288 ; 1289 1290 %% 1291