diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2022-04-27 11:04:16 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-29 00:07:31 +0200 |
commit | d784a8aaf0b50ba6443231dc33ef4f3a76369b6c (patch) | |
tree | 5ecd487559295a43a0c6c34718fc6bc7ff92292f /Userland/Libraries/LibWeb | |
parent | 761d29d64713ff10e8620c6e18f205e863f91a02 (diff) | |
download | serenity-d784a8aaf0b50ba6443231dc33ef4f3a76369b6c.zip |
LibWeb: Replace Result with ErrorOr in CSS Parser
...using a ParseErrorOr type alias.
This lets us replace a bunch of manual error-checking with TRY. :^)
I also replaced the ParsingResult::Done value with returning an
Optional. I wasn't happy with treating "Done" as an error when I first
wrote this, and this makes a clear distinction between the two.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 203 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 21 |
2 files changed, 105 insertions, 119 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index ee35d62bf5..ce6d3001fc 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -220,7 +220,7 @@ Optional<SelectorList> Parser::parse_as_relative_selector(SelectorParsingMode pa } template<typename T> -Result<SelectorList, Parser::ParsingResult> Parser::parse_a_selector_list(TokenStream<T>& tokens, SelectorType mode, SelectorParsingMode parsing_mode) +Parser::ParseErrorOr<SelectorList> 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); @@ -237,43 +237,40 @@ Result<SelectorList, Parser::ParsingResult> Parser::parse_a_selector_list(TokenS } if (selectors.is_empty() && parsing_mode != SelectorParsingMode::Forgiving) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; return selectors; } -Result<NonnullRefPtr<Selector>, Parser::ParsingResult> Parser::parse_complex_selector(TokenStream<ComponentValue>& tokens, SelectorType mode) +Parser::ParseErrorOr<NonnullRefPtr<Selector>> Parser::parse_complex_selector(TokenStream<ComponentValue>& tokens, SelectorType mode) { Vector<Selector::CompoundSelector> compound_selectors; - auto first_selector = parse_compound_selector(tokens); - if (first_selector.is_error()) - return first_selector.error(); + auto first_selector = TRY(parse_compound_selector(tokens)); + if (!first_selector.has_value()) + return ParseError::SyntaxError; + if (mode == SelectorType::Standalone) { - if (first_selector.value().combinator != Selector::Combinator::Descendant) - return ParsingResult::SyntaxError; - first_selector.value().combinator = Selector::Combinator::None; + if (first_selector->combinator != Selector::Combinator::Descendant) + return ParseError::SyntaxError; + first_selector->combinator = Selector::Combinator::None; } - compound_selectors.append(first_selector.value()); + compound_selectors.append(first_selector.release_value()); while (tokens.has_next_token()) { - auto compound_selector = parse_compound_selector(tokens); - if (compound_selector.is_error()) { - if (compound_selector.error() == ParsingResult::Done) - break; - - return compound_selector.error(); - } - compound_selectors.append(compound_selector.value()); + auto compound_selector = TRY(parse_compound_selector(tokens)); + if (!compound_selector.has_value()) + break; + compound_selectors.append(compound_selector.release_value()); } if (compound_selectors.is_empty()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; return Selector::create(move(compound_selectors)); } -Result<Selector::CompoundSelector, Parser::ParsingResult> Parser::parse_compound_selector(TokenStream<ComponentValue>& tokens) +Parser::ParseErrorOr<Optional<Selector::CompoundSelector>> Parser::parse_compound_selector(TokenStream<ComponentValue>& tokens) { tokens.skip_whitespace(); @@ -284,19 +281,14 @@ Result<Selector::CompoundSelector, Parser::ParsingResult> Parser::parse_compound Vector<Selector::SimpleSelector> simple_selectors; while (tokens.has_next_token()) { - auto component = parse_simple_selector(tokens); - if (component.is_error()) { - if (component.error() == ParsingResult::Done) - break; - - return component.error(); - } - - simple_selectors.append(component.value()); + auto component = TRY(parse_simple_selector(tokens)); + if (!component.has_value()) + break; + simple_selectors.append(component.release_value()); } if (simple_selectors.is_empty()) - return ParsingResult::Done; + return Optional<Selector::CompoundSelector> {}; return Selector::CompoundSelector { combinator, move(simple_selectors) }; } @@ -329,7 +321,7 @@ Optional<Selector::Combinator> Parser::parse_selector_combinator(TokenStream<Com return {}; } -Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_simple_selector(ComponentValue const& first_value) +Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_attribute_simple_selector(ComponentValue const& first_value) { auto attribute_tokens = TokenStream { first_value.block().values() }; @@ -337,14 +329,14 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_ if (!attribute_tokens.has_next_token()) { dbgln_if(CSS_PARSER_DEBUG, "CSS attribute selector is empty!"); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } // FIXME: Handle namespace prefix for attribute name. auto const& attribute_part = attribute_tokens.next_token(); if (!attribute_part.is(Token::Type::Ident)) { dbgln_if(CSS_PARSER_DEBUG, "Expected ident for attribute name, got: '{}'", attribute_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } Selector::SimpleSelector simple_selector { @@ -368,7 +360,7 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_ auto const& delim_part = attribute_tokens.next_token(); if (!delim_part.is(Token::Type::Delim)) { dbgln_if(CSS_PARSER_DEBUG, "Expected a delim for attribute comparison, got: '{}'", delim_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } if (delim_part.token().delim() == '=') { @@ -376,13 +368,13 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_ } else { if (!attribute_tokens.has_next_token()) { dbgln_if(CSS_PARSER_DEBUG, "Attribute selector ended part way through a match type."); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } auto const& delim_second_part = attribute_tokens.next_token(); if (!(delim_second_part.is(Token::Type::Delim) && delim_second_part.token().delim() == '=')) { dbgln_if(CSS_PARSER_DEBUG, "Expected a double delim for attribute comparison, got: '{}{}'", delim_part.to_debug_string(), delim_second_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } switch (delim_part.token().delim()) { case '~': @@ -408,13 +400,13 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_ attribute_tokens.skip_whitespace(); if (!attribute_tokens.has_next_token()) { dbgln_if(CSS_PARSER_DEBUG, "Attribute selector ended without a value to match."); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } auto const& value_part = attribute_tokens.next_token(); if (!value_part.is(Token::Type::Ident) && !value_part.is(Token::Type::String)) { dbgln_if(CSS_PARSER_DEBUG, "Expected a string or ident for the value to match attribute against, got: '{}'", value_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } simple_selector.attribute().value = value_part.token().is(Token::Type::Ident) ? value_part.token().ident() : value_part.token().string(); @@ -430,23 +422,23 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_attribute_ simple_selector.attribute().case_type = Selector::SimpleSelector::Attribute::CaseType::CaseSensitiveMatch; } else { dbgln_if(CSS_PARSER_DEBUG, "Expected a \"i\" or \"s\" attribute selector case sensitivity identifier, got: '{}'", case_sensitivity_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } } else { dbgln_if(CSS_PARSER_DEBUG, "Expected an attribute selector case sensitivity identifier, got: '{}'", case_sensitivity_part.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } } if (attribute_tokens.has_next_token()) { dbgln_if(CSS_PARSER_DEBUG, "Was not expecting anything else inside attribute selector."); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } return simple_selector; } -Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_simple_selector(TokenStream<ComponentValue>& tokens) +Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selector(TokenStream<ComponentValue>& tokens) { auto peek_token_ends_selector = [&]() -> bool { auto const& value = tokens.peek_token(); @@ -454,31 +446,31 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim }; if (peek_token_ends_selector()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; bool is_pseudo = false; if (tokens.peek_token().is(Token::Type::Colon)) { is_pseudo = true; tokens.next_token(); if (peek_token_ends_selector()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } if (is_pseudo) { auto const& name_token = tokens.next_token(); if (!name_token.is(Token::Type::Ident)) { dbgln_if(CSS_PARSER_DEBUG, "Expected an ident for pseudo-element, got: '{}'", name_token.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } auto pseudo_name = name_token.token().ident(); if (has_ignored_vendor_prefix(pseudo_name)) - return ParsingResult::IncludesIgnoredVendorPrefix; + return ParseError::IncludesIgnoredVendorPrefix; auto pseudo_element = pseudo_element_from_string(pseudo_name); if (!pseudo_element.has_value()) { dbgln_if(CSS_PARSER_DEBUG, "Unrecognized pseudo-element: '::{}'", pseudo_name); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } return Selector::SimpleSelector { @@ -488,14 +480,14 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim } if (peek_token_ends_selector()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; auto const& pseudo_class_token = tokens.next_token(); if (pseudo_class_token.is(Token::Type::Ident)) { auto pseudo_name = pseudo_class_token.token().ident(); if (has_ignored_vendor_prefix(pseudo_name)) - return ParsingResult::IncludesIgnoredVendorPrefix; + return ParseError::IncludesIgnoredVendorPrefix; auto make_pseudo_class_selector = [](auto pseudo_class) { return Selector::SimpleSelector { @@ -559,16 +551,16 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim } dbgln_if(CSS_PARSER_DEBUG, "Unrecognized pseudo-class: ':{}'", pseudo_name); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } if (pseudo_class_token.is_function()) { - auto parse_nth_child_selector = [this](auto pseudo_class, Vector<ComponentValue> const& function_values, bool allow_of = false) -> Result<Selector::SimpleSelector, Parser::ParsingResult> { + auto parse_nth_child_selector = [this](auto pseudo_class, Vector<ComponentValue> const& function_values, bool allow_of = false) -> ParseErrorOr<Selector::SimpleSelector> { auto tokens = TokenStream<ComponentValue>(function_values); auto nth_child_pattern = parse_a_n_plus_b_pattern(tokens, allow_of ? AllowTrailingTokens::Yes : AllowTrailingTokens::No); if (!nth_child_pattern.has_value()) { dbgln_if(CSS_PARSER_DEBUG, "!!! Invalid An+B format for {}", pseudo_class_name(pseudo_class)); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } tokens.skip_whitespace(); @@ -584,23 +576,21 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim // Parse the `of <selector-list>` syntax auto const& maybe_of = tokens.next_token(); if (!(maybe_of.is(Token::Type::Ident) && maybe_of.token().ident().equals_ignoring_case("of"sv))) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; tokens.skip_whitespace(); - auto selector_list = parse_a_selector_list(tokens, SelectorType::Standalone); - if (selector_list.is_error()) - return ParsingResult::SyntaxError; + auto selector_list = TRY(parse_a_selector_list(tokens, SelectorType::Standalone)); tokens.skip_whitespace(); if (tokens.has_next_token()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::PseudoClass, .value = Selector::SimpleSelector::PseudoClass { .type = pseudo_class, .nth_child_pattern = nth_child_pattern.release_value(), - .argument_selector_list = selector_list.release_value() } + .argument_selector_list = move(selector_list) } }; }; @@ -608,9 +598,8 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim if (pseudo_function.name().equals_ignoring_case("is"sv) || pseudo_function.name().equals_ignoring_case("where"sv)) { auto function_token_stream = TokenStream(pseudo_function.values()); - 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. - VERIFY(!argument_selector_list.is_error()); + auto argument_selector_list = MUST(parse_a_selector_list(function_token_stream, SelectorType::Standalone, SelectorParsingMode::Forgiving)); return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::PseudoClass, @@ -618,26 +607,22 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim .type = pseudo_function.name().equals_ignoring_case("is"sv) ? Selector::SimpleSelector::PseudoClass::Type::Is : Selector::SimpleSelector::PseudoClass::Type::Where, - .argument_selector_list = argument_selector_list.release_value() } + .argument_selector_list = move(argument_selector_list) } }; } else if (pseudo_function.name().equals_ignoring_case("not")) { auto function_token_stream = TokenStream(pseudo_function.values()); - auto not_selector = parse_a_selector_list(function_token_stream, SelectorType::Standalone); - if (not_selector.is_error()) { - dbgln_if(CSS_PARSER_DEBUG, "Invalid selector in :not() clause"); - return ParsingResult::SyntaxError; - } + auto not_selector = TRY(parse_a_selector_list(function_token_stream, SelectorType::Standalone)); return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::PseudoClass, .value = Selector::SimpleSelector::PseudoClass { .type = Selector::SimpleSelector::PseudoClass::Type::Not, - .argument_selector_list = not_selector.release_value() } + .argument_selector_list = move(not_selector) } }; } else if (pseudo_function.name().equals_ignoring_case("lang"sv)) { if (pseudo_function.values().is_empty()) { dbgln_if(CSS_PARSER_DEBUG, "Empty :lang() selector"); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } // FIXME: Support multiple, comma-separated, language ranges. Vector<FlyString> languages; @@ -659,13 +644,13 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_pseudo_sim } dbgln_if(CSS_PARSER_DEBUG, "Unrecognized pseudo-class function: ':{}'()", pseudo_function.name()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } dbgln_if(CSS_PARSER_DEBUG, "Unexpected Block in pseudo-class name, expected a function or identifier. '{}'", pseudo_class_token.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } -Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_selector(TokenStream<ComponentValue>& tokens) +Parser::ParseErrorOr<Optional<Selector::SimpleSelector>> Parser::parse_simple_selector(TokenStream<ComponentValue>& tokens) { auto peek_token_ends_selector = [&]() -> bool { auto const& value = tokens.peek_token(); @@ -673,7 +658,7 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel }; if (peek_token_ends_selector()) - return ParsingResult::Done; + return Optional<Selector::SimpleSelector> {}; auto const& first_value = tokens.next_token(); @@ -686,12 +671,12 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel }; case '.': { if (peek_token_ends_selector()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; auto const& class_name_value = tokens.next_token(); if (!class_name_value.is(Token::Type::Ident)) { dbgln_if(CSS_PARSER_DEBUG, "Expected an ident after '.', got: {}", class_name_value.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::Class, @@ -705,17 +690,17 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel // Whitespace is not required between the compound-selector and a combinator. // So, if we see a combinator, return that this compound-selector is done, instead of a syntax error. tokens.reconsume_current_input_token(); - return ParsingResult::Done; + return Optional<Selector::SimpleSelector> {}; default: dbgln_if(CSS_PARSER_DEBUG, "!!! Invalid simple selector!"); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } } if (first_value.is(Token::Type::Hash)) { if (first_value.token().hash_type() != Token::HashType::Id) { dbgln_if(CSS_PARSER_DEBUG, "Selector contains hash token that is not an id: {}", first_value.to_debug_string()); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } return Selector::SimpleSelector { .type = Selector::SimpleSelector::Type::Id, @@ -729,13 +714,13 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel }; } if (first_value.is_block() && first_value.block().is_square()) - return parse_attribute_simple_selector(first_value); + return TRY(parse_attribute_simple_selector(first_value)); if (first_value.is(Token::Type::Colon)) - return parse_pseudo_simple_selector(tokens); + return TRY(parse_pseudo_simple_selector(tokens)); dbgln_if(CSS_PARSER_DEBUG, "!!! Invalid simple selector!"); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } NonnullRefPtrVector<MediaQuery> Parser::parse_as_media_query_list() @@ -2460,7 +2445,7 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<Rule> rule) auto selectors = parse_a_selector_list(prelude_stream, SelectorType::Standalone); if (selectors.is_error()) { - if (selectors.error() != ParsingResult::IncludesIgnoredVendorPrefix) { + if (selectors.error() != ParseError::IncludesIgnoredVendorPrefix) { dbgln_if(CSS_PARSER_DEBUG, "CSSParser: style rule selectors invalid; discarding."); if constexpr (CSS_PARSER_DEBUG) { prelude_stream.dump_all_tokens(); @@ -2540,7 +2525,7 @@ Optional<StyleProperty> Parser::convert_to_style_property(Declaration const& dec auto value_token_stream = TokenStream(declaration.values()); auto value = parse_css_value(property_id, value_token_stream); if (value.is_error()) { - if (value.error() != ParsingResult::IncludesIgnoredVendorPrefix) { + if (value.error() != ParseError::IncludesIgnoredVendorPrefix) { dbgln_if(CSS_PARSER_DEBUG, "Unable to parse value for CSS property '{}'.", property_name); if constexpr (CSS_PARSER_DEBUG) { value_token_stream.dump_all_tokens(); @@ -4989,7 +4974,7 @@ RefPtr<StyleValue> Parser::parse_as_css_value(PropertyID property_id) return parsed_value.release_value(); } -Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value(PropertyID property_id, TokenStream<ComponentValue>& tokens) +Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(PropertyID property_id, TokenStream<ComponentValue>& tokens) { auto block_contains_var_or_attr = [](Block const& block, auto&& recurse) -> bool { for (auto const& token : block.values()) { @@ -5018,7 +5003,7 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value continue; if (token.is(Token::Type::Ident) && has_ignored_vendor_prefix(token.token().ident())) - return ParsingResult::IncludesIgnoredVendorPrefix; + return ParseError::IncludesIgnoredVendorPrefix; } if (!contains_var_or_attr) { @@ -5035,7 +5020,7 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value return { UnresolvedStyleValue::create(move(component_values), contains_var_or_attr) }; if (component_values.is_empty()) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; if (component_values.size() == 1) { if (auto parsed_value = parse_builtin_value(component_values.first())) @@ -5047,26 +5032,26 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value case PropertyID::Background: if (auto parsed_value = parse_background_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BackgroundAttachment: case PropertyID::BackgroundClip: case PropertyID::BackgroundImage: case PropertyID::BackgroundOrigin: if (auto parsed_value = parse_simple_comma_separated_value_list(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BackgroundPosition: if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_position_value(tokens); })) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BackgroundRepeat: if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_repeat_value(tokens); })) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BackgroundSize: if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_size_value(tokens); })) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Border: case PropertyID::BorderBottom: case PropertyID::BorderLeft: @@ -5074,73 +5059,73 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value case PropertyID::BorderTop: if (auto parsed_value = parse_border_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BorderTopLeftRadius: case PropertyID::BorderTopRightRadius: case PropertyID::BorderBottomRightRadius: case PropertyID::BorderBottomLeftRadius: if (auto parsed_value = parse_border_radius_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BorderRadius: if (auto parsed_value = parse_border_radius_shorthand_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::BoxShadow: if (auto parsed_value = parse_shadow_value(component_values, AllowInsetKeyword::Yes)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Content: if (auto parsed_value = parse_content_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Flex: if (auto parsed_value = parse_flex_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::FlexFlow: if (auto parsed_value = parse_flex_flow_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Font: if (auto parsed_value = parse_font_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::FontFamily: if (auto parsed_value = parse_font_family_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::ListStyle: if (auto parsed_value = parse_list_style_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Overflow: if (auto parsed_value = parse_overflow_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::TextDecoration: if (auto parsed_value = parse_text_decoration_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::TextDecorationLine: { TokenStream tokens { component_values }; auto parsed_value = parse_text_decoration_line_value(tokens); if (parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } case PropertyID::TextShadow: if (auto parsed_value = parse_shadow_value(component_values, AllowInsetKeyword::No)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::Transform: if (auto parsed_value = parse_transform_value(component_values)) return parsed_value.release_nonnull(); - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; case PropertyID::TransformOrigin: if (auto parse_value = parse_transform_origin_value(component_values)) return parse_value.release_nonnull(); - return ParsingResult ::SyntaxError; + return ParseError ::SyntaxError; default: break; } @@ -5150,7 +5135,7 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value if (property_accepts_value(property_id, *parsed_value)) return parsed_value.release_nonnull(); } - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } // We have multiple values, so treat them as a StyleValueList. @@ -5159,14 +5144,14 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value for (auto& component_value : component_values) { auto parsed_value = parse_css_value(component_value); if (!parsed_value || !property_accepts_value(property_id, *parsed_value)) - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; parsed_values.append(parsed_value.release_nonnull()); } if (!parsed_values.is_empty() && parsed_values.size() <= property_maximum_value_count(property_id)) return { StyleValueList::create(move(parsed_values), StyleValueList::Separator::Space) }; } - return ParsingResult::SyntaxError; + return ParseError::SyntaxError; } RefPtr<StyleValue> Parser::parse_css_value(ComponentValue const& component_value) diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 7e6b2e511e..20b9d247f8 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -7,10 +7,10 @@ #pragma once +#include <AK/Error.h> #include <AK/NonnullOwnPtrVector.h> #include <AK/NonnullRefPtrVector.h> #include <AK/RefPtr.h> -#include <AK/Result.h> #include <AK/Vector.h> #include <LibWeb/CSS/CSSStyleDeclaration.h> #include <LibWeb/CSS/FontFace.h> @@ -112,11 +112,12 @@ public: static RefPtr<StyleValue> parse_css_value(Badge<StyleComputer>, ParsingContext const&, PropertyID, Vector<ComponentValue> const&); private: - enum class ParsingResult { - Done, + enum class ParseError { IncludesIgnoredVendorPrefix, SyntaxError, }; + template<typename T> + using ParseErrorOr = ErrorOr<T, ParseError>; // "Parse a stylesheet" is intended to be the normal parser entry point, for parsing stylesheets. struct ParsedStyleSheet { @@ -161,7 +162,7 @@ private: Relative }; template<typename T> - Result<SelectorList, ParsingResult> parse_a_selector_list(TokenStream<T>&, SelectorType, SelectorParsingMode = SelectorParsingMode::Standard); + ParseErrorOr<SelectorList> parse_a_selector_list(TokenStream<T>&, SelectorType, SelectorParsingMode = SelectorParsingMode::Standard); template<typename T> NonnullRefPtrVector<MediaQuery> parse_a_media_query_list(TokenStream<T>&); @@ -283,7 +284,7 @@ private: }; Optional<AK::URL> parse_url_function(ComponentValue const&, AllowedDataUrlType = AllowedDataUrlType::None); - Result<NonnullRefPtr<StyleValue>, ParsingResult> parse_css_value(PropertyID, TokenStream<ComponentValue>&); + ParseErrorOr<NonnullRefPtr<StyleValue>> parse_css_value(PropertyID, TokenStream<ComponentValue>&); RefPtr<StyleValue> parse_css_value(ComponentValue const&); RefPtr<StyleValue> parse_builtin_value(ComponentValue const&); RefPtr<StyleValue> parse_dynamic_value(ComponentValue const&); @@ -336,13 +337,13 @@ private: OwnPtr<CalculatedStyleValue::CalcNumberSumPartWithOperator> parse_calc_number_sum_part_with_operator(TokenStream<ComponentValue>&); OwnPtr<CalculatedStyleValue::CalcSum> parse_calc_expression(Vector<ComponentValue> const&); - Result<NonnullRefPtr<Selector>, ParsingResult> parse_complex_selector(TokenStream<ComponentValue>&, SelectorType); - Result<Selector::CompoundSelector, ParsingResult> parse_compound_selector(TokenStream<ComponentValue>&); + ParseErrorOr<NonnullRefPtr<Selector>> parse_complex_selector(TokenStream<ComponentValue>&, SelectorType); + ParseErrorOr<Optional<Selector::CompoundSelector>> parse_compound_selector(TokenStream<ComponentValue>&); Optional<Selector::Combinator> parse_selector_combinator(TokenStream<ComponentValue>&); - Result<Selector::SimpleSelector, ParsingResult> parse_attribute_simple_selector(ComponentValue const&); - Result<Selector::SimpleSelector, ParsingResult> parse_pseudo_simple_selector(TokenStream<ComponentValue>&); - Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<ComponentValue>&); + ParseErrorOr<Selector::SimpleSelector> parse_attribute_simple_selector(ComponentValue const&); + ParseErrorOr<Selector::SimpleSelector> parse_pseudo_simple_selector(TokenStream<ComponentValue>&); + ParseErrorOr<Optional<Selector::SimpleSelector>> parse_simple_selector(TokenStream<ComponentValue>&); NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<ComponentValue>&); OwnPtr<MediaCondition> parse_media_condition(TokenStream<ComponentValue>&, MediaCondition::AllowOr allow_or); |