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