Browse Source

LibHTML: Refactor the CSS parser into a class

Also added a parser function for standalone style declarations.
Andreas Kling 5 years ago
parent
commit
b2a0d20580
2 changed files with 95 additions and 47 deletions
  1. 94 47
      Libraries/LibHTML/Parser/CSSParser.cpp
  2. 1 0
      Libraries/LibHTML/Parser/CSSParser.h

+ 94 - 47
Libraries/LibHTML/Parser/CSSParser.cpp

@@ -37,53 +37,45 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& view)
     return StringStyleValue::create(string);
     return StringStyleValue::create(string);
 }
 }
 
 
-NonnullRefPtr<StyleSheet> parse_css(const String& css)
-{
-    NonnullRefPtrVector<StyleRule> rules;
-
-    enum class State {
-        Free,
-        InSelectorComponent,
-        InPropertyName,
-        InPropertyValue,
-    };
-
-    struct CurrentRule {
-        Vector<Selector> selectors;
-        Vector<StyleProperty> properties;
-    };
-
-    CurrentRule current_rule;
-    Vector<char> buffer;
-
-    int index = 0;
+class CSSParser {
+public:
+    CSSParser(const StringView& input)
+        : css(input)
+    {
+    }
 
 
-    auto peek = [&]() -> char {
+    char peek() const
+    {
         if (index < css.length())
         if (index < css.length())
             return css[index];
             return css[index];
         return 0;
         return 0;
-    };
+    }
 
 
-    auto consume_specific = [&](char ch) {
+    char consume_specific(char ch)
+    {
         ASSERT(peek() == ch);
         ASSERT(peek() == ch);
         ++index;
         ++index;
         return ch;
         return ch;
-    };
+    }
 
 
-    auto consume_one = [&]() -> char {
+    char consume_one()
+    {
         return css[index++];
         return css[index++];
     };
     };
 
 
-    auto consume_whitespace = [&] {
+    void consume_whitespace()
+    {
         while (isspace(peek()))
         while (isspace(peek()))
             ++index;
             ++index;
-    };
+    }
 
 
-    auto is_valid_selector_char = [](char ch) {
+    bool is_valid_selector_char(char ch) const
+    {
         return isalnum(ch) || ch == '-' || ch == '_';
         return isalnum(ch) || ch == '-' || ch == '_';
-    };
+    }
 
 
-    auto parse_selector = [&] {
+    void parse_selector()
+    {
         consume_whitespace();
         consume_whitespace();
         Selector::Component::Type type;
         Selector::Component::Type type;
 
 
@@ -110,7 +102,8 @@ NonnullRefPtr<StyleSheet> parse_css(const String& css)
         current_rule.selectors.append(Selector(move(components)));
         current_rule.selectors.append(Selector(move(components)));
     };
     };
 
 
-    auto parse_selector_list = [&] {
+    void parse_selector_list()
+    {
         for (;;) {
         for (;;) {
             parse_selector();
             parse_selector();
             consume_whitespace();
             consume_whitespace();
@@ -121,17 +114,20 @@ NonnullRefPtr<StyleSheet> parse_css(const String& css)
             if (peek() == '{')
             if (peek() == '{')
                 break;
                 break;
         }
         }
-    };
+    }
 
 
-    auto is_valid_property_name_char = [](char ch) {
+    bool is_valid_property_name_char(char ch) const
+    {
         return !isspace(ch) && ch != ':';
         return !isspace(ch) && ch != ':';
-    };
+    }
 
 
-    auto is_valid_property_value_char = [](char ch) {
+    bool is_valid_property_value_char(char ch) const
+    {
         return !isspace(ch) && ch != ';';
         return !isspace(ch) && ch != ';';
-    };
+    }
 
 
-    auto parse_declaration = [&] {
+    void parse_property()
+    {
         consume_whitespace();
         consume_whitespace();
         buffer.clear();
         buffer.clear();
         while (is_valid_property_name_char(peek()))
         while (is_valid_property_name_char(peek()))
@@ -147,29 +143,80 @@ NonnullRefPtr<StyleSheet> parse_css(const String& css)
         buffer.clear();
         buffer.clear();
         consume_specific(';');
         consume_specific(';');
         current_rule.properties.append({ property_name, parse_css_value(property_value) });
         current_rule.properties.append({ property_name, parse_css_value(property_value) });
-    };
+    }
 
 
-    auto parse_declarations = [&] {
+    void parse_declaration()
+    {
         for (;;) {
         for (;;) {
-            parse_declaration();
+            parse_property();
             consume_whitespace();
             consume_whitespace();
             if (peek() == '}')
             if (peek() == '}')
                 break;
                 break;
         }
         }
-    };
+    }
 
 
-    auto parse_rule = [&] {
+    void parse_rule()
+    {
         parse_selector_list();
         parse_selector_list();
         consume_specific('{');
         consume_specific('{');
-        parse_declarations();
+        parse_declaration();
         consume_specific('}');
         consume_specific('}');
         rules.append(StyleRule::create(move(current_rule.selectors), StyleDeclaration::create(move(current_rule.properties))));
         rules.append(StyleRule::create(move(current_rule.selectors), StyleDeclaration::create(move(current_rule.properties))));
         consume_whitespace();
         consume_whitespace();
-    };
+    }
+
+    NonnullRefPtr<StyleSheet> parse_sheet()
+    {
+        while (index < css.length()) {
+            parse_rule();
+        }
 
 
-    while (index < css.length()) {
-        parse_rule();
+        return StyleSheet::create(move(rules));
     }
     }
 
 
-    return StyleSheet::create(move(rules));
+    NonnullRefPtr<StyleDeclaration> parse_standalone_declaration()
+    {
+        consume_whitespace();
+        for (;;) {
+            parse_property();
+            consume_whitespace();
+            if (!peek())
+                break;
+        }
+        return StyleDeclaration::create(move(current_rule.properties));
+    }
+
+private:
+    NonnullRefPtrVector<StyleRule> rules;
+
+    enum class State {
+        Free,
+        InSelectorComponent,
+        InPropertyName,
+        InPropertyValue,
+    };
+
+    struct CurrentRule {
+        Vector<Selector> selectors;
+        Vector<StyleProperty> properties;
+    };
+
+    CurrentRule current_rule;
+    Vector<char> buffer;
+
+    int index = 0;
+
+    String css;
+};
+
+NonnullRefPtr<StyleSheet> parse_css(const String& css)
+{
+    CSSParser parser(css);
+    return parser.parse_sheet();
+}
+
+NonnullRefPtr<StyleDeclaration> parse_css_declaration(const String& css)
+{
+    CSSParser parser(css);
+    return parser.parse_standalone_declaration();
 }
 }

+ 1 - 0
Libraries/LibHTML/Parser/CSSParser.h

@@ -4,4 +4,5 @@
 #include <LibHTML/CSS/StyleSheet.h>
 #include <LibHTML/CSS/StyleSheet.h>
 
 
 NonnullRefPtr<StyleSheet> parse_css(const String&);
 NonnullRefPtr<StyleSheet> parse_css(const String&);
+NonnullRefPtr<StyleDeclaration> parse_css_declaration(const String&);