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