From c3810b827a86dc1e1211bb58293a3d43c7f8f506 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 28 Sep 2021 23:33:15 +0300 Subject: [PATCH] LibWeb: Add support for parsing IDL dictionaries --- .../LibWeb/WrapperGenerator.cpp | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp index 0533d33a0c..cbb34c8168 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,19 @@ struct Attribute { String setter_callback_name; }; +struct DictionaryMember { + bool required { false }; + Type type; + String name; + HashMap extended_attributes; + Optional default_value; +}; + +struct Dictionary { + String parent_name; + Vector members; +}; + struct Interface { String name; String parent_name; @@ -149,6 +163,8 @@ struct Interface { Optional named_property_deleter; + HashMap dictionaries; + // Added for convenience after parsing String wrapper_class; String wrapper_base_class; @@ -564,6 +580,67 @@ static NonnullOwnPtr 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; }