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