Procházet zdrojové kódy

LibWeb: Add support for parsing IDL dictionaries

Idan Horowitz před 3 roky
rodič
revize
c3810b827a

+ 77 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp

@@ -12,6 +12,7 @@
 #include <AK/HashMap.h>
 #include <AK/LexicalPath.h>
 #include <AK/OwnPtr.h>
+#include <AK/QuickSort.h>
 #include <AK/SourceGenerator.h>
 #include <AK/StringBuilder.h>
 #include <AK/Tuple.h>
@@ -126,6 +127,19 @@ struct Attribute {
     String setter_callback_name;
 };
 
+struct DictionaryMember {
+    bool required { false };
+    Type type;
+    String name;
+    HashMap<String, String> extended_attributes;
+    Optional<String> default_value;
+};
+
+struct Dictionary {
+    String parent_name;
+    Vector<DictionaryMember> members;
+};
+
 struct Interface {
     String name;
     String parent_name;
@@ -149,6 +163,8 @@ struct Interface {
 
     Optional<Function> named_property_deleter;
 
+    HashMap<String, Dictionary> dictionaries;
+
     // Added for convenience after parsing
     String wrapper_class;
     String wrapper_base_class;
@@ -564,6 +580,67 @@ static NonnullOwnPtr<Interface> parse_interface(StringView filename, StringView
     interface->prototype_class = String::formatted("{}Prototype", interface->name);
     interface->prototype_base_class = String::formatted("{}Prototype", interface->parent_name.is_empty() ? "Object" : interface->parent_name);
 
+    consume_whitespace();
+    while (!lexer.is_eof()) {
+        assert_string("dictionary");
+        consume_whitespace();
+
+        Dictionary dictionary {};
+
+        auto name = lexer.consume_until([](auto ch) { return isspace(ch); });
+        consume_whitespace();
+
+        if (lexer.consume_specific(':')) {
+            consume_whitespace();
+            dictionary.parent_name = lexer.consume_until([](auto ch) { return isspace(ch); });
+            consume_whitespace();
+        }
+        assert_specific('{');
+
+        for (;;) {
+            consume_whitespace();
+
+            if (lexer.consume_specific('}')) {
+                consume_whitespace();
+                assert_specific(';');
+                break;
+            }
+
+            DictionaryMember member {};
+            if (lexer.consume_specific("required")) {
+                member.required = true;
+                consume_whitespace();
+                if (lexer.consume_specific('['))
+                    member.extended_attributes = parse_extended_attributes();
+            }
+
+            member.type = parse_type();
+            consume_whitespace();
+
+            member.name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == ';'; });
+            consume_whitespace();
+
+            if (lexer.consume_specific('=')) {
+                VERIFY(!member.required);
+                consume_whitespace();
+                auto default_value = lexer.consume_until([](auto ch) { return isspace(ch) || ch == ';'; });
+                member.default_value = default_value;
+                consume_whitespace();
+            }
+
+            assert_specific(';');
+            dictionary.members.append(move(member));
+        }
+
+        // dictionary members need to be evaluated in lexicographical order
+        quick_sort(dictionary.members, [&](auto& one, auto& two) {
+            return one.name < two.name;
+        });
+
+        interface->dictionaries.set(name, move(dictionary));
+        consume_whitespace();
+    }
+
     return interface;
 }