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