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