1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 20:57:41 +00:00

LibWeb: Combine identical relative/regular selector parsing functions

This commit is contained in:
Sam Atkins 2022-03-17 19:29:40 +00:00 committed by Andreas Kling
parent 5b0187477b
commit 174a25db5b
2 changed files with 18 additions and 37 deletions

View file

@ -181,7 +181,7 @@ NonnullRefPtr<CSSStyleSheet> Parser::parse_a_stylesheet(TokenStream<T>& tokens)
Optional<SelectorList> Parser::parse_as_selector(SelectorParsingMode parsing_mode) Optional<SelectorList> Parser::parse_as_selector(SelectorParsingMode parsing_mode)
{ {
auto selector_list = parse_a_selector_list(m_token_stream, parsing_mode); auto selector_list = parse_a_selector_list(m_token_stream, SelectorType::Standalone, parsing_mode);
if (!selector_list.is_error()) if (!selector_list.is_error())
return selector_list.release_value(); return selector_list.release_value();
@ -190,7 +190,7 @@ Optional<SelectorList> Parser::parse_as_selector(SelectorParsingMode parsing_mod
Optional<SelectorList> Parser::parse_as_relative_selector(SelectorParsingMode parsing_mode) Optional<SelectorList> Parser::parse_as_relative_selector(SelectorParsingMode parsing_mode)
{ {
auto selector_list = parse_a_relative_selector_list(m_token_stream, parsing_mode); auto selector_list = parse_a_selector_list(m_token_stream, SelectorType::Relative, parsing_mode);
if (!selector_list.is_error()) if (!selector_list.is_error())
return selector_list.release_value(); return selector_list.release_value();
@ -198,14 +198,14 @@ Optional<SelectorList> Parser::parse_as_relative_selector(SelectorParsingMode pa
} }
template<typename T> template<typename T>
Result<SelectorList, Parser::ParsingResult> Parser::parse_a_selector_list(TokenStream<T>& tokens, SelectorParsingMode parsing_mode) Result<SelectorList, Parser::ParsingResult> Parser::parse_a_selector_list(TokenStream<T>& tokens, SelectorType mode, SelectorParsingMode parsing_mode)
{ {
auto comma_separated_lists = parse_a_comma_separated_list_of_component_values(tokens); auto comma_separated_lists = parse_a_comma_separated_list_of_component_values(tokens);
NonnullRefPtrVector<Selector> selectors; NonnullRefPtrVector<Selector> selectors;
for (auto& selector_parts : comma_separated_lists) { for (auto& selector_parts : comma_separated_lists) {
auto stream = TokenStream(selector_parts); auto stream = TokenStream(selector_parts);
auto selector = parse_complex_selector(stream, false); auto selector = parse_complex_selector(stream, mode);
if (selector.is_error()) { if (selector.is_error()) {
if (parsing_mode == SelectorParsingMode::Forgiving) if (parsing_mode == SelectorParsingMode::Forgiving)
continue; continue;
@ -220,37 +220,14 @@ Result<SelectorList, Parser::ParsingResult> Parser::parse_a_selector_list(TokenS
return selectors; return selectors;
} }
template<typename T> Result<NonnullRefPtr<Selector>, Parser::ParsingResult> Parser::parse_complex_selector(TokenStream<StyleComponentValueRule>& tokens, SelectorType mode)
Result<SelectorList, Parser::ParsingResult> Parser::parse_a_relative_selector_list(TokenStream<T>& tokens, SelectorParsingMode parsing_mode)
{
auto comma_separated_lists = parse_a_comma_separated_list_of_component_values(tokens);
NonnullRefPtrVector<Selector> selectors;
for (auto& selector_parts : comma_separated_lists) {
auto stream = TokenStream(selector_parts);
auto selector = parse_complex_selector(stream, true);
if (selector.is_error()) {
if (parsing_mode == SelectorParsingMode::Forgiving)
continue;
return selector.error();
}
selectors.append(selector.release_value());
}
if (selectors.is_empty() && parsing_mode != SelectorParsingMode::Forgiving)
return ParsingResult::SyntaxError;
return selectors;
}
Result<NonnullRefPtr<Selector>, Parser::ParsingResult> Parser::parse_complex_selector(TokenStream<StyleComponentValueRule>& tokens, bool allow_starting_combinator)
{ {
Vector<Selector::CompoundSelector> compound_selectors; Vector<Selector::CompoundSelector> compound_selectors;
auto first_selector = parse_compound_selector(tokens); auto first_selector = parse_compound_selector(tokens);
if (first_selector.is_error()) if (first_selector.is_error())
return first_selector.error(); return first_selector.error();
if (!allow_starting_combinator) { if (mode == SelectorType::Standalone) {
if (first_selector.value().combinator != Selector::Combinator::Descendant) if (first_selector.value().combinator != Selector::Combinator::Descendant)
return ParsingResult::SyntaxError; return ParsingResult::SyntaxError;
first_selector.value().combinator = Selector::Combinator::None; first_selector.value().combinator = Selector::Combinator::None;
@ -593,7 +570,7 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel
return false; return false;
function_values.skip_whitespace(); function_values.skip_whitespace();
auto selector_list = parse_a_selector_list(function_values); auto selector_list = parse_a_selector_list(function_values, SelectorType::Standalone);
if (selector_list.is_error()) if (selector_list.is_error())
return false; return false;
@ -613,14 +590,14 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel
? Selector::SimpleSelector::PseudoClass::Type::Is ? Selector::SimpleSelector::PseudoClass::Type::Is
: Selector::SimpleSelector::PseudoClass::Type::Where; : Selector::SimpleSelector::PseudoClass::Type::Where;
auto function_token_stream = TokenStream(pseudo_function.values()); auto function_token_stream = TokenStream(pseudo_function.values());
auto argument_selector_list = parse_a_selector_list(function_token_stream, SelectorParsingMode::Forgiving); auto argument_selector_list = parse_a_selector_list(function_token_stream, SelectorType::Standalone, SelectorParsingMode::Forgiving);
// NOTE: Because it's forgiving, even complete garbage will parse OK as an empty selector-list. // NOTE: Because it's forgiving, even complete garbage will parse OK as an empty selector-list.
VERIFY(!argument_selector_list.is_error()); VERIFY(!argument_selector_list.is_error());
simple_selector.pseudo_class.argument_selector_list = argument_selector_list.release_value(); simple_selector.pseudo_class.argument_selector_list = argument_selector_list.release_value();
} else if (pseudo_function.name().equals_ignoring_case("not"sv)) { } else if (pseudo_function.name().equals_ignoring_case("not"sv)) {
simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Not; simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Not;
auto function_token_stream = TokenStream(pseudo_function.values()); auto function_token_stream = TokenStream(pseudo_function.values());
auto not_selector = parse_a_selector_list(function_token_stream); auto not_selector = parse_a_selector_list(function_token_stream, SelectorType::Standalone);
if (not_selector.is_error()) { if (not_selector.is_error()) {
dbgln_if(CSS_PARSER_DEBUG, "Invalid selector in :not() clause"); dbgln_if(CSS_PARSER_DEBUG, "Invalid selector in :not() clause");
return ParsingResult::SyntaxError; return ParsingResult::SyntaxError;
@ -2114,7 +2091,7 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<StyleRule> rule)
} else { } else {
auto prelude_stream = TokenStream(rule->m_prelude); auto prelude_stream = TokenStream(rule->m_prelude);
auto selectors = parse_a_selector_list(prelude_stream); auto selectors = parse_a_selector_list(prelude_stream, SelectorType::Standalone);
if (selectors.is_error()) { if (selectors.is_error()) {
if (selectors.error() != ParsingResult::IncludesIgnoredVendorPrefix) { if (selectors.error() != ParsingResult::IncludesIgnoredVendorPrefix) {

View file

@ -148,10 +148,14 @@ private:
Vector<StyleComponentValueRule> parse_a_list_of_component_values(TokenStream<T>&); Vector<StyleComponentValueRule> parse_a_list_of_component_values(TokenStream<T>&);
template<typename T> template<typename T>
Vector<Vector<StyleComponentValueRule>> parse_a_comma_separated_list_of_component_values(TokenStream<T>&); Vector<Vector<StyleComponentValueRule>> parse_a_comma_separated_list_of_component_values(TokenStream<T>&);
enum class SelectorType {
Standalone,
Relative
};
template<typename T> template<typename T>
Result<SelectorList, ParsingResult> parse_a_selector_list(TokenStream<T>&, SelectorParsingMode = SelectorParsingMode::Standard); Result<SelectorList, ParsingResult> parse_a_selector_list(TokenStream<T>&, SelectorType, SelectorParsingMode = SelectorParsingMode::Standard);
template<typename T>
Result<SelectorList, ParsingResult> parse_a_relative_selector_list(TokenStream<T>&, SelectorParsingMode = SelectorParsingMode::Standard);
template<typename T> template<typename T>
NonnullRefPtrVector<MediaQuery> parse_a_media_query_list(TokenStream<T>&); NonnullRefPtrVector<MediaQuery> parse_a_media_query_list(TokenStream<T>&);
template<typename T> template<typename T>
@ -308,7 +312,7 @@ private:
OwnPtr<CalculatedStyleValue::CalcNumberSumPartWithOperator> parse_calc_number_sum_part_with_operator(TokenStream<StyleComponentValueRule>&); OwnPtr<CalculatedStyleValue::CalcNumberSumPartWithOperator> parse_calc_number_sum_part_with_operator(TokenStream<StyleComponentValueRule>&);
OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_expression(Vector<StyleComponentValueRule> const&); OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_expression(Vector<StyleComponentValueRule> const&);
Result<NonnullRefPtr<Selector>, ParsingResult> parse_complex_selector(TokenStream<StyleComponentValueRule>&, bool allow_starting_combinator); Result<NonnullRefPtr<Selector>, ParsingResult> parse_complex_selector(TokenStream<StyleComponentValueRule>&, SelectorType);
Result<Selector::CompoundSelector, ParsingResult> parse_compound_selector(TokenStream<StyleComponentValueRule>&); Result<Selector::CompoundSelector, ParsingResult> parse_compound_selector(TokenStream<StyleComponentValueRule>&);
Optional<Selector::Combinator> parse_selector_combinator(TokenStream<StyleComponentValueRule>&); Optional<Selector::Combinator> parse_selector_combinator(TokenStream<StyleComponentValueRule>&);
Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&); Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&);