AK: Use templates instead of Function for Conditions in the GenericLexer

Since commit 1ec59f28ce turns the ctype macros
into functions we can now feed them directly to a GenericLexer! This will lead to
removing the ctype adapters that were kind-of excessive boilerplate, but needed as
the Kernel doesn't compile with the LibC.
This commit is contained in:
Benoit Lormeau 2020-09-27 12:20:08 +02:00 committed by Andreas Kling
parent eef794b8c6
commit e4da2875c5
2 changed files with 61 additions and 56 deletions

View file

@ -75,12 +75,6 @@ bool GenericLexer::next_is(const char* expected) const
return true;
}
// Tests the next character against a Condition
bool GenericLexer::next_is(Condition condition) const
{
return condition(peek());
}
// Consume a character and advance the parser index
char GenericLexer::consume()
{
@ -154,19 +148,6 @@ StringView GenericLexer::consume_line()
return m_input.substring_view(start, length);
}
// Consume and return characters while `condition` returns true
StringView GenericLexer::consume_while(Condition condition)
{
size_t start = m_index;
while (!is_eof() && condition(peek()))
m_index++;
size_t length = m_index - start;
if (length == 0)
return {};
return m_input.substring_view(start, length);
}
// Consume and return characters until `stop` is peek'd
// The `stop` character is ignored, as it is user-defined
StringView GenericLexer::consume_until(char stop)
@ -199,19 +180,6 @@ StringView GenericLexer::consume_until(const char* stop)
return m_input.substring_view(start, length);
}
// Consume and return characters until `condition` return true
StringView GenericLexer::consume_until(Condition condition)
{
size_t start = m_index;
while (!is_eof() && !condition(peek()))
m_index++;
size_t length = m_index - start;
if (length == 0)
return {};
return m_input.substring_view(start, length);
}
/*
* Consume a string surrounded by single or double quotes. The returned
* StringView does not include the quotes. An escape character can be provided
@ -276,13 +244,6 @@ void GenericLexer::ignore(size_t count)
m_index += count;
}
// Ignore characters while `condition` returns true
void GenericLexer::ignore_while(Condition condition)
{
while (!is_eof() && condition(peek()))
m_index++;
}
// Ignore characters until `stop` is peek'd
// The `stop` character is ignored as it is user-defined
void GenericLexer::ignore_until(char stop)
@ -303,14 +264,6 @@ void GenericLexer::ignore_until(const char* stop)
ignore(__builtin_strlen(stop));
}
// Ignore characters until `condition` return true
// We don't skip the stop character as it may not be a unique value
void GenericLexer::ignore_until(Condition condition)
{
while (!is_eof() && !condition(peek()))
m_index++;
}
// CType adapters
bool is_alpha(char c)
{

View file

@ -26,7 +26,6 @@
#pragma once
#include <AK/Function.h>
#include <AK/String.h>
#include <AK/StringView.h>
@ -37,9 +36,6 @@ public:
explicit GenericLexer(const StringView& input);
virtual ~GenericLexer();
// A lambda/function can be used to match characters as the user pleases
using Condition = Function<bool(char)>;
size_t tell() const { return m_index; }
size_t tell_remaining() const { return m_input.length() - m_index; }
@ -52,7 +48,6 @@ public:
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);
@ -61,18 +56,75 @@ public:
StringView consume(size_t count);
StringView consume_all();
StringView consume_line();
StringView consume_while(Condition);
StringView consume_until(char);
StringView consume_until(const char*);
StringView consume_until(Condition);
StringView consume_quoted_string(char escape_char = 0);
String consume_and_unescape_string(char escape_char = '\\');
void ignore(size_t count = 1);
void ignore_while(Condition);
void ignore_until(char);
void ignore_until(const char*);
void ignore_until(Condition);
/*
* Conditions are used to match arbitrary characters. You can use lambdas,
* ctype functions, or is_any_of() and its derivatives (see below).
* A few examples:
* - `if (lexer.next_is(isdigit))`
* - `auto name = lexer.consume_while([](char c) { return isalnum(c) || c == '_'; });`
* - `lexer.ignore_until(is_any_of("<^>"));`
*/
// Test the next character against a Condition
template<typename C>
bool next_is(C condition) const
{
return condition(peek());
}
// Consume and return characters while `condition` returns true
template<typename C>
StringView consume_while(C condition)
{
size_t start = m_index;
while (!is_eof() && condition(peek()))
m_index++;
size_t length = m_index - start;
if (length == 0)
return {};
return m_input.substring_view(start, length);
}
// Consume and return characters until `condition` return true
template<typename C>
StringView consume_until(C condition)
{
size_t start = m_index;
while (!is_eof() && !condition(peek()))
m_index++;
size_t length = m_index - start;
if (length == 0)
return {};
return m_input.substring_view(start, length);
}
// Ignore characters while `condition` returns true
template<typename C>
void ignore_while(C condition)
{
while (!is_eof() && condition(peek()))
m_index++;
}
// Ignore characters until `condition` return true
// We don't skip the stop character as it may not be a unique value
template<typename C>
void ignore_until(C condition)
{
while (!is_eof() && !condition(peek()))
m_index++;
}
protected:
StringView m_input;