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