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