diff options
Diffstat (limited to 'Source/WebCore/css/CSSGrammar.y.in')
-rw-r--r-- | Source/WebCore/css/CSSGrammar.y.in | 1772 |
1 files changed, 892 insertions, 880 deletions
diff --git a/Source/WebCore/css/CSSGrammar.y.in b/Source/WebCore/css/CSSGrammar.y.in index d43d3c9bd..8cc70be80 100644 --- a/Source/WebCore/css/CSSGrammar.y.in +++ b/Source/WebCore/css/CSSGrammar.y.in @@ -1,6 +1,6 @@ /* * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2004-2015 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2012 Intel Corporation. All rights reserved. @@ -21,35 +21,36 @@ * */ -%pure_parser +%pure-parser %parse-param { CSSParser* parser } %lex-param { CSSParser* parser } %union { - bool boolean; - char character; - int integer; double number; CSSParserString string; - - StyleRuleBase* rule; - Vector<RefPtr<StyleRuleBase> >* ruleList; - CSSParserSelector* selector; - Vector<OwnPtr<CSSParserSelector> >* selectorList; CSSSelector::MarginBoxType marginBox; - CSSSelector::Relation relation; + CSSParserValue value; + CSSParserSelectorCombinator relation; + StyleRuleBase* rule; + Vector<RefPtr<StyleRuleBase>>* ruleList; MediaQuerySet* mediaList; MediaQuery* mediaQuery; MediaQuery::Restrictor mediaQueryRestrictor; MediaQueryExp* mediaQueryExp; - CSSParserValue value; - CSSParserValueList* valueList; - Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList; + Vector<CSSParser::SourceSize>* sourceSizeList; + Vector<std::unique_ptr<MediaQueryExp>>* mediaQueryExpList; StyleKeyframe* keyframe; - Vector<RefPtr<StyleKeyframe> >* keyframeRuleList; - float val; + Vector<RefPtr<StyleKeyframe>>* keyframeRuleList; CSSPropertyID id; + CSSParserSelector* selector; + Vector<std::unique_ptr<CSSParserSelector>>* selectorList; + bool boolean; + CSSSelector::Match match; + int integer; + char character; + CSSParserValueList* valueList; + Vector<CSSParserString>* stringList; CSSParser::Location location; } @@ -60,6 +61,8 @@ static inline int cssyyerror(void*, const char*) return 1; } +#if YYDEBUG > 0 + static inline bool isCSSTokenAString(int yytype) { switch (yytype) { @@ -75,9 +78,18 @@ static inline bool isCSSTokenAString(int yytype) case ANYFUNCTION: case NOTFUNCTION: case CALCFUNCTION: - case MINFUNCTION: + case MATCHESFUNCTION: case MAXFUNCTION: - case VAR_DEFINITION: + case MINFUNCTION: + case NTHCHILDFUNCTIONS: + case NTHCHILDSELECTORSEPARATOR: + case LANGFUNCTION: + case VARFUNCTION: +#if ENABLE_CSS_SELECTORS_LEVEL4 + case DIRFUNCTION: + case ROLEFUNCTION: +#endif + case CUSTOM_PROPERTY: case UNICODERANGE: return true; default: @@ -85,12 +97,37 @@ static inline bool isCSSTokenAString(int yytype) } } +#endif + +static inline CSSParserValue makeIdentValue(CSSParserString string) +{ + CSSParserValue v; + v.id = cssValueKeywordID(string); + v.unit = CSSPrimitiveValue::CSS_IDENT; + v.string = string; + return v; +} + +static bool selectorListDoesNotMatchAnyPseudoElement(const Vector<std::unique_ptr<CSSParserSelector>>* selectorVector) +{ + if (!selectorVector) + return true; + + for (unsigned i = 0; i < selectorVector->size(); ++i) { + for (const CSSParserSelector* selector = selectorVector->at(i).get(); selector; selector = selector->tagHistory()) { + if (selector->matchesPseudoElement()) + return false; + } + } + return true; +} + %} -#if ENABLE_SHADOW_DOM -%expect 32 +#if ENABLE_CSS_GRID_LAYOUT +%expect 39 #else -%expect 31 +%expect 38 #endif %nonassoc LOWEST_PREC @@ -109,6 +146,7 @@ static inline bool isCSSTokenAString(int yytype) %token <string> STRING %right <string> IDENT %token <string> NTH +%token <string> NTHCHILDSELECTORSEPARATOR %nonassoc <string> HEX %nonassoc <string> IDSEL @@ -122,31 +160,19 @@ static inline bool isCSSTokenAString(int yytype) %token IMPORT_SYM %token PAGE_SYM %token MEDIA_SYM -#if ENABLE_CSS3_CONDITIONAL_RULES -%token SUPPORTS_SYM -#endif %token FONT_FACE_SYM -#if ENABLE_SHADOW_DOM -%token HOST_SYM -#endif %token CHARSET_SYM +%token KEYFRAME_RULE_SYM +%token KEYFRAMES_SYM %token NAMESPACE_SYM -%token VARFUNCTION %token WEBKIT_RULE_SYM %token WEBKIT_DECLS_SYM -%token WEBKIT_KEYFRAME_RULE_SYM -%token WEBKIT_KEYFRAMES_SYM %token WEBKIT_VALUE_SYM %token WEBKIT_MEDIAQUERY_SYM +%token WEBKIT_SIZESATTR_SYM %token WEBKIT_SELECTOR_SYM %token WEBKIT_REGION_RULE_SYM %token WEBKIT_VIEWPORT_RULE_SYM -#if ENABLE_CSS3_CONDITIONAL_RULES -%token WEBKIT_SUPPORTS_CONDITION_SYM -#endif -#if ENABLE_CSS_SHADERS -%token WEBKIT_FILTER_RULE_SYM -#endif %token <marginBox> TOPLEFTCORNER_SYM %token <marginBox> TOPLEFT_SYM %token <marginBox> TOPCENTER_SYM @@ -170,11 +196,6 @@ static inline bool isCSSTokenAString(int yytype) %token MEDIA_ONLY %token MEDIA_NOT %token MEDIA_AND -#if ENABLE_CSS3_CONDITIONAL_RULES -%token SUPPORTS_NOT -%token SUPPORTS_AND -%token SUPPORTS_OR -#endif %token <number> REMS %token <number> CHS @@ -207,139 +228,143 @@ static inline bool isCSSTokenAString(int yytype) %token <number> DPPX %token <number> DPI %token <number> DPCM +%token <number> FR %token <string> URI %token <string> FUNCTION %token <string> ANYFUNCTION -#if ENABLE_VIDEO_TRACK -%token <string> CUEFUNCTION -#endif %token <string> NOTFUNCTION %token <string> CALCFUNCTION -%token <string> MINFUNCTION +%token <string> MATCHESFUNCTION %token <string> MAXFUNCTION -%token <string> VAR_DEFINITION +%token <string> MINFUNCTION +%token <string> NTHCHILDFUNCTIONS +%token <string> LANGFUNCTION +%token <string> VARFUNCTION + +#if ENABLE_CSS_SELECTORS_LEVEL4 +%token <string> DIRFUNCTION +%token <string> ROLEFUNCTION +#endif + +%token <string> CUSTOM_PROPERTY %token <string> UNICODERANGE %type <relation> combinator -%type <rule> charset -%type <rule> ignored_charset -%type <rule> ruleset -%type <rule> media -%type <rule> import -%type <rule> namespace -%type <rule> page -%type <rule> margin_box -%type <rule> font_face -#if ENABLE_SHADOW_DOM -%type <rule> host -#endif -%type <rule> keyframes -%type <rule> invalid_rule -%type <rule> save_block -%type <rule> invalid_at -%type <rule> rule -%type <rule> valid_rule -%type <ruleList> block_rule_list -%type <ruleList> region_block_rule_list -%type <rule> block_rule -%type <rule> block_valid_rule -%type <rule> region -#if ENABLE_CSS3_CONDITIONAL_RULES -%type <rule> supports -#endif -#if ENABLE_CSS_DEVICE_ADAPTATION -%type <rule> viewport -#endif -#if ENABLE_CSS_SHADERS -%type <rule> filter -#endif +%type <rule> block_rule block_valid_rule font_face import keyframes media page region rule ruleset valid_rule +%destructor { if ($$) $$->deref(); } block_rule block_valid_rule font_face import keyframes media page region rule ruleset valid_rule -%type <string> maybe_ns_prefix +%type <ruleList> block_rule_list block_valid_rule_list +%destructor { delete $$; } block_rule_list block_valid_rule_list -%type <string> namespace_selector +%type <string> ident_or_string maybe_ns_prefix namespace_selector string_or_uri -%type <string> string_or_uri -%type <string> ident_or_string -%type <string> medium %type <marginBox> margin_sym -%type <string> media_feature -%type <mediaList> media_list -%type <mediaList> maybe_media_list +%type <mediaList> media_list maybe_media_list +%destructor { if ($$) $$->deref(); } media_list maybe_media_list + %type <mediaQuery> media_query +%destructor { delete $$; } media_query + %type <mediaQueryRestrictor> maybe_media_restrictor -%type <valueList> maybe_media_value -%type <mediaQueryExp> media_query_exp -%type <mediaQueryExpList> media_query_exp_list -%type <mediaQueryExpList> maybe_and_media_query_exp_list - -#if ENABLE_CSS3_CONDITIONAL_RULES -%type <boolean> supports_condition -%type <boolean> supports_condition_in_parens -%type <boolean> supports_negation -%type <boolean> supports_conjunction -%type <boolean> supports_disjunction -%type <boolean> supports_declaration_condition -%type <boolean> supports_error -#endif + +%type <mediaQueryExp> media_query_exp base_media_query_exp +%destructor { delete $$; } media_query_exp base_media_query_exp + +%type <sourceSizeList> source_size_list +%destructor { delete $$; } source_size_list + +%type <mediaQueryExp> maybe_source_media_query_exp +%destructor { delete $$; } maybe_source_media_query_exp + +%type <value> source_size_length +%destructor { destroy($$); } source_size_length + +%type <mediaQueryExpList> media_query_exp_list maybe_and_media_query_exp_list +%destructor { delete $$; } media_query_exp_list maybe_and_media_query_exp_list %type <string> keyframe_name + %type <keyframe> keyframe_rule +%destructor { if ($$) $$->deref(); } keyframe_rule + %type <keyframeRuleList> keyframes_rule -%type <valueList> key_list -%type <value> key +%destructor { delete $$; } keyframes_rule + +// These parser values never need to be destroyed because they are never functions or value lists. +%type <value> calc_func_term key unary_term + +// These parser values need to be destroyed because they might be functions. +%type <value> calc_function function variable_function min_or_max_function term +%destructor { destroy($$); } calc_function function variable_function min_or_max_function term %type <id> property -%type <selector> specifier -%type <selector> specifier_list -%type <selector> simple_selector -%type <selector> selector -%type <selectorList> selector_list -%type <selectorList> simple_selector_list -%type <selectorList> region_selector -%type <selector> selector_with_trailing_whitespace -%type <selector> class -%type <selector> attrib -%type <selector> pseudo -%type <selector> pseudo_page -%type <selector> page_selector - -%type <boolean> declaration_list -%type <boolean> decl_list -%type <boolean> declaration -%type <boolean> declarations_and_margins - -%type <boolean> prio - -%type <integer> match -%type <integer> unary_operator -%type <integer> maybe_unary_operator -%type <character> operator - -%type <valueList> expr -%type <valueList> valid_expr -%type <value> term -%type <value> unary_term -%type <value> function -%type <value> calc_func_term -%type <character> calc_func_operator -%type <valueList> calc_func_expr -%type <valueList> valid_calc_func_expr -%type <valueList> calc_func_expr_list -%type <valueList> calc_func_paren_expr -%type <value> calc_function +%type <selector> attrib class page_selector pseudo pseudo_page complex_selector complex_selector_with_trailing_whitespace compound_selector specifier specifier_list +%destructor { delete $$; } attrib class page_selector pseudo pseudo_page complex_selector complex_selector_with_trailing_whitespace compound_selector specifier specifier_list + +%type <selectorList> selector_list nested_selector_list simple_selector_list nth_selector_ending +%destructor { delete $$; } selector_list nested_selector_list simple_selector_list +%destructor { delete $$; } nth_selector_ending + +%type <boolean> attrib_flags declaration declaration_list decl_list priority + +%type <match> match + +%type <integer> unary_operator maybe_unary_operator + +%type <character> operator calc_func_operator + +%type <valueList> calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr whitespace_or_expr maybe_expr +%destructor { delete $$; } calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr whitespace_or_expr maybe_expr + +%type <string> lang_range +%type <stringList> comma_separated_lang_ranges +%destructor { delete $$; } comma_separated_lang_ranges + %type <string> min_or_max -%type <value> min_or_max_function %type <string> element_name -%type <string> attr_name %type <location> error_location +#if ENABLE_CSS_GRID_LAYOUT + +%type <valueList> ident_list +%destructor { delete $$; } ident_list + +%type <value> track_names_list +%destructor { destroy($$); } track_names_list + +#endif + +%token SUPPORTS_AND +%token SUPPORTS_NOT +%token SUPPORTS_OR +%token SUPPORTS_SYM +%token WEBKIT_SUPPORTS_CONDITION_SYM + +%type <rule> supports +%destructor { if ($$) $$->deref(); } supports + +%type <boolean> supports_condition supports_condition_in_parens supports_conjunction supports_declaration_condition supports_disjunction supports_error supports_negation + +#if ENABLE_CSS_DEVICE_ADAPTATION + +%type <rule> viewport +%destructor { if ($$) $$->deref(); } viewport + +#endif + +#if ENABLE_VIDEO_TRACK + +%token <string> CUEFUNCTION + +#endif + %% stylesheet: @@ -348,35 +373,22 @@ stylesheet: | webkit_decls maybe_space | webkit_value maybe_space | webkit_mediaquery maybe_space + | webkit_source_size_list maybe_space | webkit_selector maybe_space | webkit_keyframe_rule maybe_space -#if ENABLE_CSS3_CONDITIONAL_RULES | webkit_supports_condition maybe_space -#endif ; -webkit_rule: - WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' { - parser->m_rule = $4; - } -; +webkit_rule: WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' { parser->m_rule = adoptRef($4); } ; -webkit_keyframe_rule: - WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' { - parser->m_keyframe = $4; - } -; +webkit_keyframe_rule: KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' { parser->m_keyframe = adoptRef($4); } ; -webkit_decls: - WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' { - /* can be empty */ - } -; +webkit_decls: WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' ; webkit_value: WEBKIT_VALUE_SYM '{' maybe_space expr '}' { if ($4) { - parser->m_valueList = parser->sinkFloatingValueList($4); + parser->m_valueList = std::unique_ptr<CSSParserValueList>($4); int oldParsedProperties = parser->m_parsedProperties.size(); if (!parser->parseValue(parser->m_id, parser->m_important)) parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); @@ -385,55 +397,34 @@ webkit_value: } ; -webkit_mediaquery: - WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' { - parser->m_mediaQuery = parser->sinkFloatingMediaQuery($4); - } -; +webkit_mediaquery: WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' { parser->m_mediaQuery = std::unique_ptr<MediaQuery>($4); } ; webkit_selector: WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' { if ($4) { if (parser->m_selectorListForParseSelector) parser->m_selectorListForParseSelector->adoptSelectorVector(*$4); + parser->recycleSelectorVector(std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($4)); } } ; -#if ENABLE_CSS3_CONDITIONAL_RULES -webkit_supports_condition: - WEBKIT_SUPPORTS_CONDITION_SYM '{' maybe_space supports_condition '}' { - parser->m_supportsCondition = $4; - } -; -#endif +webkit_supports_condition: WEBKIT_SUPPORTS_CONDITION_SYM WHITESPACE maybe_space supports_condition '}' { parser->m_supportsCondition = $4; } ; -maybe_space: - /* empty */ %prec UNIMPORTANT_TOK - | maybe_space WHITESPACE - ; +/* for expressions that require at least one whitespace to be present, like the + and - operators in calc expressions */ +space: WHITESPACE | space WHITESPACE ; -maybe_sgml: - /* empty */ - | maybe_sgml SGML_CD - | maybe_sgml WHITESPACE - ; +maybe_space: /* empty */ %prec UNIMPORTANT_TOK | maybe_space WHITESPACE ; -maybe_charset: - /* empty */ - | charset { - } - ; +maybe_sgml: /* empty */ | maybe_sgml SGML_CD | maybe_sgml WHITESPACE ; -closing_brace: - '}' - | %prec LOWEST_PREC TOKEN_EOF - ; +maybe_charset: /* empty */ | charset ; -closing_parenthesis: - ')' - | %prec LOWEST_PREC TOKEN_EOF - ; +closing_brace: '}' | %prec LOWEST_PREC TOKEN_EOF ; + +closing_parenthesis: ')' | %prec LOWEST_PREC TOKEN_EOF ; + +closing_bracket: ']' | %prec LOWEST_PREC TOKEN_EOF; charset: CHARSET_SYM maybe_space STRING maybe_space ';' { @@ -441,31 +432,23 @@ charset: parser->m_styleSheet->parserSetEncodingFromCharsetRule($3); if (parser->isExtractingSourceData() && parser->m_currentRuleDataStack->isEmpty() && parser->m_ruleSourceDataResult) parser->addNewRuleToSourceTree(CSSRuleSourceData::createUnknown()); - $$ = 0; - } - | CHARSET_SYM error invalid_block { - } - | CHARSET_SYM error ';' { } + | CHARSET_SYM error invalid_block + | CHARSET_SYM error ';' ; -ignored_charset: - CHARSET_SYM maybe_space STRING maybe_space ';' { - // Ignore any @charset rule not at the beginning of the style sheet. - $$ = 0; - } - | CHARSET_SYM maybe_space ';' { - $$ = 0; - } -; +// Ignore any @charset rule not at the beginning of the style sheet. +ignored_charset: CHARSET_SYM maybe_space STRING maybe_space ';' | CHARSET_SYM maybe_space ';' ; rule_list: - /* empty */ - | rule_list rule maybe_sgml { - if ($2 && parser->m_styleSheet) - parser->m_styleSheet->parserAppendRule($2); - } - ; + /* empty */ + | rule_list rule maybe_sgml { + if (RefPtr<StyleRuleBase> rule = adoptRef($2)) { + if (parser->m_styleSheet) + parser->m_styleSheet->parserAppendRule(rule.releaseNonNull()); + } + } + ; valid_rule: ruleset @@ -473,52 +456,45 @@ valid_rule: | page | font_face | keyframes - | namespace + | namespace { $$ = nullptr; } | import | region -#if ENABLE_CSS3_CONDITIONAL_RULES | supports -#endif -#if ENABLE_SHADOW_DOM - | host -#endif #if ENABLE_CSS_DEVICE_ADAPTATION | viewport #endif -#if ENABLE_CSS_SHADERS - | filter -#endif ; rule: valid_rule { + $$ = $1; parser->m_hadSyntacticallyValidCSSRule = true; } - | ignored_charset - | invalid_rule - | invalid_at - ; + | ignored_charset { $$ = nullptr; } + | invalid_rule { $$ = nullptr; } + | invalid_at { $$ = nullptr; } + ; block_rule_list: - /* empty */ { $$ = 0; } + /* empty */ { $$ = nullptr; } | block_rule_list block_rule maybe_sgml { $$ = $1; - if ($2) { + if (RefPtr<StyleRuleBase> rule = adoptRef($2)) { if (!$$) - $$ = parser->createRuleList(); - $$->append($2); + $$ = new Vector<RefPtr<StyleRuleBase>>; + $$->append(rule.release()); } } ; -region_block_rule_list: - /* empty */ { $$ = 0; } - | region_block_rule_list block_valid_rule maybe_sgml { +block_valid_rule_list: + /* empty */ { $$ = nullptr; } + | block_valid_rule_list block_valid_rule maybe_sgml { $$ = $1; - if ($2) { + if (RefPtr<StyleRuleBase> rule = adoptRef($2)) { if (!$$) - $$ = parser->createRuleList(); - $$->append($2); + $$ = new Vector<RefPtr<StyleRuleBase>>; + $$->append(rule.release()); } } ; @@ -529,25 +505,13 @@ block_valid_rule: | font_face | media | keyframes -#if ENABLE_CSS3_CONDITIONAL_RULES | supports -#endif #if ENABLE_CSS_DEVICE_ADAPTATION | viewport #endif -#if ENABLE_CSS_SHADERS - | filter -#endif ; -block_rule: - block_valid_rule - | invalid_rule - | invalid_at - | namespace - | import - | region - ; +block_rule: block_valid_rule | invalid_rule { $$ = nullptr; } | invalid_at { $$ = nullptr; } | namespace { $$ = nullptr; } | import | region ; at_import_header_end_maybe_space: maybe_space { @@ -564,93 +528,98 @@ before_import_rule: import: before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list ';' { - $$ = parser->createImportRule($4, $6); + $$ = parser->createImportRule($4, adoptRef($6)).leakRef(); } | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list TOKEN_EOF { - $$ = parser->createImportRule($4, $6); + $$ = parser->createImportRule($4, adoptRef($6)).leakRef(); } | before_import_rule IMPORT_SYM at_import_header_end_maybe_space string_or_uri maybe_space maybe_media_list invalid_block { - $$ = 0; + $$ = nullptr; parser->popRuleData(); + if ($6) + $6->deref(); } | before_import_rule IMPORT_SYM error ';' { - $$ = 0; + $$ = nullptr; parser->popRuleData(); } | before_import_rule IMPORT_SYM error invalid_block { - $$ = 0; + $$ = nullptr; parser->popRuleData(); } ; namespace: -NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' { - parser->addNamespace($3, $4); - $$ = 0; -} -| NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block { - $$ = 0; -} -| NAMESPACE_SYM error invalid_block { - $$ = 0; -} -| NAMESPACE_SYM error ';' { - $$ = 0; -} -; + NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' { parser->addNamespace($3, $4); } + | NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block + | NAMESPACE_SYM error invalid_block + | NAMESPACE_SYM error ';' + ; -maybe_ns_prefix: -/* empty */ { $$.clear(); } -| IDENT maybe_space { $$ = $1; } -; +maybe_ns_prefix: /* empty */ { $$.clear(); } | IDENT maybe_space; -string_or_uri: -STRING -| URI -; +string_or_uri: STRING | URI ; -media_feature: - IDENT maybe_space { +maybe_media_value: /*empty*/ { $$ = nullptr; } | ':' maybe_space expr maybe_space { $$ = $3; } ; + +webkit_source_size_list: + WEBKIT_SIZESATTR_SYM WHITESPACE source_size_list maybe_space '}' { + parser->m_sourceSizeList = std::unique_ptr<Vector<CSSParser::SourceSize>>($3); + } + ; + +source_size_list: + maybe_source_media_query_exp source_size_length { + $$ = new Vector<CSSParser::SourceSize>; + $$->append(parser->sourceSize(std::unique_ptr<MediaQueryExp>($1), $2)); + } + | source_size_list maybe_space ',' maybe_space maybe_source_media_query_exp source_size_length { $$ = $1; + $$->append(parser->sourceSize(std::unique_ptr<MediaQueryExp>($5), $6)); } ; -maybe_media_value: - /*empty*/ { - $$ = 0; +maybe_source_media_query_exp: + /* empty */ { + $$ = new MediaQueryExp; } - | ':' maybe_space expr maybe_space { - $$ = $3; + | base_media_query_exp maybe_space; + +source_size_length: unary_term | calc_function; + +base_media_query_exp: '(' maybe_space IDENT maybe_space maybe_media_value ')' { + std::unique_ptr<CSSParserValueList> mediaValue($5); + $3.convertToASCIILowercaseInPlace(); + $$ = new MediaQueryExp($3, mediaValue.get()); } ; media_query_exp: - maybe_media_restrictor maybe_space '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space { - // If restrictor is specified, media query expression is invalid. - // Create empty media query expression and continue parsing media query. - if ($1 != MediaQuery::None) - $$ = parser->createFloatingMediaQueryExp("", 0); - else { - $5.lower(); - $$ = parser->createFloatingMediaQueryExp($5, $7); - } + maybe_media_restrictor maybe_space base_media_query_exp maybe_space { + if ($1 != MediaQuery::None) { + // If restrictor is specified, media query expression is invalid. + // Create empty media query expression and continue parsing media query. + delete $3; + $$ = new MediaQueryExp; + } else + $$ = $3; } ; media_query_exp_list: media_query_exp { - $$ = parser->createFloatingMediaQueryExpList(); - $$->append(parser->sinkFloatingMediaQueryExp($1)); + $$ = new Vector<std::unique_ptr<MediaQueryExp>>; + $$->append(std::unique_ptr<MediaQueryExp>($1)); } | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp { $$ = $1; - $$->append(parser->sinkFloatingMediaQueryExp($5)); + $$->append(std::unique_ptr<MediaQueryExp>($5)); } ; maybe_and_media_query_exp_list: /*empty*/ { - $$ = parser->createFloatingMediaQueryExpList(); + $$ = new Vector<std::unique_ptr<MediaQueryExp>>; } | MEDIA_AND maybe_space media_query_exp_list { $$ = $3; @@ -671,37 +640,35 @@ maybe_media_restrictor: media_query: media_query_exp_list { - $$ = parser->createFloatingMediaQuery(parser->sinkFloatingMediaQueryExpList($1)); + $$ = new MediaQuery(MediaQuery::None, "all", std::unique_ptr<Vector<std::unique_ptr<MediaQueryExp>>>($1)); } | - maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list { - $3.lower(); - $$ = parser->createFloatingMediaQuery($1, $3, parser->sinkFloatingMediaQueryExpList($4)); + maybe_media_restrictor maybe_space IDENT maybe_space maybe_and_media_query_exp_list { + $3.convertToASCIILowercaseInPlace(); + $$ = new MediaQuery($1, $3, std::unique_ptr<Vector<std::unique_ptr<MediaQueryExp>>>($5)); } ; -maybe_media_list: - /* empty */ { - $$ = parser->createMediaQuerySet(); - } - | media_list - ; +maybe_media_list: /* empty */ { $$ = &MediaQuerySet::create().leakRef(); } | media_list ; media_list: media_query { - $$ = parser->createMediaQuerySet(); - $$->addMediaQuery(parser->sinkFloatingMediaQuery($1)); + $$ = &MediaQuerySet::create().leakRef(); + $$->addMediaQuery(std::unique_ptr<MediaQuery>($1)); parser->updateLastMediaLine($$); } | media_list ',' maybe_space media_query { $$ = $1; + std::unique_ptr<MediaQuery> mediaQuery($4); if ($$) { - $$->addMediaQuery(parser->sinkFloatingMediaQuery($4)); + $$->addMediaQuery(WTFMove(mediaQuery)); parser->updateLastMediaLine($$); } } | media_list error { - $$ = 0; + $$ = nullptr; + if ($1) + $1->deref(); } ; @@ -725,38 +692,36 @@ at_rule_header_end_maybe_space: media: before_media_rule MEDIA_SYM maybe_space media_list at_rule_header_end '{' at_rule_body_start maybe_space block_rule_list save_block { - $$ = parser->createMediaRule($4, $9); + $$ = parser->createMediaRule(adoptRef($4), std::unique_ptr<Vector<RefPtr<StyleRuleBase>>>($9).get()).leakRef(); } | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space block_rule_list save_block { - $$ = parser->createEmptyMediaRule($7); + $$ = parser->createEmptyMediaRule(std::unique_ptr<Vector<RefPtr<StyleRuleBase>>>($7).get()).leakRef(); } | before_media_rule MEDIA_SYM at_rule_header_end_maybe_space ';' { - $$ = 0; + $$ = nullptr; parser->popRuleData(); } ; -medium: - IDENT maybe_space { - $$ = $1; - } - ; - -#if ENABLE_CSS3_CONDITIONAL_RULES supports: before_supports_rule SUPPORTS_SYM maybe_space supports_condition at_supports_rule_header_end '{' at_rule_body_start maybe_space block_rule_list save_block { - $$ = parser->createSupportsRule($4, $9); + $$ = parser->createSupportsRule($4, std::unique_ptr<Vector<RefPtr<StyleRuleBase>>>($9).get()).leakRef(); } | before_supports_rule SUPPORTS_SYM supports_error { - $$ = 0; + $$ = nullptr; parser->popRuleData(); parser->popSupportsRuleData(); } ; -supports_error: - error ';' - | error invalid_block +supports_error: + error ';' { + $$ = false; + } + | error invalid_block { + $$ = false; + } + ; before_supports_rule: /* empty */ { @@ -772,53 +737,35 @@ at_supports_rule_header_end: } ; -supports_condition: - supports_condition_in_parens - | supports_negation - | supports_conjunction - | supports_disjunction - ; +supports_condition: supports_condition_in_parens | supports_negation | supports_conjunction | supports_disjunction ; -supports_negation: - SUPPORTS_NOT maybe_space supports_condition_in_parens { - $$ = !$3; - } - ; +supports_negation: SUPPORTS_NOT maybe_space supports_condition_in_parens { $$ = !$3; } ; supports_conjunction: - supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens { - $$ = $1 && $4; - } - | supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens { - $$ = $1 && $4; - } + supports_condition_in_parens SUPPORTS_AND maybe_space supports_condition_in_parens { $$ = $1 && $4; } + | supports_conjunction SUPPORTS_AND maybe_space supports_condition_in_parens { $$ = $1 && $4; } ; supports_disjunction: - supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens { - $$ = $1 || $4; - } - | supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens { - $$ = $1 || $4; - } + supports_condition_in_parens SUPPORTS_OR maybe_space supports_condition_in_parens { $$ = $1 || $4; } + | supports_disjunction SUPPORTS_OR maybe_space supports_condition_in_parens { $$ = $1 || $4; } ; supports_condition_in_parens: - '(' maybe_space supports_condition ')' maybe_space { - $$ = $3; - } - | supports_declaration_condition - | '(' error ')' + '(' maybe_space supports_condition ')' maybe_space { $$ = $3; } + | supports_declaration_condition { $$ = $1; } + | '(' error ')' { $$ = false; } ; supports_declaration_condition: - '(' maybe_space property ':' maybe_space expr prio ')' maybe_space { + '(' maybe_space property ':' maybe_space expr priority ')' maybe_space { $$ = false; CSSParser* p = static_cast<CSSParser*>(parser); - if ($3 && $6) { - p->m_valueList = p->sinkFloatingValueList($6); + std::unique_ptr<CSSParserValueList> propertyValue($6); + if ($3 && propertyValue) { + p->m_valueList = WTFMove(propertyValue); int oldParsedProperties = p->m_parsedProperties.size(); - $$ = p->parseValue(static_cast<CSSPropertyID>($3), $7); + $$ = p->parseValue($3, $7); // We just need to know if the declaration is supported as it is written. Rollback any additions. if ($$) p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties); @@ -826,8 +773,23 @@ supports_declaration_condition: } p->markPropertyEnd($7, false); } + | + '(' maybe_space CUSTOM_PROPERTY maybe_space ':' whitespace_or_expr priority ')' maybe_space { + $$ = false; + CSSParser* p = static_cast<CSSParser*>(parser); + std::unique_ptr<CSSParserValueList> propertyValue($6); + if (propertyValue) { + parser->m_valueList = WTFMove(propertyValue); + int oldParsedProperties = p->m_parsedProperties.size(); + p->setCustomPropertyName($3); + $$ = p->parseValue(CSSPropertyCustom, $7); + if ($$) + p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties); + p->m_valueList = nullptr; + } + p->markPropertyEnd($7, false); + } ; -#endif before_keyframes_rule: /* empty */ { @@ -836,56 +798,51 @@ before_keyframes_rule: ; keyframes: - before_keyframes_rule WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space keyframes_rule closing_brace { - $$ = parser->createKeyframesRule($4, parser->sinkFloatingKeyframeVector($9)); + before_keyframes_rule KEYFRAMES_SYM maybe_space keyframe_name at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space keyframes_rule closing_brace { + $$ = parser->createKeyframesRule($4, std::unique_ptr<Vector<RefPtr<StyleKeyframe>>>($9)).leakRef(); } ; - -keyframe_name: - IDENT - | STRING - ; + +keyframe_name: IDENT | STRING ; keyframes_rule: - /* empty */ { $$ = parser->createFloatingKeyframeVector(); } + /* empty */ { $$ = new Vector<RefPtr<StyleKeyframe>>; } | keyframes_rule keyframe_rule maybe_space { $$ = $1; - if ($2) - $$->append($2); + if (RefPtr<StyleKeyframe> keyframe = adoptRef($2)) + $$->append(keyframe.release()); } ; -keyframe_rule: - key_list maybe_space '{' maybe_space declaration_list closing_brace { - $$ = parser->createKeyframe($1); - } - ; +keyframe_rule: key_list maybe_space '{' maybe_space declaration_list closing_brace { $$ = parser->createKeyframe(*std::unique_ptr<CSSParserValueList>($1)).leakRef(); } ; key_list: key { - $$ = parser->createFloatingValueList(); - $$->addValue(parser->sinkFloatingValue($1)); + $$ = new CSSParserValueList; + $$->addValue($1); } | key_list maybe_space ',' maybe_space key { $$ = $1; + ASSERT($5.unit != CSSParserValue::Function); // No need to call destroy. if ($$) - $$->addValue(parser->sinkFloatingValue($5)); + $$->addValue($5); } ; key: maybe_unary_operator PERCENTAGE { $$.id = CSSValueInvalid; $$.isInt = false; $$.fValue = $1 * $2; $$.unit = CSSPrimitiveValue::CSS_NUMBER; } | IDENT { - $$.id = CSSValueInvalid; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER; - CSSParserString& str = $1; - if (str.equalIgnoringCase("from")) + $$.id = CSSValueInvalid; + $$.isInt = false; + if (equalLettersIgnoringASCIICase($1, "from")) $$.fValue = 0; - else if (str.equalIgnoringCase("to")) + else if (equalLettersIgnoringASCIICase($1, "to")) $$.fValue = 100; else { $$.unit = 0; YYERROR; } + $$.unit = CSSPrimitiveValue::CSS_NUMBER; } | error { $$.unit = 0; @@ -902,28 +859,28 @@ page: before_page_rule PAGE_SYM maybe_space page_selector at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space_before_declaration declarations_and_margins closing_brace { if ($4) - $$ = parser->createPageRule(parser->sinkFloatingSelector($4)); + $$ = parser->createPageRule(std::unique_ptr<CSSParserSelector>($4)).leakRef(); else { // Clear properties in the invalid @page rule. parser->clearProperties(); // Also clear margin at-rules here once we fully implement margin at-rules parsing. - $$ = 0; + $$ = nullptr; parser->popRuleData(); } } | before_page_rule PAGE_SYM error invalid_block { - parser->popRuleData(); - $$ = 0; + parser->popRuleData(); + $$ = nullptr; } | before_page_rule PAGE_SYM error ';' { - parser->popRuleData(); - $$ = 0; + parser->popRuleData(); + $$ = nullptr; } ; page_selector: IDENT { - $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); + $$ = new CSSParserSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); $$->setForPage(); } | IDENT pseudo_page { @@ -939,25 +896,22 @@ page_selector: $$->setForPage(); } | /* empty */ { - $$ = parser->createFloatingSelector(); + $$ = new CSSParserSelector; $$->setForPage(); } ; -declarations_and_margins: - declaration_list - | declarations_and_margins margin_box maybe_space declaration_list - ; +declarations_and_margins: declaration_list | declarations_and_margins margin_box maybe_space declaration_list ; margin_box: margin_sym { parser->startDeclarationsForMarginBox(); } maybe_space '{' maybe_space declaration_list closing_brace { - $$ = parser->createMarginAtRule($1); + parser->createMarginAtRule($1); } ; -margin_sym : +margin_sym: TOPLEFTCORNER_SYM { $$ = CSSSelector::TopLeftCornerMarginBox; } @@ -1015,40 +969,21 @@ before_font_face_rule: ; font_face: - before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space - '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { - $$ = parser->createFontFaceRule(); + before_font_face_rule FONT_FACE_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { + $$ = parser->createFontFaceRule().leakRef(); } | before_font_face_rule FONT_FACE_SYM error invalid_block { - $$ = 0; - parser->popRuleData(); + $$ = nullptr; + parser->popRuleData(); } | before_font_face_rule FONT_FACE_SYM error ';' { - $$ = 0; - parser->popRuleData(); - } -; - -#if ENABLE_SHADOW_DOM -before_host_rule: - /* empty */ { - parser->markRuleHeaderStart(CSSRuleSourceData::HOST_RULE); - } - ; - -host: - before_host_rule HOST_SYM at_rule_header_end_maybe_space - '{' at_rule_body_start maybe_space block_rule_list save_block { - $$ = parser->createHostRule($7); - } - | before_host_rule HOST_SYM at_rule_header_end_maybe_space ';' { - $$ = 0; + $$ = nullptr; parser->popRuleData(); } - ; -#endif +; #if ENABLE_CSS_DEVICE_ADAPTATION + before_viewport_rule: /* empty */ { parser->markViewportRuleBodyStart(); @@ -1059,32 +994,22 @@ before_viewport_rule: viewport: before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM at_rule_header_end_maybe_space '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { - $$ = parser->createViewportRule(); + $$ = parser->createViewportRule().leakRef(); parser->markViewportRuleBodyEnd(); } | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error invalid_block { - $$ = 0; + $$ = nullptr; parser->popRuleData(); parser->markViewportRuleBodyEnd(); } | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error ';' { - $$ = 0; + $$ = nullptr; parser->popRuleData(); parser->markViewportRuleBodyEnd(); } ; -#endif -region_selector: - selector_list { - if ($1) { - parser->setReusableRegionSelectorVector($1); - $$ = parser->reusableRegionSelectorVector(); - } - else - $$ = 0; - } -; +#endif before_region_rule: /* empty */ { @@ -1093,240 +1018,233 @@ before_region_rule: ; region: - before_region_rule WEBKIT_REGION_RULE_SYM WHITESPACE region_selector at_rule_header_end '{' at_rule_body_start maybe_space region_block_rule_list save_block { + before_region_rule WEBKIT_REGION_RULE_SYM maybe_space selector_list at_rule_header_end '{' at_rule_body_start maybe_space block_valid_rule_list save_block { + std::unique_ptr<Vector<RefPtr<StyleRuleBase>>> ruleList($9); if ($4) - $$ = parser->createRegionRule($4, $9); + $$ = parser->createRegionRule(std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($4).get(), ruleList.get()).leakRef(); else { - $$ = 0; + $$ = nullptr; parser->popRuleData(); } } ; -#if ENABLE_CSS_SHADERS -before_filter_rule: - /* empty */ { - parser->markRuleHeaderStart(CSSRuleSourceData::FILTER_RULE); - parser->m_inFilterRule = true; - } - ; - -filter: - before_filter_rule WEBKIT_FILTER_RULE_SYM WHITESPACE IDENT at_rule_header_end_maybe_space - '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { - parser->m_inFilterRule = false; - $$ = parser->createFilterRule($4); - } - ; -#endif - combinator: - '+' maybe_space { $$ = CSSSelector::DirectAdjacent; } - | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; } - | '>' maybe_space { $$ = CSSSelector::Child; } + '+' maybe_space { $$ = CSSParserSelectorCombinator::DirectAdjacent; } + | '~' maybe_space { $$ = CSSParserSelectorCombinator::IndirectAdjacent; } + | '>' maybe_space { $$ = CSSParserSelectorCombinator::Child; } +#if ENABLE_CSS_SELECTORS_LEVEL4 + | '>' '>' maybe_space { $$ = CSSParserSelectorCombinator::DescendantDoubleChild; } +#endif ; -maybe_unary_operator: - unary_operator { $$ = $1; } - | { $$ = 1; } - ; +maybe_unary_operator: unary_operator | { $$ = 1; } ; -unary_operator: - '-' { $$ = -1; } - | '+' { $$ = 1; } - ; +unary_operator: '-' { $$ = -1; } | '+' { $$ = 1; } ; -maybe_space_before_declaration: - maybe_space { - parser->markPropertyStart(); - } - ; +maybe_space_before_declaration: maybe_space { parser->markPropertyStart(); } ; before_selector_list: - /* empty */ { + { parser->markRuleHeaderStart(CSSRuleSourceData::STYLE_RULE); parser->markSelectorStart(); } ; -at_rule_header_end: - /* empty */ { - parser->markRuleHeaderEnd(); - } - ; +at_rule_header_end: { parser->markRuleHeaderEnd(); } ; -at_selector_end: - /* empty */ { - parser->markSelectorEnd(); - } - ; +at_selector_end: { parser->markSelectorEnd(); } ; ruleset: before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { - $$ = parser->createStyleRule($2); + $$ = parser->createStyleRule($2).leakRef(); + parser->recycleSelectorVector(std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($2)); } ; -before_selector_group_item: - /* empty */ { - parser->markSelectorStart(); - } +before_selector_group_item: { parser->markSelectorStart(); } ; selector_list: - selector %prec UNIMPORTANT_TOK { + complex_selector %prec UNIMPORTANT_TOK { + $$ = nullptr; if ($1) { - $$ = parser->reusableSelectorVector(); - $$->shrink(0); - $$->append(parser->sinkFloatingSelector($1)); + $$ = parser->createSelectorVector().release(); + $$->append(std::unique_ptr<CSSParserSelector>($1)); parser->updateLastSelectorLineAndPosition(); } } - | selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK { - if ($1 && $6) { - $$ = $1; - $$->append(parser->sinkFloatingSelector($6)); + | selector_list at_selector_end ',' maybe_space before_selector_group_item complex_selector %prec UNIMPORTANT_TOK { + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> selectorList($1); + std::unique_ptr<CSSParserSelector> selector($6); + $$ = nullptr; + if (selectorList && selector) { + $$ = selectorList.release(); + $$->append(WTFMove(selector)); parser->updateLastSelectorLineAndPosition(); - } else - $$ = 0; + } } - | selector_list error { - $$ = 0; + | selector_list error { + $$ = nullptr; + delete $1; } ; -selector_with_trailing_whitespace: - selector WHITESPACE { - $$ = $1; +before_nested_selector_list: { parser->startNestedSelectorList(); } ; +after_nested_selector_list: { parser->endNestedSelectorList(); } ; + +nested_selector_list: + before_nested_selector_list selector_list after_nested_selector_list { + $$ = $2; } ; -selector: - simple_selector { - $$ = $1; +lang_range: IDENT | STRING ; + +comma_separated_lang_ranges: + lang_range %prec UNIMPORTANT_TOK { + $$ = new Vector<CSSParserString>; + $$->append($1); } - | selector_with_trailing_whitespace - { + | comma_separated_lang_ranges maybe_space ',' maybe_space lang_range %prec UNIMPORTANT_TOK { $$ = $1; + if ($$) + $1->append($5); } - | selector_with_trailing_whitespace simple_selector - { - $$ = $2; - if (!$1) - $$ = 0; - else if ($$) - $$->appendTagHistory(CSSSelector::Descendant, parser->sinkFloatingSelector($1)); + | comma_separated_lang_ranges error { + $$ = nullptr; + delete $1; } - | selector combinator simple_selector { - $$ = $3; - if (!$1) - $$ = 0; - else if ($$) - $$->appendTagHistory($2, parser->sinkFloatingSelector($1)); + ; + +complex_selector_with_trailing_whitespace: + complex_selector WHITESPACE; + +complex_selector: + compound_selector + | complex_selector_with_trailing_whitespace + | complex_selector_with_trailing_whitespace compound_selector { + std::unique_ptr<CSSParserSelector> left($1); + std::unique_ptr<CSSParserSelector> right($2); + $$ = nullptr; + if (left && right) { + right->appendTagHistory(CSSParserSelectorCombinator::DescendantSpace, WTFMove(left)); + $$ = right.release(); + } } - | selector error { - $$ = 0; + | complex_selector combinator compound_selector { + std::unique_ptr<CSSParserSelector> left($1); + std::unique_ptr<CSSParserSelector> right($3); + $$ = nullptr; + if (left && right) { + right->appendTagHistory($2, WTFMove(left)); + $$ = right.release(); + } + } + | complex_selector error { + $$ = nullptr; + delete $1; } ; namespace_selector: - /* empty */ '|' { $$.clear(); } + '|' { $$.clear(); } | '*' '|' { static LChar star = '*'; $$.init(&star, 1); } - | IDENT '|' { $$ = $1; } + | IDENT '|' ; - -simple_selector: + +compound_selector: element_name { - $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); + $$ = new CSSParserSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); } | element_name specifier_list { $$ = $2; if ($$) - $$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $$); + parser->rewriteSpecifiersWithElementName(nullAtom, $1, *$$); } | specifier_list { $$ = $1; if ($$) - $$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($$); + parser->rewriteSpecifiersWithNamespaceIfNeeded(*$$); } | namespace_selector element_name { - $$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2)); + $$ = new CSSParserSelector(parser->determineNameInNamespace($1, $2)); } | namespace_selector element_name specifier_list { $$ = $3; if ($$) - $$ = parser->rewriteSpecifiersWithElementName($1, $2, $$); + parser->rewriteSpecifiersWithElementName($1, $2, *$$); } | namespace_selector specifier_list { $$ = $2; if ($$) - $$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $$); + parser->rewriteSpecifiersWithElementName($1, starAtom, *$$); } ; simple_selector_list: - simple_selector %prec UNIMPORTANT_TOK { + compound_selector %prec UNIMPORTANT_TOK { + $$ = nullptr; if ($1) { - $$ = parser->createFloatingSelectorVector(); - $$->append(parser->sinkFloatingSelector($1)); - } else - $$ = 0; + $$ = parser->createSelectorVector().release(); + $$->append(std::unique_ptr<CSSParserSelector>($1)); + } } - | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK { - if ($1 && $5) { - $$ = $1; - $$->append(parser->sinkFloatingSelector($5)); - } else - $$ = 0; + | simple_selector_list maybe_space ',' maybe_space compound_selector %prec UNIMPORTANT_TOK { + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> list($1); + std::unique_ptr<CSSParserSelector> selector($5); + $$ = nullptr; + if (list && selector) { + $$ = list.release(); + $$->append(WTFMove(selector)); + } } | simple_selector_list error { - $$ = 0; + $$ = nullptr; + delete $1; } - ; + ; element_name: IDENT { - CSSParserString& str = $1; - if (parser->m_context.isHTMLDocument) - str.lower(); - $$ = str; + $$ = $1; } | '*' { static LChar star = '*'; $$.init(&star, 1); } - ; + ; specifier_list: - specifier { - $$ = $1; - } + specifier | specifier_list specifier { - if (!$2) - $$ = 0; - else if ($1) - $$ = parser->rewriteSpecifiers($1, $2); + std::unique_ptr<CSSParserSelector> list($1); + std::unique_ptr<CSSParserSelector> specifier($2); + $$ = nullptr; + if (list && specifier) + $$ = parser->rewriteSpecifiers(WTFMove(list), WTFMove(specifier)).release(); } | specifier_list error { - $$ = 0; + $$ = nullptr; + delete $1; } ; specifier: IDSEL { - $$ = parser->createFloatingSelector(); + $$ = new CSSParserSelector; $$->setMatch(CSSSelector::Id); if (parser->m_context.mode == CSSQuirksMode) - $1.lower(); + $1.convertToASCIILowercaseInPlace(); $$->setValue($1); } | HEX { - if ($1[0] >= '0' && $1[0] <= '9') { - $$ = 0; - } else { - $$ = parser->createFloatingSelector(); + if ($1[0] >= '0' && $1[0] <= '9') + $$ = nullptr; + else { + $$ = new CSSParserSelector; $$->setMatch(CSSSelector::Id); if (parser->m_context.mode == CSSQuirksMode) - $1.lower(); + $1.convertToASCIILowercaseInPlace(); $$->setValue($1); } } @@ -1337,45 +1255,52 @@ specifier: class: '.' IDENT { - $$ = parser->createFloatingSelector(); + $$ = new CSSParserSelector; $$->setMatch(CSSSelector::Class); if (parser->m_context.mode == CSSQuirksMode) - $2.lower(); + $2.convertToASCIILowercaseInPlace(); $$->setValue($2); } ; -attr_name: - IDENT maybe_space { - $$ = $1; - } - ; - attrib: - '[' maybe_space attr_name ']' { - $$ = parser->createFloatingSelector(); + '[' maybe_space IDENT maybe_space ']' { + $$ = new CSSParserSelector; $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom), parser->m_context.isHTMLDocument); $$->setMatch(CSSSelector::Set); } - | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' { - $$ = parser->createFloatingSelector(); + | '[' maybe_space IDENT maybe_space match maybe_space ident_or_string maybe_space attrib_flags ']' { + $$ = new CSSParserSelector; $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom), parser->m_context.isHTMLDocument); - $$->setMatch((CSSSelector::Match)$4); - $$->setValue($6); + $$->setMatch($5); + $$->setValue($7); + $$->setAttributeValueMatchingIsCaseInsensitive($9); } - | '[' maybe_space namespace_selector attr_name ']' { - $$ = parser->createFloatingSelector(); + | '[' maybe_space namespace_selector IDENT maybe_space ']' { + $$ = new CSSParserSelector; $$->setAttribute(parser->determineNameInNamespace($3, $4), parser->m_context.isHTMLDocument); $$->setMatch(CSSSelector::Set); } - | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' { - $$ = parser->createFloatingSelector(); + | '[' maybe_space namespace_selector IDENT maybe_space match maybe_space ident_or_string maybe_space attrib_flags ']' { + $$ = new CSSParserSelector; $$->setAttribute(parser->determineNameInNamespace($3, $4), parser->m_context.isHTMLDocument); - $$->setMatch((CSSSelector::Match)$5); - $$->setValue($7); + $$->setMatch($6); + $$->setValue($8); + $$->setAttributeValueMatchingIsCaseInsensitive($10); } ; +attrib_flags: + IDENT maybe_space { + if (UNLIKELY($1.length() != 1 || !isASCIIAlphaCaselessEqual($1[0], 'i'))) + YYERROR; + $$ = true; + } + | + /* empty */ { + $$ = false; + } + match: '=' { $$ = CSSSelector::Exact; @@ -1397,55 +1322,39 @@ match: } ; -ident_or_string: - IDENT - | STRING - ; +ident_or_string: IDENT | STRING ; pseudo_page: ':' IDENT { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PagePseudoClass); - $2.lower(); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; + $$ = CSSParserSelector::parsePagePseudoSelector($2); } +nth_selector_ending: + ')' { + $$ = nullptr; + } + | space ')' { + $$ = nullptr; + } + | space NTHCHILDSELECTORSEPARATOR space nested_selector_list maybe_space ')' { + if ($4) + $$ = $4; + else + YYERROR; + } + ; + pseudo: ':' IDENT { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $2.lower(); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; + $$ = CSSParserSelector::parsePseudoClassAndCompatibilityElementSelector($2); } | ':' ':' IDENT { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoElement); - $3.lower(); - $$->setValue($3); - // FIXME: This call is needed to force selector to compute the pseudoType early enough. - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; + $$ = CSSParserSelector::parsePseudoElementSelector($3); } #if ENABLE_VIDEO_TRACK // used by ::cue(:past/:future) | ':' ':' CUEFUNCTION maybe_space simple_selector_list maybe_space ')' { - if ($5) { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($5)); - $$->setValue($3); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type != CSSSelector::PseudoCue) - $$ = 0; - } else - $$ = 0; + $$ = CSSParserSelector::parsePseudoElementCueFunctionSelector($3, $5); } #endif // use by :-webkit-any. @@ -1454,93 +1363,170 @@ pseudo: // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some // related discussion with respect to :not. | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' { + $$ = nullptr; if ($4) { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4)); - $2.lower(); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type != CSSSelector::PseudoAny) - $$ = 0; - } else - $$ = 0; + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($4)); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() == CSSSelector::PseudoClassAny) + $$ = selector.release(); + } + } + | ':' MATCHESFUNCTION maybe_space nested_selector_list maybe_space ')' { + $$ = nullptr; + if ($4) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->adoptSelectorVector(*std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>>($4)); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() == CSSSelector::PseudoClassMatches) + $$ = selector.release(); + } + } + | ':' LANGFUNCTION maybe_space comma_separated_lang_ranges maybe_space ')' { + $$ = nullptr; + if ($4) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setLangArgumentList(*std::unique_ptr<Vector<CSSParserString>>($4)); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() == CSSSelector::PseudoClassLang) + $$ = selector.release(); + } + } + +#if ENABLE_CSS_SELECTORS_LEVEL4 + | ':' DIRFUNCTION maybe_space IDENT maybe_space ')' { + $$ = nullptr; + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() == CSSSelector::PseudoClassDir) + $$ = selector.release(); } + + | ':' ROLEFUNCTION maybe_space IDENT maybe_space ')' { + $$ = nullptr; + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() == CSSSelector::PseudoClassRole) + $$ = selector.release(); + } +#endif + + // Definition of :nth-child(). + | ':' NTHCHILDFUNCTIONS maybe_space NTH nth_selector_ending { + $$ = nullptr; + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($5); + if (selectorListDoesNotMatchAnyPseudoElement(ending.get())) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + if (ending) + selector->adoptSelectorVector(*ending); + CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType(); + if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) + $$ = selector.release(); + } + } + | ':' NTHCHILDFUNCTIONS maybe_space maybe_unary_operator INTEGER nth_selector_ending { + $$ = nullptr; + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($6); + if (selectorListDoesNotMatchAnyPseudoElement(ending.get())) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument(AtomicString::number($4 * $5)); + selector->setPseudoClassValue($2); + if (ending) + selector->adoptSelectorVector(*ending); + CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType(); + if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) + $$ = selector.release(); + } + } + | ':' NTHCHILDFUNCTIONS maybe_space IDENT nth_selector_ending { + $$ = nullptr; + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> ending($5); + if (isValidNthToken($4) && selectorListDoesNotMatchAnyPseudoElement(ending.get())) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + if (ending) + selector->adoptSelectorVector(*ending); + CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType(); + if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) + $$ = selector.release(); + } + } + // used by :nth-*(ax+b) | ':' FUNCTION maybe_space NTH maybe_space ')' { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $$->setArgument($4); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; + $$ = nullptr; + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() != CSSSelector::PseudoClassUnknown) + $$ = selector.release(); } // used by :nth-* | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $$->setArgument(String::number($4 * $5)); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; + $$ = nullptr; + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument(AtomicString::number($4 * $5)); + selector->setPseudoClassValue($2); + if (selector->pseudoClassType() != CSSSelector::PseudoClassUnknown) + $$ = selector.release(); } // used by :nth-*(odd/even) and :lang | ':' FUNCTION maybe_space IDENT maybe_space ')' { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - $$->setArgument($4); - $2.lower(); - $$->setValue($2); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoUnknown) - $$ = 0; - else if (type == CSSSelector::PseudoNthChild || - type == CSSSelector::PseudoNthOfType || - type == CSSSelector::PseudoNthLastChild || - type == CSSSelector::PseudoNthLastOfType) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setArgument($4); + selector->setPseudoClassValue($2); + CSSSelector::PseudoClassType type = selector->pseudoClassType(); + if (type == CSSSelector::PseudoClassUnknown) + selector = nullptr; + else if (type == CSSSelector::PseudoClassNthChild || + type == CSSSelector::PseudoClassNthOfType || + type == CSSSelector::PseudoClassNthLastChild || + type == CSSSelector::PseudoClassNthLastOfType) { if (!isValidNthToken($4)) - $$ = 0; + selector = nullptr; } + $$ = selector.release(); } - // used by :not - | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' { - if (!$4 || !$4->isSimple()) - $$ = 0; - else { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoClass); - - Vector<OwnPtr<CSSParserSelector> > selectorVector; - selectorVector.append(parser->sinkFloatingSelector($4)); - $$->adoptSelectorVector(selectorVector); - - $2.lower(); - $$->setValue($2); + // Definition of :not(). + | ':' NOTFUNCTION maybe_space nested_selector_list maybe_space ')' { + $$ = nullptr; + if ($4) { + std::unique_ptr<Vector<std::unique_ptr<CSSParserSelector>>> list($4); + if (selectorListDoesNotMatchAnyPseudoElement(list.get())) { + auto selector = std::make_unique<CSSParserSelector>(); + selector->setMatch(CSSSelector::PseudoClass); + selector->setPseudoClassValue($2); + selector->adoptSelectorVector(*list); + if (selector->pseudoClassType() == CSSSelector::PseudoClassNot) + $$ = selector.release(); + } } } ; declaration_list: /* empty */ { $$ = false; } - | declaration { - $$ = $1; - } - | decl_list declaration { - $$ = $1; - if ( $2 ) - $$ = $2; - } - | decl_list { - $$ = $1; - } - | decl_list_recovery { - $$ = false; - } - | decl_list decl_list_recovery { - $$ = $1; - } + | declaration + | decl_list declaration { $$ = $1 || $2; } + | decl_list + | decl_list_recovery { $$ = false; } + | decl_list decl_list_recovery ; decl_list: @@ -1571,23 +1557,15 @@ decl_list_recovery: ; declaration: - VAR_DEFINITION maybe_space ':' maybe_space expr prio { -#if ENABLE_CSS_VARIABLES - parser->storeVariableDeclaration($1, parser->sinkFloatingValueList($5), $6); - $$ = true; - parser->markPropertyEnd($6, true); -#else - $$ = false; -#endif - } - | - property ':' maybe_space expr prio { + CUSTOM_PROPERTY maybe_space ':' whitespace_or_expr priority { $$ = false; bool isPropertyParsed = false; - if ($1 && $4) { - parser->m_valueList = parser->sinkFloatingValueList($4); + std::unique_ptr<CSSParserValueList> propertyValue($4); + if (propertyValue) { + parser->m_valueList = WTFMove(propertyValue); int oldParsedProperties = parser->m_parsedProperties.size(); - $$ = parser->parseValue(static_cast<CSSPropertyID>($1), $5); + parser->setCustomPropertyName($1); + $$ = parser->parseValue(CSSPropertyCustom, $5); if (!$$) parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); else @@ -1596,59 +1574,105 @@ declaration: } parser->markPropertyEnd($5, isPropertyParsed); } - | - property declaration_recovery { + | property ':' maybe_space expr priority { $$ = false; + bool isPropertyParsed = false; + std::unique_ptr<CSSParserValueList> propertyValue($4); + if ($1 && propertyValue) { + parser->m_valueList = WTFMove(propertyValue); + int oldParsedProperties = parser->m_parsedProperties.size(); + $$ = parser->parseValue($1, $5); + if (!$$) + parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); + else + isPropertyParsed = true; + parser->m_valueList = nullptr; + } + parser->markPropertyEnd($5, isPropertyParsed); } - | - property ':' maybe_space expr prio declaration_recovery { - /* When we encounter something like p {color: red !important fail;} we should drop the declaration */ + | property declaration_recovery { $$ = false; } + | property ':' maybe_space expr priority declaration_recovery { + // When we encounter something like p {color: red !important fail;} we should drop the declaration. parser->markPropertyEnd(false, false); + delete $4; $$ = false; } - | - IMPORTANT_SYM maybe_space declaration_recovery { - /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */ + | IMPORTANT_SYM maybe_space declaration_recovery { + // Handle this case -- div { text-align: center; !important } -- by just reducing away the stray !important. $$ = false; } - | - property ':' maybe_space declaration_recovery { - /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */ + | property ':' maybe_space declaration_recovery { + // If we come across rules with invalid values like this case: p { weight: *; }, just discard the rule. parser->markPropertyEnd(false, false); $$ = false; } ; -declaration_recovery: - error error_location error_recovery { - parser->syntaxError($2); - } - ; +declaration_recovery: error error_location error_recovery { parser->syntaxError($2); } ; + +property: IDENT maybe_space { $$ = cssPropertyID($1); } ; + +priority: IMPORTANT_SYM maybe_space { $$ = true; } | /* empty */ { $$ = false; } ; -property: +#if ENABLE_CSS_GRID_LAYOUT + +ident_list: IDENT maybe_space { - $$ = cssPropertyID($1); + $$ = new CSSParserValueList; + $$->addValue(makeIdentValue($1)); } - ; + | ident_list IDENT maybe_space { + $$ = $1; + $$->addValue(makeIdentValue($2)); + } + ; -prio: - IMPORTANT_SYM maybe_space { $$ = true; } - | /* empty */ { $$ = false; } +track_names_list: + '[' maybe_space closing_bracket { + $$.setFromValueList(std::make_unique<CSSParserValueList>()); + } + | '[' maybe_space ident_list closing_bracket { + $$.setFromValueList(std::unique_ptr<CSSParserValueList>($3)); + } + | '[' maybe_space expr_recovery closing_bracket { + $$.id = CSSValueInvalid; + $$.unit = 0; + YYERROR; + } ; -expr: - valid_expr - | valid_expr expr_recovery { $$ = 0; } - ; +#endif + +whitespace_or_expr: + WHITESPACE maybe_expr { + if ($2) + $$ = $2; + else { + CSSParserValue val; + val.id = CSSValueInvalid; + val.unit = CSSPrimitiveValue::CSS_PARSER_WHITESPACE; + val.string.init(emptyString()); + $$ = new CSSParserValueList; + $$->addValue(val); + } + } + | maybe_space expr { $$ = $2; } + ; + +maybe_expr: /* empty */ { $$ = nullptr; } | expr { $$ = $1; }; + +expr: valid_expr | valid_expr expr_recovery { $$ = nullptr; delete $1; } ; valid_expr: term { - $$ = parser->createFloatingValueList(); - $$->addValue(parser->sinkFloatingValue($1)); + $$ = new CSSParserValueList; + $$->addValue($1); } | valid_expr operator term { $$ = $1; - if ($$) { + if (!$$) + destroy($3); + else { if ($2) { CSSParserValue v; v.id = CSSValueInvalid; @@ -1656,36 +1680,20 @@ valid_expr: v.iValue = $2; $$->addValue(v); } - $$->addValue(parser->sinkFloatingValue($3)); + $$->addValue($3); } } ; -expr_recovery: - error error_location error_recovery - ; +expr_recovery: error error_location error_recovery ; -operator: - '/' maybe_space { - $$ = '/'; - } - | ',' maybe_space { - $$ = ','; - } - | /* empty */ { - $$ = 0; - } - ; +operator: '/' maybe_space { $$ = '/'; } | ',' maybe_space { $$ = ','; } | /* empty */ { $$ = 0; } ; term: - unary_term maybe_space { $$ = $1; } + unary_term maybe_space | unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; } | STRING maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } - | IDENT maybe_space { - $$.id = cssValueKeywordID($1); - $$.unit = CSSPrimitiveValue::CSS_IDENT; - $$.string = $1; - } + | IDENT maybe_space { $$ = makeIdentValue($1); } /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */ | DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } | unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } @@ -1693,26 +1701,17 @@ term: | UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } | HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } | '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */ - | VARFUNCTION maybe_space IDENT closing_parenthesis maybe_space { -#if ENABLE_CSS_VARIABLES - $$.id = CSSValueInvalid; - $$.string = $3; - $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME; -#endif - } /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ - | function maybe_space { - $$ = $1; - } - | calc_function maybe_space { - $$ = $1; - } - | min_or_max_function maybe_space { - $$ = $1; - } + | function maybe_space + | calc_function maybe_space + | variable_function maybe_space + | min_or_max_function maybe_space | '%' maybe_space { /* Handle width: %; */ $$.id = CSSValueInvalid; $$.unit = 0; } +#if ENABLE_CSS_GRID_LAYOUT + | track_names_list maybe_space +#endif ; unary_term: @@ -1741,7 +1740,7 @@ unary_term: $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_REMS; if (parser->m_styleSheet) - parser->m_styleSheet->parserSetUsesRemUnits(true); + parser->m_styleSheet->parserSetUsesRemUnits(); } | CHS { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CHS; } | VW { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_VW; } @@ -1751,28 +1750,28 @@ unary_term: | DPPX { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPPX; } | DPI { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPI; } | DPCM { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DPCM; } + | FR { $$.id = CSSValueInvalid; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_FR; } ; function: FUNCTION maybe_space expr closing_parenthesis { - CSSParserFunction* f = parser->createFloatingFunction(); + CSSParserFunction* f = new CSSParserFunction; f->name = $1; - f->args = parser->sinkFloatingValueList($3); + f->args = std::unique_ptr<CSSParserValueList>($3); $$.id = CSSValueInvalid; $$.unit = CSSParserValue::Function; $$.function = f; } | FUNCTION maybe_space closing_parenthesis { - CSSParserFunction* f = parser->createFloatingFunction(); + CSSParserFunction* f = new CSSParserFunction; f->name = $1; - CSSParserValueList* valueList = parser->createFloatingValueList(); - f->args = parser->sinkFloatingValueList(valueList); + f->args = std::unique_ptr<CSSParserValueList>(new CSSParserValueList); $$.id = CSSValueInvalid; $$.unit = CSSParserValue::Function; $$.function = f; } | FUNCTION maybe_space expr_recovery closing_parenthesis { - CSSParserFunction* f = parser->createFloatingFunction(); + CSSParserFunction* f = new CSSParserFunction; f->name = $1; f->args = nullptr; $$.id = CSSValueInvalid; @@ -1781,23 +1780,79 @@ function: } ; +variable_function: + VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space closing_parenthesis { + CSSParserVariable* var = new CSSParserVariable; + var->name = $3; + var->args = nullptr; + $$.id = CSSValueInvalid; + $$.unit = CSSParserValue::Variable; + $$.variable = var; + } + | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space expr closing_parenthesis { + CSSParserVariable* var = new CSSParserVariable; + var->name = $3; + var->args = std::unique_ptr<CSSParserValueList>($7); + $$.id = CSSValueInvalid; + $$.unit = CSSParserValue::Variable; + $$.variable = var; + } + | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space closing_parenthesis { + CSSParserVariable* var = new CSSParserVariable; + var->name = $3; + var->args = std::unique_ptr<CSSParserValueList>(new CSSParserValueList()); + $$.id = CSSValueInvalid; + $$.unit = CSSParserValue::Variable; + $$.variable = var; + } + // Error handling cases + | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; + YYERROR; + } + | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space invalid_var_fallback maybe_space closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; + YYERROR; + } + | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space priority closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; + YYERROR; + } + | VARFUNCTION maybe_space expr closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; + delete $3; + YYERROR; + } + | VARFUNCTION maybe_space expr_recovery closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; + YYERROR; + } + ; + +invalid_var_fallback: + '!' | ';'; + calc_func_term: - unary_term { $$ = $1; } - | VARFUNCTION maybe_space IDENT closing_parenthesis { -#if ENABLE_CSS_VARIABLES - $$.id = CSSValueInvalid; - $$.string = $3; - $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME; -#endif - } + unary_term + | variable_function { $$ = $1; } | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } ; +/* + * The grammar requires spaces around binary ‘+’ and ‘-’ operators. + * The '*' and '/' operators do not require spaces. + * http://www.w3.org/TR/css3-values/#calc-syntax + */ calc_func_operator: - WHITESPACE '+' WHITESPACE { + space '+' space { $$ = '+'; } - | WHITESPACE '-' WHITESPACE { + | space '-' space { $$ = '-'; } | calc_maybe_space '*' maybe_space { @@ -1808,13 +1863,11 @@ calc_func_operator: } ; -calc_maybe_space: - /* empty */ - | WHITESPACE - ; +calc_maybe_space: /* empty */ | WHITESPACE ; calc_func_paren_expr: '(' maybe_space calc_func_expr calc_maybe_space closing_parenthesis { + $$ = nullptr; if ($3) { $$ = $3; CSSParserValue v; @@ -1824,168 +1877,128 @@ calc_func_paren_expr: $$->insertValueAt(0, v); v.iValue = ')'; $$->addValue(v); - } else - $$ = 0; + } } ; -calc_func_expr: - valid_calc_func_expr - | valid_calc_func_expr expr_recovery { $$ = 0; } - ; +calc_func_expr: valid_calc_func_expr | valid_calc_func_expr expr_recovery { $$ = nullptr; delete $1; } ; valid_calc_func_expr: calc_func_term { - $$ = parser->createFloatingValueList(); - $$->addValue(parser->sinkFloatingValue($1)); + $$ = new CSSParserValueList; + $$->addValue($1); } | calc_func_expr calc_func_operator calc_func_term { - if ($1 && $2) { - $$ = $1; + std::unique_ptr<CSSParserValueList> expression($1); + $$ = nullptr; + if (expression && $2) { + $$ = expression.release(); CSSParserValue v; v.id = CSSValueInvalid; v.unit = CSSParserValue::Operator; v.iValue = $2; $$->addValue(v); - $$->addValue(parser->sinkFloatingValue($3)); - } else - $$ = 0; + $$->addValue($3); + } else { + destroy($3); + } } | calc_func_expr calc_func_operator calc_func_paren_expr { - if ($1 && $2 && $3) { - $$ = $1; + std::unique_ptr<CSSParserValueList> left($1); + std::unique_ptr<CSSParserValueList> right($3); + $$ = nullptr; + if (left && $2 && right) { CSSParserValue v; v.id = CSSValueInvalid; v.unit = CSSParserValue::Operator; v.iValue = $2; - $$->addValue(v); - $$->extend(*($3)); - } else - $$ = 0; + left->addValue(v); + left->extend(*right); + $$ = left.release(); + } } | calc_func_paren_expr ; calc_func_expr_list: - calc_func_expr calc_maybe_space { - $$ = $1; - } + calc_func_expr calc_maybe_space | calc_func_expr_list ',' maybe_space calc_func_expr calc_maybe_space { - if ($1 && $4) { - $$ = $1; + std::unique_ptr<CSSParserValueList> list($1); + std::unique_ptr<CSSParserValueList> expression($4); + $$ = nullptr; + if (list && expression) { + $$ = list.release(); CSSParserValue v; v.id = CSSValueInvalid; v.unit = CSSParserValue::Operator; v.iValue = ','; $$->addValue(v); - $$->extend(*($4)); - } else - $$ = 0; + $$->extend(*expression); + } } ; calc_function: CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis { - CSSParserFunction* f = parser->createFloatingFunction(); + CSSParserFunction* f = new CSSParserFunction; f->name = $1; - f->args = parser->sinkFloatingValueList($3); + f->args = std::unique_ptr<CSSParserValueList>($3); $$.id = CSSValueInvalid; $$.unit = CSSParserValue::Function; $$.function = f; } | CALCFUNCTION maybe_space expr_recovery closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; YYERROR; } ; -min_or_max: - MINFUNCTION { - $$ = $1; - } - | MAXFUNCTION { - $$ = $1; - } - ; +min_or_max: MINFUNCTION | MAXFUNCTION ; min_or_max_function: min_or_max maybe_space calc_func_expr_list closing_parenthesis { - CSSParserFunction* f = parser->createFloatingFunction(); + CSSParserFunction* f = new CSSParserFunction; f->name = $1; - f->args = parser->sinkFloatingValueList($3); + f->args = std::unique_ptr<CSSParserValueList>($3); $$.id = CSSValueInvalid; $$.unit = CSSParserValue::Function; $$.function = f; - } + } | min_or_max maybe_space expr_recovery closing_parenthesis { + $$.id = CSSValueInvalid; + $$.unit = 0; YYERROR; } ; /* error handling rules */ -save_block: - closing_brace { - $$ = 0; - } - | error closing_brace { - $$ = 0; - } - ; - -invalid_at: - ATKEYWORD error invalid_block { - $$ = 0; - } - | ATKEYWORD error ';' { - $$ = 0; - } - ; - -invalid_rule: - error invalid_block { - $$ = 0; - } +save_block: closing_brace | error closing_brace ; -/* - Seems like the two rules below are trying too much and violating - http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html +invalid_at: ATKEYWORD error invalid_block | ATKEYWORD error ';' ; - | error ';' { - $$ = 0; - } - | error '}' { - $$ = 0; - } -*/ - ; +invalid_rule: error invalid_block ; -invalid_block: - '{' error_recovery closing_brace { - parser->invalidBlockHit(); - } - ; +invalid_block: '{' error_recovery closing_brace { parser->invalidBlockHit(); } ; -invalid_square_brackets_block: - '[' error_recovery ']' - | '[' error_recovery TOKEN_EOF - ; +invalid_square_brackets_block: '[' error_recovery closing_bracket ; -invalid_parentheses_block: - opening_parenthesis error_recovery closing_parenthesis; +invalid_parentheses_block: opening_parenthesis error_recovery closing_parenthesis; opening_parenthesis: - '(' | FUNCTION | CALCFUNCTION | VARFUNCTION | MINFUNCTION | MAXFUNCTION | ANYFUNCTION | NOTFUNCTION + '(' | FUNCTION | VARFUNCTION | CALCFUNCTION | MATCHESFUNCTION | MAXFUNCTION | MINFUNCTION | ANYFUNCTION | NOTFUNCTION | LANGFUNCTION +#if ENABLE_CSS_SELECTORS_LEVEL4 + | DIRFUNCTION | ROLEFUNCTION +#endif #if ENABLE_VIDEO_TRACK | CUEFUNCTION #endif ; -error_location: { - $$ = parser->currentLocation(); - } - ; +error_location: { $$ = parser->currentLocation(); } ; error_recovery: /* empty */ @@ -1996,4 +2009,3 @@ error_recovery: ; %% - |