From 064159d2154235d004f39bbe24acf82024bca1cb Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 21 Aug 2020 09:51:57 -0400 Subject: [PATCH] LibWeb: Use GenericLexer in WrapperGenerator --- AK/GenericLexer.cpp | 19 ++- AK/GenericLexer.h | 18 +-- .../CodeGenerators/WrapperGenerator.cpp | 125 ++++++------------ 3 files changed, 70 insertions(+), 92 deletions(-) diff --git a/AK/GenericLexer.cpp b/AK/GenericLexer.cpp index 1cb892a292..d288809ab2 100644 --- a/AK/GenericLexer.cpp +++ b/AK/GenericLexer.cpp @@ -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) { diff --git a/AK/GenericLexer.h b/AK/GenericLexer.h index 127b64518b..4956da649c 100644 --- a/AK/GenericLexer.h +++ b/AK/GenericLexer.h @@ -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: diff --git a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index 4150cf69d5..c2cf0c1e71 100644 --- a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -120,101 +121,59 @@ static OwnPtr parse_interface(const StringView& input) { auto interface = make(); - 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& 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 parse_interface(const StringView& input) auto parse_function = [&](HashMap& 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 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 parse_interface(const StringView& input) HashMap 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 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; }