mirror of
				https://github.com/LadybirdBrowser/ladybird.git
				synced 2025-10-25 01:19:45 +00:00 
			
		
		
		
	Functionally this is the same before, as result is always True or False before this point, and `True && Foo` evaluates to `Foo`. But this is more clearly correct, instead of correct by coincidence.
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/NonnullOwnPtr.h>
 | |
| #include <AK/String.h>
 | |
| #include <AK/Vector.h>
 | |
| #include <LibWeb/Forward.h>
 | |
| 
 | |
| namespace Web::CSS {
 | |
| 
 | |
| // Corresponds to Kleene 3-valued logic.
 | |
| enum class MatchResult : u8 {
 | |
|     False,
 | |
|     True,
 | |
|     Unknown,
 | |
| };
 | |
| 
 | |
| constexpr MatchResult operator&&(MatchResult const a, MatchResult const b)
 | |
| {
 | |
|     // If either is false, false.
 | |
|     if (a == MatchResult::False || b == MatchResult::False)
 | |
|         return MatchResult::False;
 | |
|     // If both are true, true.
 | |
|     if (a == MatchResult::True && b == MatchResult::True)
 | |
|         return MatchResult::True;
 | |
|     // Otherwise, unknown.
 | |
|     return MatchResult::Unknown;
 | |
| }
 | |
| 
 | |
| constexpr MatchResult operator||(MatchResult const a, MatchResult const b)
 | |
| {
 | |
|     // If either is true, true.
 | |
|     if (a == MatchResult::True || b == MatchResult::True)
 | |
|         return MatchResult::True;
 | |
|     // If both are false, false.
 | |
|     if (a == MatchResult::False && b == MatchResult::False)
 | |
|         return MatchResult::False;
 | |
|     // Otherwise, unknown.
 | |
|     return MatchResult::Unknown;
 | |
| }
 | |
| 
 | |
| constexpr MatchResult as_match_result(bool value)
 | |
| {
 | |
|     return value ? MatchResult::True : MatchResult::False;
 | |
| }
 | |
| 
 | |
| constexpr MatchResult negate(MatchResult value)
 | |
| {
 | |
|     switch (value) {
 | |
|     case MatchResult::False:
 | |
|         return MatchResult::True;
 | |
|     case MatchResult::True:
 | |
|         return MatchResult::False;
 | |
|     case MatchResult::Unknown:
 | |
|         return MatchResult::Unknown;
 | |
|     }
 | |
|     VERIFY_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| constexpr StringView to_string(MatchResult result)
 | |
| {
 | |
|     switch (result) {
 | |
|     case MatchResult::False:
 | |
|         return "false"sv;
 | |
|     case MatchResult::True:
 | |
|         return "true"sv;
 | |
|     case MatchResult::Unknown:
 | |
|         return "unknown"sv;
 | |
|     }
 | |
|     VERIFY_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| // The contents of this file implement the `<boolean-expr>` concept.
 | |
| // https://drafts.csswg.org/css-values-5/#typedef-boolean-expr
 | |
| class BooleanExpression {
 | |
| public:
 | |
|     virtual ~BooleanExpression() = default;
 | |
| 
 | |
|     bool evaluate_to_boolean(HTML::Window const*) const;
 | |
|     static void indent(StringBuilder& builder, int levels);
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const = 0;
 | |
|     virtual String to_string() const = 0;
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const = 0;
 | |
| };
 | |
| 
 | |
| // https://www.w3.org/TR/mediaqueries-4/#typedef-general-enclosed
 | |
| class GeneralEnclosed final : public BooleanExpression {
 | |
| public:
 | |
|     static NonnullOwnPtr<GeneralEnclosed> create(String serialized_contents, MatchResult matches = MatchResult::Unknown)
 | |
|     {
 | |
|         return adopt_own(*new GeneralEnclosed(move(serialized_contents), matches));
 | |
|     }
 | |
|     virtual ~GeneralEnclosed() override = default;
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const override { return m_matches; }
 | |
|     virtual String to_string() const override { return m_serialized_contents; }
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const override;
 | |
| 
 | |
| private:
 | |
|     GeneralEnclosed(String serialized_contents, MatchResult matches)
 | |
|         : m_serialized_contents(move(serialized_contents))
 | |
|         , m_matches(matches)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     String m_serialized_contents;
 | |
|     MatchResult m_matches;
 | |
| };
 | |
| 
 | |
| class BooleanNotExpression final : public BooleanExpression {
 | |
| public:
 | |
|     static NonnullOwnPtr<BooleanNotExpression> create(NonnullOwnPtr<BooleanExpression>&& child)
 | |
|     {
 | |
|         return adopt_own(*new BooleanNotExpression(move(child)));
 | |
|     }
 | |
|     virtual ~BooleanNotExpression() override = default;
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const override;
 | |
|     virtual String to_string() const override;
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const override;
 | |
| 
 | |
| private:
 | |
|     BooleanNotExpression(NonnullOwnPtr<BooleanExpression>&& child)
 | |
|         : m_child(move(child))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     NonnullOwnPtr<BooleanExpression> m_child;
 | |
| };
 | |
| 
 | |
| class BooleanExpressionInParens final : public BooleanExpression {
 | |
| public:
 | |
|     static NonnullOwnPtr<BooleanExpressionInParens> create(NonnullOwnPtr<BooleanExpression>&& child)
 | |
|     {
 | |
|         return adopt_own(*new BooleanExpressionInParens(move(child)));
 | |
|     }
 | |
|     virtual ~BooleanExpressionInParens() override = default;
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const override;
 | |
|     virtual String to_string() const override;
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const override;
 | |
| 
 | |
| private:
 | |
|     BooleanExpressionInParens(NonnullOwnPtr<BooleanExpression>&& child)
 | |
|         : m_child(move(child))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     NonnullOwnPtr<BooleanExpression> m_child;
 | |
| };
 | |
| 
 | |
| class BooleanAndExpression final : public BooleanExpression {
 | |
| public:
 | |
|     static NonnullOwnPtr<BooleanAndExpression> create(Vector<NonnullOwnPtr<BooleanExpression>>&& children)
 | |
|     {
 | |
|         return adopt_own(*new BooleanAndExpression(move(children)));
 | |
|     }
 | |
|     virtual ~BooleanAndExpression() override = default;
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const override;
 | |
|     virtual String to_string() const override;
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const override;
 | |
| 
 | |
| private:
 | |
|     BooleanAndExpression(Vector<NonnullOwnPtr<BooleanExpression>>&& children)
 | |
|         : m_children(move(children))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Vector<NonnullOwnPtr<BooleanExpression>> m_children;
 | |
| };
 | |
| 
 | |
| class BooleanOrExpression final : public BooleanExpression {
 | |
| public:
 | |
|     static NonnullOwnPtr<BooleanOrExpression> create(Vector<NonnullOwnPtr<BooleanExpression>>&& children)
 | |
|     {
 | |
|         return adopt_own(*new BooleanOrExpression(move(children)));
 | |
|     }
 | |
|     virtual ~BooleanOrExpression() override = default;
 | |
| 
 | |
|     virtual MatchResult evaluate(HTML::Window const*) const override;
 | |
|     virtual String to_string() const override;
 | |
|     virtual void dump(StringBuilder&, int indent_levels = 0) const override;
 | |
| 
 | |
| private:
 | |
|     BooleanOrExpression(Vector<NonnullOwnPtr<BooleanExpression>>&& children)
 | |
|         : m_children(move(children))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Vector<NonnullOwnPtr<BooleanExpression>> m_children;
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| template<>
 | |
| struct AK::Formatter<Web::CSS::BooleanExpression> : AK::Formatter<StringView> {
 | |
|     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::BooleanExpression const& expression)
 | |
|     {
 | |
|         return Formatter<StringView>::format(builder, expression.to_string());
 | |
|     }
 | |
| };
 |