mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibWeb: Use GenericLexer in WrapperGenerator
This commit is contained in:
parent
0d52e7f6e3
commit
064159d215
Notes:
sideshowbarker
2024-07-19 03:21:35 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/064159d2154 Pull-request: https://github.com/SerenityOS/serenity/pull/3243
3 changed files with 70 additions and 92 deletions
|
@ -56,6 +56,15 @@ bool GenericLexer::next_is(char expected) const
|
|||
return peek() == expected;
|
||||
}
|
||||
|
||||
// Tests if the `expected` string comes next in the input
|
||||
bool GenericLexer::next_is(StringView expected) const
|
||||
{
|
||||
for (size_t i = 0; i < expected.length(); ++i)
|
||||
if (peek(i) != expected[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tests if the `expected` string comes next in the input
|
||||
bool GenericLexer::next_is(const char* expected) const
|
||||
{
|
||||
|
@ -89,15 +98,21 @@ bool GenericLexer::consume_specific(char specific)
|
|||
}
|
||||
|
||||
// Consume the given string if it is next in the input
|
||||
bool GenericLexer::consume_specific(const char* str)
|
||||
bool GenericLexer::consume_specific(StringView str)
|
||||
{
|
||||
if (!next_is(str))
|
||||
return false;
|
||||
|
||||
ignore(__builtin_strlen(str));
|
||||
ignore(str.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consume the given string if it is next in the input
|
||||
bool GenericLexer::consume_specific(const char* str)
|
||||
{
|
||||
return consume_specific(StringView(str));
|
||||
}
|
||||
|
||||
// Consume a number of characters
|
||||
StringView GenericLexer::consume(size_t count)
|
||||
{
|
||||
|
|
|
@ -45,27 +45,29 @@ public:
|
|||
|
||||
char peek(size_t offset = 0) const;
|
||||
|
||||
bool next_is(char expected) const;
|
||||
bool next_is(const char* expected) const;
|
||||
bool next_is(char) const;
|
||||
bool next_is(StringView) const;
|
||||
bool next_is(const char*) const;
|
||||
bool next_is(Condition) const;
|
||||
|
||||
char consume();
|
||||
bool consume_specific(char specific);
|
||||
bool consume_specific(const char* str);
|
||||
bool consume_specific(char);
|
||||
bool consume_specific(StringView);
|
||||
bool consume_specific(const char*);
|
||||
StringView consume(size_t count);
|
||||
StringView consume_all();
|
||||
StringView consume_line();
|
||||
StringView consume_while(Condition);
|
||||
StringView consume_until(char stop);
|
||||
StringView consume_until(const char* stop);
|
||||
StringView consume_until(char);
|
||||
StringView consume_until(const char*);
|
||||
StringView consume_until(Condition);
|
||||
// FIXME: provide an escape character
|
||||
StringView consume_quoted_string();
|
||||
|
||||
void ignore(size_t count = 1);
|
||||
void ignore_while(Condition);
|
||||
void ignore_until(char stop);
|
||||
void ignore_until(const char* stop);
|
||||
void ignore_until(char);
|
||||
void ignore_until(const char*);
|
||||
void ignore_until(Condition);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/GenericLexer.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
|
@ -120,101 +121,59 @@ static OwnPtr<Interface> parse_interface(const StringView& input)
|
|||
{
|
||||
auto interface = make<Interface>();
|
||||
|
||||
size_t index = 0;
|
||||
GenericLexer lexer(input);
|
||||
|
||||
auto peek = [&](size_t offset = 0) -> char {
|
||||
if (index + offset > input.length())
|
||||
return 0;
|
||||
return input[index + offset];
|
||||
};
|
||||
|
||||
auto consume = [&] {
|
||||
return input[index++];
|
||||
};
|
||||
|
||||
auto consume_if = [&](auto ch) {
|
||||
if (peek() == ch) {
|
||||
consume();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto consume_specific = [&](char ch) {
|
||||
auto consumed = consume();
|
||||
auto assert_specific = [&](char ch) {
|
||||
auto consumed = lexer.consume();
|
||||
if (consumed != ch) {
|
||||
dbg() << "Expected '" << ch << "' at offset " << index << " but got '" << consumed << "'";
|
||||
dbg() << "Expected '" << ch << "' at offset " << lexer.tell() << " but got '" << consumed << "'";
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
auto consume_whitespace = [&] {
|
||||
while (isspace(peek()))
|
||||
consume();
|
||||
lexer.consume_while([](char ch) { return isspace(ch); });
|
||||
};
|
||||
|
||||
auto consume_string = [&](const StringView& string) {
|
||||
for (size_t i = 0; i < string.length(); ++i) {
|
||||
ASSERT(consume() == string[i]);
|
||||
}
|
||||
auto assert_string = [&](const StringView& expected) {
|
||||
bool saw_expected = lexer.consume_specific(expected);
|
||||
ASSERT(saw_expected);
|
||||
};
|
||||
|
||||
auto next_is = [&](const StringView& string) {
|
||||
for (size_t i = 0; i < string.length(); ++i) {
|
||||
if (peek(i) != string[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto consume_while = [&](auto condition) {
|
||||
StringBuilder builder;
|
||||
while (index < input.length() && condition(peek())) {
|
||||
builder.append(consume());
|
||||
}
|
||||
return builder.to_string();
|
||||
};
|
||||
|
||||
consume_string("interface");
|
||||
assert_string("interface");
|
||||
consume_whitespace();
|
||||
interface->name = consume_while([](auto ch) { return !isspace(ch); });
|
||||
interface->name = lexer.consume_until([](auto ch) { return isspace(ch); });
|
||||
consume_whitespace();
|
||||
if (consume_if(':')) {
|
||||
if (lexer.consume_specific(':')) {
|
||||
consume_whitespace();
|
||||
interface->parent_name = consume_while([](auto ch) { return !isspace(ch); });
|
||||
interface->parent_name = lexer.consume_until([](auto ch) { return isspace(ch); });
|
||||
consume_whitespace();
|
||||
}
|
||||
consume_specific('{');
|
||||
assert_specific('{');
|
||||
|
||||
auto parse_type = [&] {
|
||||
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != '?'; });
|
||||
auto nullable = peek() == '?';
|
||||
if (nullable)
|
||||
consume_specific('?');
|
||||
auto name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == '?'; });
|
||||
auto nullable = lexer.consume_specific('?');
|
||||
return Type { name, nullable };
|
||||
};
|
||||
|
||||
auto parse_attribute = [&](HashMap<String, String>& extended_attributes) {
|
||||
bool readonly = false;
|
||||
bool unsigned_ = false;
|
||||
if (next_is("readonly")) {
|
||||
consume_string("readonly");
|
||||
readonly = true;
|
||||
bool readonly = lexer.consume_specific("readonly");
|
||||
if (readonly)
|
||||
consume_whitespace();
|
||||
}
|
||||
if (next_is("attribute")) {
|
||||
consume_string("attribute");
|
||||
|
||||
if (lexer.consume_specific("attribute"))
|
||||
consume_whitespace();
|
||||
}
|
||||
if (next_is("unsigned")) {
|
||||
consume_string("unsigned");
|
||||
unsigned_ = true;
|
||||
|
||||
bool unsigned_ = lexer.consume_specific("unsigned");
|
||||
if (unsigned_)
|
||||
consume_whitespace();
|
||||
}
|
||||
|
||||
auto type = parse_type();
|
||||
consume_whitespace();
|
||||
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ';'; });
|
||||
consume_specific(';');
|
||||
auto name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == ';'; });
|
||||
consume_whitespace();
|
||||
assert_specific(';');
|
||||
Attribute attribute;
|
||||
attribute.readonly = readonly;
|
||||
attribute.unsigned_ = unsigned_;
|
||||
|
@ -229,25 +188,27 @@ static OwnPtr<Interface> parse_interface(const StringView& input)
|
|||
auto parse_function = [&](HashMap<String, String>& extended_attributes) {
|
||||
auto return_type = parse_type();
|
||||
consume_whitespace();
|
||||
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != '('; });
|
||||
consume_specific('(');
|
||||
auto name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == '('; });
|
||||
consume_whitespace();
|
||||
assert_specific('(');
|
||||
|
||||
Vector<Parameter> parameters;
|
||||
|
||||
for (;;) {
|
||||
if (consume_if(')'))
|
||||
if (lexer.consume_specific(')'))
|
||||
break;
|
||||
auto type = parse_type();
|
||||
consume_whitespace();
|
||||
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ',' && ch != ')'; });
|
||||
auto name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == ',' || ch == ')'; });
|
||||
parameters.append({ move(type), move(name) });
|
||||
if (consume_if(')'))
|
||||
if (lexer.consume_specific(')'))
|
||||
break;
|
||||
consume_specific(',');
|
||||
assert_specific(',');
|
||||
consume_whitespace();
|
||||
}
|
||||
|
||||
consume_specific(';');
|
||||
consume_whitespace();
|
||||
assert_specific(';');
|
||||
|
||||
interface->functions.append(Function { return_type, name, move(parameters), move(extended_attributes) });
|
||||
};
|
||||
|
@ -256,11 +217,11 @@ static OwnPtr<Interface> parse_interface(const StringView& input)
|
|||
HashMap<String, String> extended_attributes;
|
||||
for (;;) {
|
||||
consume_whitespace();
|
||||
if (consume_if(']'))
|
||||
if (lexer.consume_specific(']'))
|
||||
break;
|
||||
auto name = consume_while([](auto ch) { return ch != ']' && ch != '=' && ch != ','; });
|
||||
if (consume_if('=')) {
|
||||
auto value = consume_while([](auto ch) { return ch != ']' && ch != ','; });
|
||||
auto name = lexer.consume_until([](auto ch) { return ch == ']' || ch == '=' || ch == ','; });
|
||||
if (lexer.consume_specific('=')) {
|
||||
auto value = lexer.consume_until([](auto ch) { return ch == ']' || ch == ','; });
|
||||
extended_attributes.set(name, value);
|
||||
} else {
|
||||
extended_attributes.set(name, {});
|
||||
|
@ -275,14 +236,14 @@ static OwnPtr<Interface> parse_interface(const StringView& input)
|
|||
|
||||
consume_whitespace();
|
||||
|
||||
if (consume_if('}'))
|
||||
if (lexer.consume_specific('}'))
|
||||
break;
|
||||
|
||||
if (consume_if('[')) {
|
||||
if (lexer.consume_specific('[')) {
|
||||
extended_attributes = parse_extended_attributes();
|
||||
}
|
||||
|
||||
if (next_is("readonly") || next_is("attribute")) {
|
||||
if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
|
||||
parse_attribute(extended_attributes);
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue