From 634f2f655b7038d8f487ed94cd4f4e087a5a842c Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sun, 7 Jul 2024 19:54:59 +0100 Subject: [PATCH] AK: Allow escaping of keys in SourceGenerator This allows the opening and closing characters of the SourceGenerator to be used in the source text to be used for purposes other than keys. --- AK/SourceGenerator.h | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/AK/SourceGenerator.h b/AK/SourceGenerator.h index 7a2c0e444ae..005e5e739c4 100644 --- a/AK/SourceGenerator.h +++ b/AK/SourceGenerator.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2020, the SerenityOS developers. * Copyright (c) 2023, Sam Atkins + * Copyright (c) 2024, Tim Ledbetter * * SPDX-License-Identifier: BSD-2-Clause */ @@ -21,17 +22,19 @@ class SourceGenerator { public: using MappingType = HashMap; - explicit SourceGenerator(StringBuilder& builder, char opening = '@', char closing = '@') + explicit SourceGenerator(StringBuilder& builder, char opening = '@', char closing = '@', char escape = '\\') : m_builder(builder) , m_opening(opening) , m_closing(closing) + , m_escape(escape) { } - explicit SourceGenerator(StringBuilder& builder, MappingType&& mapping, char opening = '@', char closing = '@') + explicit SourceGenerator(StringBuilder& builder, MappingType&& mapping, char opening = '@', char closing = '@', char escape = '\\') : m_builder(builder) , m_mapping(move(mapping)) , m_opening(opening) , m_closing(closing) + , m_escape(escape) { } @@ -70,7 +73,20 @@ public: GenericLexer lexer { pattern }; while (!lexer.is_eof()) { - m_builder.append(lexer.consume_until(m_opening)); + m_builder.append(lexer.consume_until([&](char ch) { return ch == m_opening || ch == m_escape; })); + if (lexer.consume_specific(m_escape)) { + if (!(lexer.next_is(m_opening) || lexer.next_is(m_escape))) { + if (lexer.is_eof()) + warnln("Unexpected EOF while parsing escape sequence on SourceGenerator"); + else + warnln("Invalid escape sequence found `{}{}` on SourceGenerator", m_escape, lexer.peek()); + + VERIFY_NOT_REACHED(); + } + + m_builder.append(lexer.consume()); + continue; + } if (lexer.consume_specific(m_opening)) { auto const placeholder = lexer.consume_until(m_closing); @@ -129,7 +145,9 @@ public: private: StringBuilder& m_builder; MappingType m_mapping; - char m_opening, m_closing; + char m_opening { '@' }; + char m_closing { '@' }; + char m_escape { '\\' }; }; }