1 %{ 2 3 /* 4 * Copyright (C) 2002-2003 Lars Knoll (knoll (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 * Copyright (C) 2006 Alexey Proskuryakov (ap (at) nypop.com) 7 * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org> 8 * Copyright (C) 2012 Intel Corporation. All rights reserved. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 */ 25 26 #include "config.h" 27 28 #include "CSSPropertyNames.h" 29 #include "HTMLNames.h" 30 #include "core/css/CSSKeyframeRule.h" 31 #include "core/css/CSSKeyframesRule.h" 32 #include "core/css/parser/BisonCSSParser.h" 33 #include "core/css/CSSParserMode.h" 34 #include "core/css/CSSPrimitiveValue.h" 35 #include "core/css/CSSSelector.h" 36 #include "core/css/CSSSelectorList.h" 37 #include "core/css/MediaList.h" 38 #include "core/css/MediaQueryExp.h" 39 #include "core/css/StyleRule.h" 40 #include "core/css/StyleSheetContents.h" 41 #include "core/dom/Document.h" 42 #include "wtf/FastMalloc.h" 43 #include <stdlib.h> 44 #include <string.h> 45 46 using namespace WebCore; 47 using namespace HTMLNames; 48 49 #define YYMALLOC fastMalloc 50 #define YYFREE fastFree 51 52 #define YYENABLE_NLS 0 53 #define YYLTYPE_IS_TRIVIAL 1 54 #define YYMAXDEPTH 10000 55 #define YYDEBUG 0 56 57 #if YYDEBUG > 0 58 #define YYPRINT(File,Type,Value) if (isCSSTokenAString(Type)) YYFPRINTF(File, "%s", String((Value).string).utf8().data()) 59 #endif 60 61 %} 62 63 %pure-parser 64 65 %parse-param { BisonCSSParser* parser } 66 %lex-param { BisonCSSParser* parser } 67 68 %union { 69 bool boolean; 70 char character; 71 int integer; 72 double number; 73 CSSParserString string; 74 75 StyleRuleBase* rule; 76 // The content of the three below HeapVectors are guaranteed to be kept alive by 77 // the corresponding m_parsedRules, m_floatingMediaQueryExpList, and m_parsedKeyFrames 78 // lists in BisonCSSParser.h. 79 WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >* ruleList; 80 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* mediaQueryExpList; 81 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeRuleList; 82 CSSParserSelector* selector; 83 Vector<OwnPtr<CSSParserSelector> >* selectorList; 84 CSSSelector::MarginBoxType marginBox; 85 CSSSelector::Relation relation; 86 MediaQuerySet* mediaList; 87 MediaQuery* mediaQuery; 88 MediaQuery::Restrictor mediaQueryRestrictor; 89 MediaQueryExp* mediaQueryExp; 90 CSSParserValue value; 91 CSSParserValueList* valueList; 92 StyleKeyframe* keyframe; 93 float val; 94 CSSPropertyID id; 95 CSSParserLocation location; 96 } 97 98 %{ 99 100 static inline int cssyyerror(void*, const char*) 101 { 102 return 1; 103 } 104 105 #if YYDEBUG > 0 106 static inline bool isCSSTokenAString(int yytype) 107 { 108 switch (yytype) { 109 case IDENT: 110 case STRING: 111 case NTH: 112 case HEX: 113 case IDSEL: 114 case DIMEN: 115 case INVALIDDIMEN: 116 case URI: 117 case FUNCTION: 118 case ANYFUNCTION: 119 case HOSTFUNCTION: 120 case HOSTCONTEXTFUNCTION: 121 case NOTFUNCTION: 122 case CALCFUNCTION: 123 case UNICODERANGE: 124 return true; 125 default: 126 return false; 127 } 128 } 129 #endif 130 131 inline static CSSParserValue makeOperatorValue(int value) 132 { 133 CSSParserValue v; 134 v.id = CSSValueInvalid; 135 v.isInt = false; 136 v.unit = CSSParserValue::Operator; 137 v.iValue = value; 138 return v; 139 } 140 141 inline static CSSParserValue makeIdentValue(CSSParserString string) 142 { 143 CSSParserValue v; 144 v.id = cssValueKeywordID(string); 145 v.isInt = false; 146 v.unit = CSSPrimitiveValue::CSS_IDENT; 147 v.string = string; 148 return v; 149 } 150 151 %} 152 153 %expect 0 154 155 %nonassoc LOWEST_PREC 156 157 %left UNIMPORTANT_TOK 158 159 %token WHITESPACE SGML_CD 160 %token TOKEN_EOF 0 161 162 %token INCLUDES 163 %token DASHMATCH 164 %token BEGINSWITH 165 %token ENDSWITH 166 %token CONTAINS 167 168 %token <string> STRING 169 %right <string> IDENT 170 %token <string> NTH 171 172 %nonassoc <string> HEX 173 %nonassoc <string> IDSEL 174 %nonassoc ':' 175 %nonassoc '.' 176 %nonassoc '[' 177 %nonassoc <string> '*' 178 %nonassoc error 179 %left '|' 180 181 %token IMPORT_SYM 182 %token PAGE_SYM 183 %token MEDIA_SYM 184 %token SUPPORTS_SYM 185 %token FONT_FACE_SYM 186 %token CHARSET_SYM 187 %token NAMESPACE_SYM 188 %token VIEWPORT_RULE_SYM 189 %token INTERNAL_DECLS_SYM 190 %token INTERNAL_MEDIALIST_SYM 191 %token INTERNAL_RULE_SYM 192 %token INTERNAL_SELECTOR_SYM 193 %token INTERNAL_VALUE_SYM 194 %token INTERNAL_KEYFRAME_RULE_SYM 195 %token INTERNAL_KEYFRAME_KEY_LIST_SYM 196 %token INTERNAL_SUPPORTS_CONDITION_SYM 197 %token KEYFRAMES_SYM 198 %token WEBKIT_KEYFRAMES_SYM 199 %token <marginBox> TOPLEFTCORNER_SYM 200 %token <marginBox> TOPLEFT_SYM 201 %token <marginBox> TOPCENTER_SYM 202 %token <marginBox> TOPRIGHT_SYM 203 %token <marginBox> TOPRIGHTCORNER_SYM 204 %token <marginBox> BOTTOMLEFTCORNER_SYM 205 %token <marginBox> BOTTOMLEFT_SYM 206 %token <marginBox> BOTTOMCENTER_SYM 207 %token <marginBox> BOTTOMRIGHT_SYM 208 %token <marginBox> BOTTOMRIGHTCORNER_SYM 209 %token <marginBox> LEFTTOP_SYM 210 %token <marginBox> LEFTMIDDLE_SYM 211 %token <marginBox> LEFTBOTTOM_SYM 212 %token <marginBox> RIGHTTOP_SYM 213 %token <marginBox> RIGHTMIDDLE_SYM 214 %token <marginBox> RIGHTBOTTOM_SYM 215 216 %token ATKEYWORD 217 218 %token IMPORTANT_SYM 219 %token MEDIA_ONLY 220 %token MEDIA_NOT 221 %token MEDIA_AND 222 %token MEDIA_OR 223 224 %token SUPPORTS_NOT 225 %token SUPPORTS_AND 226 %token SUPPORTS_OR 227 228 %token <number> REMS 229 %token <number> CHS 230 %token <number> QEMS 231 %token <number> EMS 232 %token <number> EXS 233 %token <number> PXS 234 %token <number> CMS 235 %token <number> MMS 236 %token <number> INS 237 %token <number> PTS 238 %token <number> PCS 239 %token <number> DEGS 240 %token <number> RADS 241 %token <number> GRADS 242 %token <number> TURNS 243 %token <number> MSECS 244 %token <number> SECS 245 %token <number> HERTZ 246 %token <number> KHERTZ 247 %token <string> DIMEN 248 %token <string> INVALIDDIMEN 249 %token <number> PERCENTAGE 250 %token <number> FLOATTOKEN 251 %token <number> INTEGER 252 %token <number> VW 253 %token <number> VH 254 %token <number> VMIN 255 %token <number> VMAX 256 %token <number> DPPX 257 %token <number> DPI 258 %token <number> DPCM 259 %token <number> FR 260 261 %token <string> URI 262 %token <string> FUNCTION 263 %token <string> ANYFUNCTION 264 %token <string> CUEFUNCTION 265 %token <string> NOTFUNCTION 266 %token <string> DISTRIBUTEDFUNCTION 267 %token <string> CALCFUNCTION 268 %token <string> HOSTFUNCTION 269 %token <string> HOSTCONTEXTFUNCTION 270 271 %token <string> UNICODERANGE 272 273 %type <relation> combinator 274 275 %type <rule> ruleset 276 %type <rule> media 277 %type <rule> import 278 %type <rule> namespace 279 %type <rule> page 280 %type <rule> margin_box 281 %type <rule> font_face 282 %type <rule> keyframes 283 %type <rule> rule 284 %type <rule> valid_rule 285 %type <ruleList> block_rule_body 286 %type <ruleList> block_rule_list 287 %type <rule> block_rule 288 %type <rule> block_valid_rule 289 %type <rule> supports 290 %type <rule> viewport 291 %type <boolean> keyframes_rule_start 292 293 %type <string> maybe_ns_prefix 294 295 %type <string> namespace_selector 296 297 %type <string> string_or_uri 298 %type <string> ident_or_string 299 %type <string> medium 300 %type <marginBox> margin_sym 301 302 %type <mediaList> media_list 303 %type <mediaList> maybe_media_list 304 %type <mediaList> mq_list 305 %type <mediaQuery> media_query 306 %type <mediaQuery> valid_media_query 307 %type <mediaQueryRestrictor> maybe_media_restrictor 308 %type <valueList> maybe_media_value 309 %type <mediaQueryExp> media_query_exp 310 %type <mediaQueryExpList> media_query_exp_list 311 %type <mediaQueryExpList> maybe_and_media_query_exp_list 312 313 %type <boolean> supports_condition 314 %type <boolean> supports_condition_in_parens 315 %type <boolean> supports_negation 316 %type <boolean> supports_conjunction 317 %type <boolean> supports_disjunction 318 %type <boolean> supports_declaration_condition 319 320 %type <string> keyframe_name 321 %type <keyframe> keyframe_rule 322 %type <keyframeRuleList> keyframes_rule 323 %type <keyframeRuleList> keyframe_rule_list 324 %type <valueList> key_list 325 %type <value> key 326 327 %type <id> property 328 329 %type <selector> specifier 330 %type <selector> specifier_list 331 %type <selector> simple_selector 332 %type <selector> selector 333 %type <selectorList> selector_list 334 %type <selectorList> simple_selector_list 335 %type <selector> class 336 %type <selector> attrib 337 %type <selector> pseudo 338 %type <selector> pseudo_page 339 %type <selector> page_selector 340 341 %type <boolean> declaration_list 342 %type <boolean> decl_list 343 %type <boolean> declaration 344 %type <boolean> declarations_and_margins 345 346 %type <boolean> prio 347 348 %type <integer> match 349 %type <integer> unary_operator 350 %type <integer> maybe_unary_operator 351 %type <character> operator 352 353 %type <valueList> expr 354 %type <value> term 355 %type <value> unary_term 356 %type <value> function 357 %type <value> calc_func_term 358 %type <character> calc_func_operator 359 %type <valueList> calc_func_expr 360 %type <valueList> calc_func_paren_expr 361 %type <value> calc_function 362 363 %type <string> element_name 364 %type <string> attr_name 365 366 %type <location> error_location 367 368 %type <valueList> ident_list 369 %type <value> track_names_list 370 371 %% 372 373 stylesheet: 374 maybe_charset maybe_sgml rule_list 375 | internal_decls 376 | internal_rule 377 | internal_selector 378 | internal_value 379 | internal_medialist 380 | internal_keyframe_rule 381 | internal_keyframe_key_list 382 | internal_supports_condition 383 ; 384 385 internal_rule: 386 INTERNAL_RULE_SYM maybe_space valid_rule maybe_space TOKEN_EOF { 387 parser->m_rule = $3; 388 } 389 ; 390 391 internal_keyframe_rule: 392 INTERNAL_KEYFRAME_RULE_SYM maybe_space keyframe_rule maybe_space TOKEN_EOF { 393 parser->m_keyframe = $3; 394 } 395 ; 396 397 internal_keyframe_key_list: 398 INTERNAL_KEYFRAME_KEY_LIST_SYM maybe_space key_list TOKEN_EOF { 399 parser->m_valueList = parser->sinkFloatingValueList($3); 400 } 401 ; 402 403 internal_decls: 404 INTERNAL_DECLS_SYM maybe_space_before_declaration declaration_list TOKEN_EOF { 405 /* can be empty */ 406 } 407 ; 408 409 internal_value: 410 INTERNAL_VALUE_SYM maybe_space expr TOKEN_EOF { 411 parser->m_valueList = parser->sinkFloatingValueList($3); 412 int oldParsedProperties = parser->m_parsedProperties.size(); 413 if (!parser->parseValue(parser->m_id, parser->m_important)) 414 parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); 415 parser->m_valueList = nullptr; 416 } 417 ; 418 419 internal_medialist: 420 INTERNAL_MEDIALIST_SYM maybe_space location_label maybe_media_list TOKEN_EOF { 421 parser->m_mediaList = $4; 422 } 423 ; 424 425 internal_selector: 426 INTERNAL_SELECTOR_SYM maybe_space selector_list TOKEN_EOF { 427 if (parser->m_selectorListForParseSelector) 428 parser->m_selectorListForParseSelector->adoptSelectorVector(*$3); 429 } 430 ; 431 432 internal_supports_condition: 433 INTERNAL_SUPPORTS_CONDITION_SYM maybe_space supports_condition TOKEN_EOF { 434 parser->m_supportsCondition = $3; 435 } 436 ; 437 438 space: 439 WHITESPACE 440 | space WHITESPACE 441 ; 442 443 maybe_space: 444 /* empty */ %prec UNIMPORTANT_TOK 445 | space 446 ; 447 448 maybe_sgml: 449 /* empty */ 450 | maybe_sgml SGML_CD 451 | maybe_sgml WHITESPACE 452 ; 453 454 closing_brace: 455 '}' 456 | %prec LOWEST_PREC TOKEN_EOF 457 ; 458 459 closing_parenthesis: 460 ')' 461 | %prec LOWEST_PREC TOKEN_EOF 462 ; 463 464 closing_square_bracket: 465 ']' 466 | %prec LOWEST_PREC TOKEN_EOF 467 ; 468 469 semi_or_eof: 470 ';' 471 | TOKEN_EOF 472 ; 473 474 maybe_charset: 475 /* empty */ 476 | CHARSET_SYM maybe_space STRING maybe_space semi_or_eof { 477 if (parser->m_styleSheet) 478 parser->m_styleSheet->parserSetEncodingFromCharsetRule($3); 479 parser->startEndUnknownRule(); 480 } 481 | CHARSET_SYM at_rule_recovery 482 ; 483 484 rule_list: 485 /* empty */ 486 | rule_list rule maybe_sgml { 487 if ($2 && parser->m_styleSheet) 488 parser->m_styleSheet->parserAppendRule($2); 489 } 490 ; 491 492 valid_rule: 493 ruleset 494 | media 495 | page 496 | font_face 497 | keyframes 498 | namespace 499 | import 500 | supports 501 | viewport 502 ; 503 504 before_rule: 505 /* empty */ { 506 parser->startRule(); 507 } 508 ; 509 510 rule: 511 before_rule valid_rule { 512 $$ = $2; 513 parser->m_hadSyntacticallyValidCSSRule = true; 514 parser->endRule(!!$$); 515 } 516 | before_rule invalid_rule { 517 $$ = 0; 518 parser->endRule(false); 519 } 520 ; 521 522 block_rule_body: 523 block_rule_list 524 | block_rule_list block_rule_recovery 525 ; 526 527 block_rule_list: 528 /* empty */ { $$ = 0; } 529 | block_rule_list block_rule maybe_sgml { 530 $$ = parser->appendRule($1, $2); 531 } 532 ; 533 534 block_rule_recovery: 535 before_rule invalid_rule_header { 536 parser->endRule(false); 537 } 538 ; 539 540 block_valid_rule: 541 ruleset 542 | page 543 | font_face 544 | media 545 | keyframes 546 | supports 547 | viewport 548 | namespace 549 ; 550 551 block_rule: 552 before_rule block_valid_rule { 553 $$ = $2; 554 parser->endRule(!!$$); 555 } 556 | before_rule invalid_rule { 557 $$ = 0; 558 parser->endRule(false); 559 } 560 ; 561 562 before_import_rule: 563 /* empty */ { 564 parser->startRuleHeader(CSSRuleSourceData::IMPORT_RULE); 565 } 566 ; 567 568 import_rule_start: 569 before_import_rule IMPORT_SYM maybe_space { 570 parser->endRuleHeader(); 571 parser->startRuleBody(); 572 } 573 ; 574 575 import: 576 import_rule_start string_or_uri maybe_space location_label maybe_media_list semi_or_eof { 577 $$ = parser->createImportRule($2, $5); 578 } 579 | import_rule_start string_or_uri maybe_space location_label maybe_media_list invalid_block { 580 $$ = 0; 581 } 582 ; 583 584 namespace: 585 NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space semi_or_eof { 586 parser->addNamespace($3, $4); 587 $$ = 0; 588 } 589 ; 590 591 maybe_ns_prefix: 592 /* empty */ { $$.clear(); } 593 | IDENT maybe_space 594 ; 595 596 string_or_uri: 597 STRING 598 | URI 599 ; 600 601 maybe_media_value: 602 /*empty*/ { 603 $$ = 0; 604 } 605 | ':' maybe_space expr { 606 $$ = $3; 607 } 608 ; 609 610 media_query_exp: 611 '(' maybe_space IDENT maybe_space maybe_media_value closing_parenthesis { 612 parser->tokenToLowerCase($3); 613 $$ = parser->createFloatingMediaQueryExp($3, $5); 614 if (!$$) 615 YYERROR; 616 } 617 | '(' error error_recovery closing_parenthesis { 618 YYERROR; 619 } 620 ; 621 622 media_query_exp_list: 623 media_query_exp { 624 $$ = parser->createFloatingMediaQueryExpList(); 625 $$->append(parser->sinkFloatingMediaQueryExp($1)); 626 } 627 | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp { 628 $$ = $1; 629 $$->append(parser->sinkFloatingMediaQueryExp($5)); 630 } 631 ; 632 633 maybe_and_media_query_exp_list: 634 maybe_space { 635 $$ = parser->createFloatingMediaQueryExpList(); 636 } 637 | maybe_space MEDIA_AND maybe_space media_query_exp_list maybe_space { 638 $$ = $4; 639 } 640 ; 641 642 maybe_media_restrictor: 643 /*empty*/ { 644 $$ = MediaQuery::None; 645 } 646 | MEDIA_ONLY maybe_space { 647 $$ = MediaQuery::Only; 648 } 649 | MEDIA_NOT maybe_space { 650 $$ = MediaQuery::Not; 651 } 652 ; 653 654 valid_media_query: 655 media_query_exp_list maybe_space { 656 $$ = parser->createFloatingMediaQuery(parser->sinkFloatingMediaQueryExpList($1)); 657 } 658 | maybe_media_restrictor medium maybe_and_media_query_exp_list { 659 parser->tokenToLowerCase($2); 660 $$ = parser->createFloatingMediaQuery($1, $2, parser->sinkFloatingMediaQueryExpList($3)); 661 } 662 ; 663 664 media_query: 665 valid_media_query 666 | valid_media_query error error_location rule_error_recovery { 667 parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError); 668 $$ = parser->createFloatingNotAllQuery(); 669 } 670 | error error_location rule_error_recovery { 671 parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError); 672 $$ = parser->createFloatingNotAllQuery(); 673 } 674 ; 675 676 maybe_media_list: 677 /* empty */ { 678 $$ = parser->createMediaQuerySet(); 679 } 680 | media_list 681 ; 682 683 media_list: 684 media_query { 685 $$ = parser->createMediaQuerySet(); 686 $$->addMediaQuery(parser->sinkFloatingMediaQuery($1)); 687 } 688 | mq_list media_query { 689 $$ = $1; 690 $$->addMediaQuery(parser->sinkFloatingMediaQuery($2)); 691 } 692 | mq_list { 693 $$ = $1; 694 $$->addMediaQuery(parser->sinkFloatingMediaQuery(parser->createFloatingNotAllQuery())); 695 } 696 ; 697 698 mq_list: 699 media_query ',' maybe_space location_label { 700 $$ = parser->createMediaQuerySet(); 701 $$->addMediaQuery(parser->sinkFloatingMediaQuery($1)); 702 } 703 | mq_list media_query ',' maybe_space location_label { 704 $$ = $1; 705 $$->addMediaQuery(parser->sinkFloatingMediaQuery($2)); 706 } 707 ; 708 709 at_rule_body_start: 710 /* empty */ { 711 parser->startRuleBody(); 712 } 713 ; 714 715 before_media_rule: 716 /* empty */ { 717 parser->startRuleHeader(CSSRuleSourceData::MEDIA_RULE); 718 } 719 ; 720 721 at_rule_header_end_maybe_space: 722 maybe_space { 723 parser->endRuleHeader(); 724 } 725 ; 726 727 media_rule_start: 728 before_media_rule MEDIA_SYM maybe_space; 729 730 media: 731 media_rule_start maybe_media_list at_rule_header_end '{' at_rule_body_start maybe_space block_rule_body closing_brace { 732 $$ = parser->createMediaRule($2, $7); 733 } 734 ; 735 736 medium: 737 IDENT 738 ; 739 740 supports: 741 before_supports_rule SUPPORTS_SYM maybe_space supports_condition at_supports_rule_header_end '{' at_rule_body_start maybe_space block_rule_body closing_brace { 742 $$ = parser->createSupportsRule($4, $9); 743 } 744 ; 745 746 before_supports_rule: 747 /* empty */ { 748 parser->startRuleHeader(CSSRuleSourceData::SUPPORTS_RULE); 749 parser->markSupportsRuleHeaderStart(); 750 } 751 ; 752 753 at_supports_rule_header_end: 754 /* empty */ { 755 parser->endRuleHeader(); 756 parser->markSupportsRuleHeaderEnd(); 757 } 758 ; 759 760 supports_condition: 761 supports_condition_in_parens 762 | supports_negation 763 | supports_conjunction 764 | supports_disjunction 765 ; 766 767 supports_negation: 768 SUPPORTS_NOT maybe_space supports_condition_in_parens { 769 $$ = !$3; 770 } 771 ; 772 773 supports_conjunction: 774 supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens { 775 $$ = $1 && $4; 776 } 777 | supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens { 778 $$ = $1 && $4; 779 } 780 ; 781 782 supports_disjunction: 783 supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens { 784 $$ = $1 || $4; 785 } 786 | supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens { 787 $$ = $1 || $4; 788 } 789 ; 790 791 supports_condition_in_parens: 792 '(' maybe_space supports_condition closing_parenthesis maybe_space { 793 $$ = $3; 794 } 795 | supports_declaration_condition 796 | '(' error error_location error_recovery closing_parenthesis maybe_space { 797 parser->reportError($3, InvalidSupportsConditionCSSError); 798 $$ = false; 799 } 800 ; 801 802 supports_declaration_condition: 803 '(' maybe_space IDENT maybe_space ':' maybe_space expr prio closing_parenthesis maybe_space { 804 $$ = false; 805 CSSPropertyID id = cssPropertyID($3); 806 if (id != CSSPropertyInvalid) { 807 parser->m_valueList = parser->sinkFloatingValueList($7); 808 int oldParsedProperties = parser->m_parsedProperties.size(); 809 $$ = parser->parseValue(id, $8); 810 // We just need to know if the declaration is supported as it is written. Rollback any additions. 811 if ($$) 812 parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); 813 } 814 parser->m_valueList = nullptr; 815 parser->endProperty($8, false); 816 } 817 | '(' maybe_space IDENT maybe_space ':' maybe_space error error_recovery closing_parenthesis maybe_space { 818 $$ = false; 819 parser->endProperty(false, false, GeneralCSSError); 820 } 821 ; 822 823 before_keyframes_rule: 824 /* empty */ { 825 parser->startRuleHeader(CSSRuleSourceData::KEYFRAMES_RULE); 826 } 827 ; 828 829 keyframes_rule_start: 830 before_keyframes_rule KEYFRAMES_SYM maybe_space { 831 $$ = false; 832 } 833 | before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space { 834 $$ = true; 835 } 836 ; 837 838 keyframes: 839 keyframes_rule_start keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space location_label keyframes_rule closing_brace { 840 $$ = parser->createKeyframesRule($2, parser->sinkFloatingKeyframeVector($8), $1 /* isPrefixed */); 841 } 842 ; 843 844 keyframe_name: 845 IDENT 846 | STRING 847 ; 848 849 keyframes_rule: 850 keyframe_rule_list 851 | keyframe_rule_list keyframes_error_recovery { 852 parser->clearProperties(); 853 }; 854 855 keyframe_rule_list: 856 /* empty */ { 857 $$ = parser->createFloatingKeyframeVector(); 858 parser->resumeErrorLogging(); 859 } 860 | keyframe_rule_list keyframe_rule maybe_space location_label { 861 $$ = $1; 862 $$->append($2); 863 } 864 | keyframe_rule_list keyframes_error_recovery invalid_block maybe_space location_label { 865 parser->clearProperties(); 866 parser->resumeErrorLogging(); 867 } 868 ; 869 870 keyframe_rule: 871 key_list '{' maybe_space declaration_list closing_brace { 872 $$ = parser->createKeyframe($1); 873 } 874 ; 875 876 key_list: 877 key maybe_space { 878 $$ = parser->createFloatingValueList(); 879 $$->addValue(parser->sinkFloatingValue($1)); 880 } 881 | key_list ',' maybe_space key maybe_space { 882 $$ = $1; 883 $$->addValue(parser->sinkFloatingValue($4)); 884 } 885 ; 886 887 key: 888 maybe_unary_operator PERCENTAGE { 889 $$.setFromNumber($1 * $2); 890 } 891 | IDENT { 892 if ($1.equalIgnoringCase("from")) 893 $$.setFromNumber(0); 894 else if ($1.equalIgnoringCase("to")) 895 $$.setFromNumber(100); 896 else { 897 YYERROR; 898 } 899 } 900 ; 901 902 keyframes_error_recovery: 903 error rule_error_recovery { 904 parser->reportError(parser->lastLocationLabel(), InvalidKeyframeSelectorCSSError); 905 } 906 ; 907 908 before_page_rule: 909 /* empty */ { 910 parser->startRuleHeader(CSSRuleSourceData::PAGE_RULE); 911 } 912 ; 913 914 page: 915 before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end 916 '{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace { 917 if ($4) 918 $$ = parser->createPageRule(parser->sinkFloatingSelector($4)); 919 else { 920 // Clear properties in the invalid @page rule. 921 parser->clearProperties(); 922 // Also clear margin at-rules here once we fully implement margin at-rules parsing. 923 $$ = 0; 924 } 925 } 926 ; 927 928 page_selector: 929 IDENT maybe_space { 930 $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 931 $$->setForPage(); 932 } 933 | IDENT pseudo_page maybe_space { 934 $$ = $2; 935 $$->prependTagSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 936 $$->setForPage(); 937 } 938 | pseudo_page maybe_space { 939 $$ = $1; 940 $$->setForPage(); 941 } 942 | /* empty */ { 943 $$ = parser->createFloatingSelector(); 944 $$->setForPage(); 945 } 946 ; 947 948 declarations_and_margins: 949 declaration_list 950 | declarations_and_margins margin_box maybe_space declaration_list 951 ; 952 953 margin_box: 954 margin_sym { 955 parser->startDeclarationsForMarginBox(); 956 } maybe_space '{' maybe_space declaration_list closing_brace { 957 $$ = parser->createMarginAtRule($1); 958 } 959 ; 960 961 margin_sym : 962 TOPLEFTCORNER_SYM { 963 $$ = CSSSelector::TopLeftCornerMarginBox; 964 } 965 | TOPLEFT_SYM { 966 $$ = CSSSelector::TopLeftMarginBox; 967 } 968 | TOPCENTER_SYM { 969 $$ = CSSSelector::TopCenterMarginBox; 970 } 971 | TOPRIGHT_SYM { 972 $$ = CSSSelector::TopRightMarginBox; 973 } 974 | TOPRIGHTCORNER_SYM { 975 $$ = CSSSelector::TopRightCornerMarginBox; 976 } 977 | BOTTOMLEFTCORNER_SYM { 978 $$ = CSSSelector::BottomLeftCornerMarginBox; 979 } 980 | BOTTOMLEFT_SYM { 981 $$ = CSSSelector::BottomLeftMarginBox; 982 } 983 | BOTTOMCENTER_SYM { 984 $$ = CSSSelector::BottomCenterMarginBox; 985 } 986 | BOTTOMRIGHT_SYM { 987 $$ = CSSSelector::BottomRightMarginBox; 988 } 989 | BOTTOMRIGHTCORNER_SYM { 990 $$ = CSSSelector::BottomRightCornerMarginBox; 991 } 992 | LEFTTOP_SYM { 993 $$ = CSSSelector::LeftTopMarginBox; 994 } 995 | LEFTMIDDLE_SYM { 996 $$ = CSSSelector::LeftMiddleMarginBox; 997 } 998 | LEFTBOTTOM_SYM { 999 $$ = CSSSelector::LeftBottomMarginBox; 1000 } 1001 | RIGHTTOP_SYM { 1002 $$ = CSSSelector::RightTopMarginBox; 1003 } 1004 | RIGHTMIDDLE_SYM { 1005 $$ = CSSSelector::RightMiddleMarginBox; 1006 } 1007 | RIGHTBOTTOM_SYM { 1008 $$ = CSSSelector::RightBottomMarginBox; 1009 } 1010 ; 1011 1012 before_font_face_rule: 1013 /* empty */ { 1014 parser->startRuleHeader(CSSRuleSourceData::FONT_FACE_RULE); 1015 } 1016 ; 1017 1018 font_face: 1019 before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space 1020 '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { 1021 $$ = parser->createFontFaceRule(); 1022 } 1023 ; 1024 1025 before_viewport_rule: 1026 /* empty */ { 1027 parser->markViewportRuleBodyStart(); 1028 parser->startRuleHeader(CSSRuleSourceData::VIEWPORT_RULE); 1029 } 1030 ; 1031 1032 viewport: 1033 before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_end_maybe_space 1034 '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { 1035 $$ = parser->createViewportRule(); 1036 parser->markViewportRuleBodyEnd(); 1037 } 1038 ; 1039 1040 combinator: 1041 '+' maybe_space { $$ = CSSSelector::DirectAdjacent; } 1042 | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; } 1043 | '>' maybe_space { $$ = CSSSelector::Child; } 1044 | '/' IDENT '/' maybe_space { 1045 if ($2.equalIgnoringCase("deep")) 1046 $$ = CSSSelector::ShadowDeep; 1047 else 1048 YYERROR; 1049 } 1050 ; 1051 1052 maybe_unary_operator: 1053 unary_operator 1054 | /* empty */ { $$ = 1; } 1055 ; 1056 1057 unary_operator: 1058 '-' { $$ = -1; } 1059 | '+' { $$ = 1; } 1060 ; 1061 1062 maybe_space_before_declaration: 1063 maybe_space { 1064 parser->startProperty(); 1065 } 1066 ; 1067 1068 before_selector_list: 1069 /* empty */ { 1070 parser->startRuleHeader(CSSRuleSourceData::STYLE_RULE); 1071 parser->startSelector(); 1072 } 1073 ; 1074 1075 at_rule_header_end: 1076 /* empty */ { 1077 parser->endRuleHeader(); 1078 } 1079 ; 1080 1081 at_selector_end: 1082 /* empty */ { 1083 parser->endSelector(); 1084 } 1085 ; 1086 1087 ruleset: 1088 before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { 1089 $$ = parser->createStyleRule($2); 1090 } 1091 ; 1092 1093 before_selector_group_item: 1094 /* empty */ { 1095 parser->startSelector(); 1096 } 1097 1098 selector_list: 1099 selector %prec UNIMPORTANT_TOK { 1100 $$ = parser->reusableSelectorVector(); 1101 $$->shrink(0); 1102 $$->append(parser->sinkFloatingSelector($1)); 1103 } 1104 | selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK { 1105 $$ = $1; 1106 $$->append(parser->sinkFloatingSelector($6)); 1107 } 1108 ; 1109 1110 selector: 1111 simple_selector 1112 | selector WHITESPACE 1113 | selector WHITESPACE simple_selector 1114 { 1115 $$ = $3; 1116 CSSParserSelector* end = $$; 1117 while (end->tagHistory()) 1118 end = end->tagHistory(); 1119 end->setRelation(CSSSelector::Descendant); 1120 if ($1->isContentPseudoElement()) 1121 end->setRelationIsAffectedByPseudoContent(); 1122 end->setTagHistory(parser->sinkFloatingSelector($1)); 1123 } 1124 | selector combinator simple_selector { 1125 $$ = $3; 1126 CSSParserSelector* end = $$; 1127 while (end->tagHistory()) 1128 end = end->tagHistory(); 1129 end->setRelation($2); 1130 if ($1->isContentPseudoElement()) 1131 end->setRelationIsAffectedByPseudoContent(); 1132 end->setTagHistory(parser->sinkFloatingSelector($1)); 1133 } 1134 ; 1135 1136 namespace_selector: 1137 /* empty */ '|' { $$.clear(); } 1138 | '*' '|' { static const LChar star = '*'; $$.init(&star, 1); } 1139 | IDENT '|' 1140 ; 1141 1142 simple_selector: 1143 element_name { 1144 $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 1145 } 1146 | element_name specifier_list { 1147 $$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $2); 1148 if (!$$) 1149 YYERROR; 1150 } 1151 | specifier_list { 1152 $$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($1); 1153 if (!$$) 1154 YYERROR; 1155 } 1156 | namespace_selector element_name { 1157 $$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2)); 1158 if (!$$) 1159 YYERROR; 1160 } 1161 | namespace_selector element_name specifier_list { 1162 $$ = parser->rewriteSpecifiersWithElementName($1, $2, $3); 1163 if (!$$) 1164 YYERROR; 1165 } 1166 | namespace_selector specifier_list { 1167 $$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $2); 1168 if (!$$) 1169 YYERROR; 1170 } 1171 ; 1172 1173 simple_selector_list: 1174 simple_selector %prec UNIMPORTANT_TOK { 1175 $$ = parser->createFloatingSelectorVector(); 1176 $$->append(parser->sinkFloatingSelector($1)); 1177 } 1178 | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK { 1179 $$ = $1; 1180 $$->append(parser->sinkFloatingSelector($5)); 1181 } 1182 ; 1183 1184 element_name: 1185 IDENT { 1186 if (parser->m_context.isHTMLDocument()) 1187 parser->tokenToLowerCase($1); 1188 $$ = $1; 1189 } 1190 | '*' { 1191 static const LChar star = '*'; 1192 $$.init(&star, 1); 1193 } 1194 ; 1195 1196 specifier_list: 1197 specifier 1198 | specifier_list specifier { 1199 $$ = parser->rewriteSpecifiers($1, $2); 1200 } 1201 ; 1202 1203 specifier: 1204 IDSEL { 1205 $$ = parser->createFloatingSelector(); 1206 $$->setMatch(CSSSelector::Id); 1207 if (isQuirksModeBehavior(parser->m_context.mode())) 1208 parser->tokenToLowerCase($1); 1209 $$->setValue($1); 1210 } 1211 | HEX { 1212 if ($1[0] >= '0' && $1[0] <= '9') { 1213 YYERROR; 1214 } else { 1215 $$ = parser->createFloatingSelector(); 1216 $$->setMatch(CSSSelector::Id); 1217 if (isQuirksModeBehavior(parser->m_context.mode())) 1218 parser->tokenToLowerCase($1); 1219 $$->setValue($1); 1220 } 1221 } 1222 | class 1223 | attrib 1224 | pseudo 1225 ; 1226 1227 class: 1228 '.' IDENT { 1229 $$ = parser->createFloatingSelector(); 1230 $$->setMatch(CSSSelector::Class); 1231 if (isQuirksModeBehavior(parser->m_context.mode())) 1232 parser->tokenToLowerCase($2); 1233 $$->setValue($2); 1234 } 1235 ; 1236 1237 attr_name: 1238 IDENT maybe_space { 1239 if (parser->m_context.isHTMLDocument()) 1240 parser->tokenToLowerCase($1); 1241 $$ = $1; 1242 } 1243 ; 1244 1245 attrib: 1246 '[' maybe_space attr_name closing_square_bracket { 1247 $$ = parser->createFloatingSelector(); 1248 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom)); 1249 $$->setMatch(CSSSelector::Set); 1250 } 1251 | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space closing_square_bracket { 1252 $$ = parser->createFloatingSelector(); 1253 $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom)); 1254 $$->setMatch((CSSSelector::Match)$4); 1255 $$->setValue($6); 1256 } 1257 | '[' maybe_space namespace_selector attr_name closing_square_bracket { 1258 $$ = parser->createFloatingSelector(); 1259 $$->setAttribute(parser->determineNameInNamespace($3, $4)); 1260 $$->setMatch(CSSSelector::Set); 1261 } 1262 | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space closing_square_bracket { 1263 $$ = parser->createFloatingSelector(); 1264 $$->setAttribute(parser->determineNameInNamespace($3, $4)); 1265 $$->setMatch((CSSSelector::Match)$5); 1266 $$->setValue($7); 1267 } 1268 | '[' selector_recovery closing_square_bracket { 1269 YYERROR; 1270 } 1271 ; 1272 1273 match: 1274 '=' { 1275 $$ = CSSSelector::Exact; 1276 } 1277 | INCLUDES { 1278 $$ = CSSSelector::List; 1279 } 1280 | DASHMATCH { 1281 $$ = CSSSelector::Hyphen; 1282 } 1283 | BEGINSWITH { 1284 $$ = CSSSelector::Begin; 1285 } 1286 | ENDSWITH { 1287 $$ = CSSSelector::End; 1288 } 1289 | CONTAINS { 1290 $$ = CSSSelector::Contain; 1291 } 1292 ; 1293 1294 ident_or_string: 1295 IDENT 1296 | STRING 1297 ; 1298 1299 pseudo_page: 1300 ':' IDENT { 1301 if ($2.isFunction()) 1302 YYERROR; 1303 $$ = parser->createFloatingSelector(); 1304 $$->setMatch(CSSSelector::PagePseudoClass); 1305 parser->tokenToLowerCase($2); 1306 $$->setValue($2); 1307 CSSSelector::PseudoType type = $$->pseudoType(); 1308 if (type == CSSSelector::PseudoUnknown) 1309 YYERROR; 1310 } 1311 1312 pseudo: 1313 ':' error_location IDENT { 1314 if ($3.isFunction()) 1315 YYERROR; 1316 $$ = parser->createFloatingSelector(); 1317 $$->setMatch(CSSSelector::PseudoClass); 1318 parser->tokenToLowerCase($3); 1319 $$->setValue($3); 1320 CSSSelector::PseudoType type = $$->pseudoType(); 1321 if (type == CSSSelector::PseudoUnknown) { 1322 parser->reportError($2, InvalidSelectorPseudoCSSError); 1323 YYERROR; 1324 } 1325 } 1326 | ':' ':' error_location IDENT { 1327 if ($4.isFunction()) 1328 YYERROR; 1329 $$ = parser->createFloatingSelector(); 1330 $$->setMatch(CSSSelector::PseudoElement); 1331 parser->tokenToLowerCase($4); 1332 $$->setValue($4); 1333 // FIXME: This call is needed to force selector to compute the pseudoType early enough. 1334 CSSSelector::PseudoType type = $$->pseudoType(); 1335 if (type == CSSSelector::PseudoUnknown) { 1336 parser->reportError($3, InvalidSelectorPseudoCSSError); 1337 YYERROR; 1338 } 1339 } 1340 // used by ::cue(:past/:future) 1341 | ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis { 1342 $$ = parser->createFloatingSelector(); 1343 $$->setMatch(CSSSelector::PseudoElement); 1344 $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($5)); 1345 $$->setValue($3); 1346 CSSSelector::PseudoType type = $$->pseudoType(); 1347 if (type != CSSSelector::PseudoCue) 1348 YYERROR; 1349 } 1350 | ':' ':' CUEFUNCTION selector_recovery closing_parenthesis { 1351 YYERROR; 1352 } 1353 // use by :-webkit-any. 1354 // FIXME: should we support generic selectors here or just simple_selectors? 1355 // Use simple_selector_list for now to match -moz-any. 1356 // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some 1357 // related discussion with respect to :not. 1358 | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis { 1359 $$ = parser->createFloatingSelector(); 1360 $$->setMatch(CSSSelector::PseudoClass); 1361 $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4)); 1362 parser->tokenToLowerCase($2); 1363 $$->setValue($2); 1364 CSSSelector::PseudoType type = $$->pseudoType(); 1365 if (type != CSSSelector::PseudoAny) 1366 YYERROR; 1367 } 1368 | ':' ANYFUNCTION selector_recovery closing_parenthesis { 1369 YYERROR; 1370 } 1371 // used by :nth-*(ax+b) 1372 | ':' FUNCTION maybe_space NTH maybe_space closing_parenthesis { 1373 $$ = parser->createFloatingSelector(); 1374 $$->setMatch(CSSSelector::PseudoClass); 1375 $$->setArgument($4); 1376 $$->setValue($2); 1377 CSSSelector::PseudoType type = $$->pseudoType(); 1378 if (type == CSSSelector::PseudoUnknown) 1379 YYERROR; 1380 } 1381 // used by :nth-* 1382 | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space closing_parenthesis { 1383 $$ = parser->createFloatingSelector(); 1384 $$->setMatch(CSSSelector::PseudoClass); 1385 $$->setArgument(AtomicString::number($4 * $5)); 1386 $$->setValue($2); 1387 CSSSelector::PseudoType type = $$->pseudoType(); 1388 if (type == CSSSelector::PseudoUnknown) 1389 YYERROR; 1390 } 1391 // used by :nth-*(odd/even) and :lang 1392 | ':' FUNCTION maybe_space IDENT maybe_space closing_parenthesis { 1393 $$ = parser->createFloatingSelector(); 1394 $$->setMatch(CSSSelector::PseudoClass); 1395 $$->setArgument($4); 1396 parser->tokenToLowerCase($2); 1397 $$->setValue($2); 1398 CSSSelector::PseudoType type = $$->pseudoType(); 1399 if (type == CSSSelector::PseudoUnknown) 1400 YYERROR; 1401 else if (type == CSSSelector::PseudoNthChild || 1402 type == CSSSelector::PseudoNthOfType || 1403 type == CSSSelector::PseudoNthLastChild || 1404 type == CSSSelector::PseudoNthLastOfType) { 1405 if (!isValidNthToken($4)) 1406 YYERROR; 1407 } 1408 } 1409 | ':' FUNCTION selector_recovery closing_parenthesis { 1410 YYERROR; 1411 } 1412 // used by :not 1413 | ':' NOTFUNCTION maybe_space simple_selector maybe_space closing_parenthesis { 1414 if (!$4->isSimple()) 1415 YYERROR; 1416 else { 1417 $$ = parser->createFloatingSelector(); 1418 $$->setMatch(CSSSelector::PseudoClass); 1419 1420 Vector<OwnPtr<CSSParserSelector> > selectorVector; 1421 selectorVector.append(parser->sinkFloatingSelector($4)); 1422 $$->adoptSelectorVector(selectorVector); 1423 1424 parser->tokenToLowerCase($2); 1425 $$->setValue($2); 1426 } 1427 } 1428 | ':' NOTFUNCTION selector_recovery closing_parenthesis { 1429 YYERROR; 1430 } 1431 | ':' HOSTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis { 1432 $$ = parser->createFloatingSelector(); 1433 $$->setMatch(CSSSelector::PseudoClass); 1434 $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4)); 1435 parser->tokenToLowerCase($2); 1436 $$->setValue($2); 1437 CSSSelector::PseudoType type = $$->pseudoType(); 1438 if (type != CSSSelector::PseudoHost) 1439 YYERROR; 1440 } 1441 | ':' HOSTFUNCTION selector_recovery closing_parenthesis { 1442 YYERROR; 1443 } 1444 // used by :host-context() 1445 | ':' HOSTCONTEXTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis { 1446 $$ = parser->createFloatingSelector(); 1447 $$->setMatch(CSSSelector::PseudoClass); 1448 $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4)); 1449 parser->tokenToLowerCase($2); 1450 $$->setValue($2); 1451 CSSSelector::PseudoType type = $$->pseudoType(); 1452 if (type != CSSSelector::PseudoHostContext) 1453 YYERROR; 1454 } 1455 | ':' HOSTCONTEXTFUNCTION selector_recovery closing_parenthesis { 1456 YYERROR; 1457 } 1458 ; 1459 1460 selector_recovery: 1461 error error_location error_recovery; 1462 1463 declaration_list: 1464 /* empty */ { $$ = false; } 1465 | declaration 1466 | decl_list declaration { 1467 $$ = $1 || $2; 1468 } 1469 | decl_list 1470 ; 1471 1472 decl_list: 1473 declaration ';' maybe_space { 1474 parser->startProperty(); 1475 $$ = $1; 1476 } 1477 | decl_list declaration ';' maybe_space { 1478 parser->startProperty(); 1479 $$ = $1 || $2; 1480 } 1481 ; 1482 1483 declaration: 1484 property ':' maybe_space error_location expr prio { 1485 $$ = false; 1486 bool isPropertyParsed = false; 1487 if ($1 != CSSPropertyInvalid) { 1488 parser->m_valueList = parser->sinkFloatingValueList($5); 1489 int oldParsedProperties = parser->m_parsedProperties.size(); 1490 $$ = parser->parseValue($1, $6); 1491 if (!$$) { 1492 parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); 1493 parser->reportError($4, InvalidPropertyValueCSSError); 1494 } else 1495 isPropertyParsed = true; 1496 parser->m_valueList = nullptr; 1497 } 1498 parser->endProperty($6, isPropertyParsed); 1499 } 1500 | 1501 property ':' maybe_space error_location expr prio error error_recovery { 1502 /* When we encounter something like p {color: red !important fail;} we should drop the declaration */ 1503 parser->reportError($4, InvalidPropertyValueCSSError); 1504 parser->endProperty(false, false); 1505 $$ = false; 1506 } 1507 | 1508 property ':' maybe_space error_location error error_recovery { 1509 parser->reportError($4, InvalidPropertyValueCSSError); 1510 parser->endProperty(false, false); 1511 $$ = false; 1512 } 1513 | 1514 property error error_location error_recovery { 1515 parser->reportError($3, PropertyDeclarationCSSError); 1516 parser->endProperty(false, false, GeneralCSSError); 1517 $$ = false; 1518 } 1519 | 1520 error error_location error_recovery { 1521 parser->reportError($2, PropertyDeclarationCSSError); 1522 $$ = false; 1523 } 1524 ; 1525 1526 property: 1527 error_location IDENT maybe_space { 1528 $$ = cssPropertyID($2); 1529 parser->setCurrentProperty($$); 1530 if ($$ == CSSPropertyInvalid) 1531 parser->reportError($1, InvalidPropertyCSSError); 1532 } 1533 ; 1534 1535 prio: 1536 IMPORTANT_SYM maybe_space { $$ = true; } 1537 | /* empty */ { $$ = false; } 1538 ; 1539 1540 ident_list: 1541 IDENT maybe_space { 1542 $$ = parser->createFloatingValueList(); 1543 $$->addValue(makeIdentValue($1)); 1544 } 1545 | ident_list IDENT maybe_space { 1546 $$ = $1; 1547 $$->addValue(makeIdentValue($2)); 1548 } 1549 ; 1550 1551 track_names_list: 1552 '(' maybe_space closing_parenthesis { 1553 $$.setFromValueList(parser->sinkFloatingValueList(parser->createFloatingValueList())); 1554 } 1555 | '(' maybe_space ident_list closing_parenthesis { 1556 $$.setFromValueList(parser->sinkFloatingValueList($3)); 1557 } 1558 | '(' maybe_space expr_recovery closing_parenthesis { 1559 YYERROR; 1560 } 1561 ; 1562 1563 expr: 1564 term { 1565 $$ = parser->createFloatingValueList(); 1566 $$->addValue(parser->sinkFloatingValue($1)); 1567 } 1568 | expr operator term { 1569 $$ = $1; 1570 $$->addValue(makeOperatorValue($2)); 1571 $$->addValue(parser->sinkFloatingValue($3)); 1572 } 1573 | expr term { 1574 $$ = $1; 1575 $$->addValue(parser->sinkFloatingValue($2)); 1576 } 1577 ; 1578 1579 expr_recovery: 1580 error error_location error_recovery { 1581 parser->reportError($2, PropertyDeclarationCSSError); 1582 } 1583 ; 1584 1585 operator: 1586 '/' maybe_space { 1587 $$ = '/'; 1588 } 1589 | ',' maybe_space { 1590 $$ = ','; 1591 } 1592 ; 1593 1594 term: 1595 unary_term maybe_space 1596 | unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; } 1597 | STRING maybe_space { $$.id = CSSValueInvalid; $$.isInt = false; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } 1598 | IDENT maybe_space { $$ = makeIdentValue($1); } 1599 /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */ 1600 | DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } 1601 | unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } 1602 | URI maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_URI; } 1603 | UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } 1604 | HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } 1605 | '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */ 1606 /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ 1607 | function maybe_space 1608 | calc_function maybe_space 1609 | '%' maybe_space { /* Handle width: %; */ 1610 $$.id = CSSValueInvalid; $$.isInt = false; $$.unit = 0; 1611 } 1612 | track_names_list maybe_space 1613 ; 1614 1615 unary_term: 1616 INTEGER { $$.setFromNumber($1); $$.isInt = true; } 1617 | FLOATTOKEN { $$.setFromNumber($1); } 1618 | PERCENTAGE { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PERCENTAGE); } 1619 | PXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PX); } 1620 | CMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CM); } 1621 | MMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MM); } 1622 | INS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_IN); } 1623 | PTS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PT); } 1624 | PCS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_PC); } 1625 | DEGS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DEG); } 1626 | RADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_RAD); } 1627 | GRADS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_GRAD); } 1628 | TURNS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_TURN); } 1629 | MSECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_MS); } 1630 | SECS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_S); } 1631 | HERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_HZ); } 1632 | KHERTZ { $$.setFromNumber($1, CSSPrimitiveValue::CSS_KHZ); } 1633 | EMS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EMS); } 1634 | QEMS { $$.setFromNumber($1, CSSParserValue::Q_EMS); } 1635 | EXS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_EXS); } 1636 | REMS { 1637 $$.setFromNumber($1, CSSPrimitiveValue::CSS_REMS); 1638 if (parser->m_styleSheet) 1639 parser->m_styleSheet->parserSetUsesRemUnits(true); 1640 } 1641 | CHS { $$.setFromNumber($1, CSSPrimitiveValue::CSS_CHS); } 1642 | VW { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VW); } 1643 | VH { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VH); } 1644 | VMIN { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMIN); } 1645 | VMAX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_VMAX); } 1646 | DPPX { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPPX); } 1647 | DPI { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPI); } 1648 | DPCM { $$.setFromNumber($1, CSSPrimitiveValue::CSS_DPCM); } 1649 | FR { $$.setFromNumber($1, CSSPrimitiveValue::CSS_FR); } 1650 ; 1651 1652 function: 1653 FUNCTION maybe_space expr closing_parenthesis { 1654 $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3))); 1655 } | 1656 FUNCTION maybe_space closing_parenthesis { 1657 $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList(parser->createFloatingValueList()))); 1658 } | 1659 FUNCTION maybe_space expr_recovery closing_parenthesis { 1660 YYERROR; 1661 } 1662 ; 1663 1664 calc_func_term: 1665 unary_term 1666 | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } 1667 ; 1668 1669 calc_func_operator: 1670 space '+' space { 1671 $$ = '+'; 1672 } 1673 | space '-' space { 1674 $$ = '-'; 1675 } 1676 | calc_maybe_space '*' maybe_space { 1677 $$ = '*'; 1678 } 1679 | calc_maybe_space '/' maybe_space { 1680 $$ = '/'; 1681 } 1682 ; 1683 1684 calc_maybe_space: 1685 /* empty */ 1686 | WHITESPACE 1687 ; 1688 1689 calc_func_paren_expr: 1690 '(' maybe_space calc_func_expr calc_maybe_space closing_parenthesis { 1691 $$ = $3; 1692 $$->insertValueAt(0, makeOperatorValue('(')); 1693 $$->addValue(makeOperatorValue(')')); 1694 } 1695 | '(' maybe_space expr_recovery closing_parenthesis { 1696 YYERROR; 1697 } 1698 ; 1699 1700 calc_func_expr: 1701 calc_func_term { 1702 $$ = parser->createFloatingValueList(); 1703 $$->addValue(parser->sinkFloatingValue($1)); 1704 } 1705 | calc_func_expr calc_func_operator calc_func_term { 1706 $$ = $1; 1707 $$->addValue(makeOperatorValue($2)); 1708 $$->addValue(parser->sinkFloatingValue($3)); 1709 } 1710 | calc_func_expr calc_func_operator calc_func_paren_expr { 1711 $$ = $1; 1712 $$->addValue(makeOperatorValue($2)); 1713 $$->stealValues(*($3)); 1714 } 1715 | calc_func_paren_expr 1716 ; 1717 1718 calc_function: 1719 CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis { 1720 $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3))); 1721 } 1722 | CALCFUNCTION maybe_space expr_recovery closing_parenthesis { 1723 YYERROR; 1724 } 1725 ; 1726 1727 1728 invalid_at: 1729 ATKEYWORD 1730 | margin_sym 1731 ; 1732 1733 at_rule_recovery: 1734 at_rule_header_recovery at_invalid_rule_header_end at_rule_end 1735 ; 1736 1737 at_rule_header_recovery: 1738 error error_location rule_error_recovery { 1739 parser->reportError($2, InvalidRuleCSSError); 1740 } 1741 ; 1742 1743 at_rule_end: 1744 at_invalid_rule_header_end semi_or_eof 1745 | at_invalid_rule_header_end invalid_block 1746 ; 1747 1748 regular_invalid_at_rule_header: 1749 keyframes_rule_start at_rule_header_recovery 1750 | before_page_rule PAGE_SYM at_rule_header_recovery 1751 | before_font_face_rule FONT_FACE_SYM at_rule_header_recovery 1752 | before_supports_rule SUPPORTS_SYM error error_location rule_error_recovery { 1753 parser->reportError($4, InvalidSupportsConditionCSSError); 1754 parser->popSupportsRuleData(); 1755 } 1756 | before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_recovery { 1757 parser->markViewportRuleBodyEnd(); 1758 } 1759 | import_rule_start at_rule_header_recovery 1760 | NAMESPACE_SYM at_rule_header_recovery 1761 | error_location invalid_at at_rule_header_recovery { 1762 parser->resumeErrorLogging(); 1763 parser->reportError($1, InvalidRuleCSSError); 1764 } 1765 ; 1766 1767 invalid_rule: 1768 error error_location rule_error_recovery at_invalid_rule_header_end invalid_block { 1769 parser->reportError($2, InvalidRuleCSSError); 1770 } 1771 | regular_invalid_at_rule_header at_invalid_rule_header_end ';' 1772 | regular_invalid_at_rule_header at_invalid_rule_header_end invalid_block 1773 | media_rule_start maybe_media_list ';' 1774 ; 1775 1776 invalid_rule_header: 1777 error error_location rule_error_recovery at_invalid_rule_header_end { 1778 parser->reportError($2, InvalidRuleCSSError); 1779 } 1780 | regular_invalid_at_rule_header at_invalid_rule_header_end 1781 | media_rule_start maybe_media_list 1782 ; 1783 1784 at_invalid_rule_header_end: 1785 /* empty */ { 1786 parser->endInvalidRuleHeader(); 1787 } 1788 ; 1789 1790 invalid_block: 1791 '{' error_recovery closing_brace { 1792 parser->invalidBlockHit(); 1793 } 1794 ; 1795 1796 invalid_square_brackets_block: 1797 '[' error_recovery closing_square_bracket 1798 ; 1799 1800 invalid_parentheses_block: 1801 opening_parenthesis error_recovery closing_parenthesis; 1802 1803 opening_parenthesis: 1804 '(' | FUNCTION | CALCFUNCTION | ANYFUNCTION | NOTFUNCTION | CUEFUNCTION | DISTRIBUTEDFUNCTION | HOSTFUNCTION 1805 ; 1806 1807 error_location: { 1808 $$ = parser->currentLocation(); 1809 } 1810 ; 1811 1812 location_label: { 1813 parser->setLocationLabel(parser->currentLocation()); 1814 } 1815 ; 1816 1817 error_recovery: 1818 /* empty */ 1819 | error_recovery error 1820 | error_recovery invalid_block 1821 | error_recovery invalid_square_brackets_block 1822 | error_recovery invalid_parentheses_block 1823 ; 1824 1825 rule_error_recovery: 1826 /* empty */ 1827 | rule_error_recovery error 1828 | rule_error_recovery invalid_square_brackets_block 1829 | rule_error_recovery invalid_parentheses_block 1830 ; 1831 1832 %% 1833