1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:54:58 +00:00

LibIDL: Ignore leading underscores in IDL identifier names

According to the WebIDL specification, any leading underscores in
identifier names are ignored. A leading underscore is used when an
identifier would otherwise be a reserved word.
This commit is contained in:
Tim Ledbetter 2024-03-10 22:07:54 +00:00 committed by Andreas Kling
parent 130f28cf50
commit 9eaae99da7
2 changed files with 48 additions and 23 deletions

View file

@ -9,6 +9,7 @@
#include "IDLParser.h" #include "IDLParser.h"
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/Function.h>
#include <AK/LexicalPath.h> #include <AK/LexicalPath.h>
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <LibCore/File.h> #include <LibCore/File.h>
@ -104,6 +105,27 @@ void Parser::assert_string(StringView expected)
report_parsing_error(ByteString::formatted("expected '{}'", expected), filename, input, lexer.tell()); report_parsing_error(ByteString::formatted("expected '{}'", expected), filename, input, lexer.tell());
} }
ByteString Parser::parse_identifier_until(AK::Function<bool(char)> predicate)
{
auto identifier = lexer.consume_until(move(predicate));
return identifier.trim("_"sv, TrimMode::Left);
}
ByteString Parser::parse_identifier_ending_with_space_or(auto... possible_terminating_characters)
{
return parse_identifier_until([&](auto ch) { return (is_ascii_space(ch) || ... || (ch == possible_terminating_characters)); });
}
ByteString Parser::parse_identifier_ending_with(auto... possible_terminating_characters)
{
return parse_identifier_until([&](auto ch) { return (... || (ch == possible_terminating_characters)); });
}
ByteString Parser::parse_identifier_ending_with_space()
{
return parse_identifier_ending_with_space_or();
}
HashMap<ByteString, ByteString> Parser::parse_extended_attributes() HashMap<ByteString, ByteString> Parser::parse_extended_attributes()
{ {
HashMap<ByteString, ByteString> extended_attributes; HashMap<ByteString, ByteString> extended_attributes;
@ -111,7 +133,7 @@ HashMap<ByteString, ByteString> Parser::parse_extended_attributes()
consume_whitespace(); consume_whitespace();
if (lexer.consume_specific(']')) if (lexer.consume_specific(']'))
break; break;
auto name = lexer.consume_until([](auto ch) { return ch == ']' || ch == '=' || ch == ','; }); auto name = parse_identifier_ending_with(']', '=', ',');
if (lexer.consume_specific('=')) { if (lexer.consume_specific('=')) {
bool did_open_paren = false; bool did_open_paren = false;
auto value = lexer.consume_until( auto value = lexer.consume_until(
@ -277,20 +299,19 @@ void Parser::parse_attribute(HashMap<ByteString, ByteString>& extended_attribute
auto type = parse_type(); auto type = parse_type();
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; }); auto name = parse_identifier_ending_with_space_or(';');
consume_whitespace(); consume_whitespace();
assert_specific(';'); assert_specific(';');
auto name_as_string = name.to_byte_string(); auto getter_callback_name = ByteString::formatted("{}_getter", name.to_snakecase());
auto getter_callback_name = ByteString::formatted("{}_getter", name_as_string.to_snakecase()); auto setter_callback_name = ByteString::formatted("{}_setter", name.to_snakecase());
auto setter_callback_name = ByteString::formatted("{}_setter", name_as_string.to_snakecase());
Attribute attribute { Attribute attribute {
inherit, inherit,
readonly, readonly,
move(type), move(type),
move(name_as_string), move(name),
move(extended_attributes), move(extended_attributes),
move(getter_callback_name), move(getter_callback_name),
move(setter_callback_name), move(setter_callback_name),
@ -305,7 +326,7 @@ void Parser::parse_constant(Interface& interface)
auto type = parse_type(); auto type = parse_type();
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == '='; }); auto name = parse_identifier_ending_with_space_or('=');
consume_whitespace(); consume_whitespace();
lexer.consume_specific('='); lexer.consume_specific('=');
consume_whitespace(); consume_whitespace();
@ -343,7 +364,7 @@ Vector<Parameter> Parser::parse_parameters()
auto type = parse_type(); auto type = parse_type();
bool variadic = lexer.consume_specific("..."sv); bool variadic = lexer.consume_specific("..."sv);
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ',' || ch == ')' || ch == '='; }); auto name = parse_identifier_ending_with_space_or(',', ')', '=');
Parameter parameter = { move(type), move(name), optional, {}, move(extended_attributes), variadic }; Parameter parameter = { move(type), move(name), optional, {}, move(extended_attributes), variadic };
consume_whitespace(); consume_whitespace();
if (variadic) { if (variadic) {
@ -381,7 +402,7 @@ Function Parser::parse_function(HashMap<ByteString, ByteString>& extended_attrib
auto return_type = parse_type(); auto return_type = parse_type();
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == '('; }); auto name = parse_identifier_ending_with_space_or('(');
consume_whitespace(); consume_whitespace();
assert_specific('('); assert_specific('(');
auto parameters = parse_parameters(); auto parameters = parse_parameters();
@ -560,11 +581,11 @@ void Parser::parse_deleter(HashMap<ByteString, ByteString>& extended_attributes,
void Parser::parse_interface(Interface& interface) void Parser::parse_interface(Interface& interface)
{ {
consume_whitespace(); consume_whitespace();
interface.name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); interface.name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
if (lexer.consume_specific(':')) { if (lexer.consume_specific(':')) {
consume_whitespace(); consume_whitespace();
interface.parent_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); interface.parent_name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
} }
assert_specific('{'); assert_specific('{');
@ -650,7 +671,7 @@ void Parser::parse_namespace(Interface& interface)
{ {
consume_whitespace(); consume_whitespace();
interface.name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); interface.name = parse_identifier_ending_with_space();
interface.is_namespace = true; interface.is_namespace = true;
consume_whitespace(); consume_whitespace();
@ -681,7 +702,7 @@ void Parser::parse_enumeration(HashMap<ByteString, ByteString> extended_attribut
Enumeration enumeration {}; Enumeration enumeration {};
enumeration.extended_attributes = move(extended_attributes); enumeration.extended_attributes = move(extended_attributes);
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); auto name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
assert_specific('{'); assert_specific('{');
@ -736,10 +757,10 @@ void Parser::parse_typedef(Interface& interface)
auto type = parse_type(); auto type = parse_type();
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until(';'); auto name = parse_identifier_ending_with(';');
assert_specific(';'); assert_specific(';');
interface.typedefs.set(name, Typedef { move(extended_attributes), move(type) }); interface.typedefs.set(move(name), Typedef { move(extended_attributes), move(type) });
consume_whitespace(); consume_whitespace();
} }
@ -750,12 +771,12 @@ void Parser::parse_dictionary(Interface& interface)
Dictionary dictionary {}; Dictionary dictionary {};
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); auto name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
if (lexer.consume_specific(':')) { if (lexer.consume_specific(':')) {
consume_whitespace(); consume_whitespace();
dictionary.parent_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); dictionary.parent_name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
} }
assert_specific('{'); assert_specific('{');
@ -783,7 +804,7 @@ void Parser::parse_dictionary(Interface& interface)
auto type = parse_type(); auto type = parse_type();
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; }); auto name = parse_identifier_ending_with_space_or(';');
consume_whitespace(); consume_whitespace();
Optional<StringView> default_value; Optional<StringView> default_value;
@ -800,7 +821,7 @@ void Parser::parse_dictionary(Interface& interface)
DictionaryMember member { DictionaryMember member {
required, required,
move(type), move(type),
name, move(name),
move(extended_attributes), move(extended_attributes),
Optional<ByteString>(move(default_value)), Optional<ByteString>(move(default_value)),
}; };
@ -842,7 +863,7 @@ void Parser::parse_callback_function(HashMap<ByteString, ByteString>& extended_a
assert_string("callback"sv); assert_string("callback"sv);
consume_whitespace(); consume_whitespace();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); auto name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
assert_specific('='); assert_specific('=');
@ -856,7 +877,7 @@ void Parser::parse_callback_function(HashMap<ByteString, ByteString>& extended_a
consume_whitespace(); consume_whitespace();
assert_specific(';'); assert_specific(';');
interface.callback_functions.set(name, CallbackFunction { move(return_type), move(parameters), extended_attributes.contains("LegacyTreatNonObjectAsNull") }); interface.callback_functions.set(move(name), CallbackFunction { move(return_type), move(parameters), extended_attributes.contains("LegacyTreatNonObjectAsNull") });
consume_whitespace(); consume_whitespace();
} }
@ -880,11 +901,11 @@ void Parser::parse_non_interface_entities(bool allow_interface, Interface& inter
parse_callback_function(extended_attributes, interface); parse_callback_function(extended_attributes, interface);
} else if ((allow_interface && !lexer.next_is("interface") && !lexer.next_is("namespace")) || !allow_interface) { } else if ((allow_interface && !lexer.next_is("interface") && !lexer.next_is("namespace")) || !allow_interface) {
auto current_offset = lexer.tell(); auto current_offset = lexer.tell();
auto name = lexer.consume_until([](auto ch) { return is_ascii_space(ch); }); auto name = parse_identifier_ending_with_space();
consume_whitespace(); consume_whitespace();
if (lexer.consume_specific("includes"sv)) { if (lexer.consume_specific("includes"sv)) {
consume_whitespace(); consume_whitespace();
auto mixin_name = lexer.consume_until([](auto ch) { return is_ascii_space(ch) || ch == ';'; }); auto mixin_name = parse_identifier_ending_with_space_or(';');
interface.included_mixins.ensure(name).set(mixin_name); interface.included_mixins.ensure(name).set(mixin_name);
consume_whitespace(); consume_whitespace();
assert_specific(';'); assert_specific(';');

View file

@ -57,6 +57,10 @@ private:
Vector<Parameter> parse_parameters(); Vector<Parameter> parse_parameters();
NonnullRefPtr<Type const> parse_type(); NonnullRefPtr<Type const> parse_type();
void parse_constant(Interface&); void parse_constant(Interface&);
ByteString parse_identifier_until(AK::Function<bool(char)> predicate);
ByteString parse_identifier_ending_with(auto... possible_terminating_characters);
ByteString parse_identifier_ending_with_space();
ByteString parse_identifier_ending_with_space_or(auto... possible_terminating_characters);
ByteString import_base_path; ByteString import_base_path;
ByteString filename; ByteString filename;