1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:38:12 +00:00

LibWeb: Add support for parsing IDL dictionaries

This commit is contained in:
Idan Horowitz 2021-09-28 23:33:15 +03:00
parent 87f655f2af
commit c3810b827a

View file

@ -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;
}