diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-07-28 05:04:39 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-02 01:03:59 +0200 |
commit | dc68c765b7fc945e7bbd743b82113927cd49748e (patch) | |
tree | 10f5ea83a5f299137d9ac4a63391a7894557d916 /Userland/Libraries/LibCpp/Preprocessor.cpp | |
parent | 8fefbfd5ace73fb5a55565e9178a94c26b97cc06 (diff) | |
download | serenity-dc68c765b7fc945e7bbd743b82113927cd49748e.zip |
LibCpp: Correctly parse lines that end in '\'
Such lines should be considered to be joined into the next line.
This makes multiline preprocessor stuff "work".
Diffstat (limited to 'Userland/Libraries/LibCpp/Preprocessor.cpp')
-rw-r--r-- | Userland/Libraries/LibCpp/Preprocessor.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/Userland/Libraries/LibCpp/Preprocessor.cpp b/Userland/Libraries/LibCpp/Preprocessor.cpp index 6dbb601201..9428f7ee0c 100644 --- a/Userland/Libraries/LibCpp/Preprocessor.cpp +++ b/Userland/Libraries/LibCpp/Preprocessor.cpp @@ -15,7 +15,25 @@ Preprocessor::Preprocessor(const String& filename, const StringView& program) : m_filename(filename) , m_program(program) { - m_lines = m_program.split_view('\n', true); + GenericLexer program_lexer { m_program }; + for (;;) { + if (program_lexer.is_eof()) + break; + auto line = program_lexer.consume_until('\n'); + bool has_multiline = false; + while (line.ends_with('\\') && !program_lexer.is_eof()) { + auto continuation = program_lexer.consume_until('\n'); + line = StringView { line.characters_without_null_termination(), line.length() + continuation.length() + 1 }; + // Append an empty line to keep the line count correct. + m_lines.append({}); + has_multiline = true; + } + + if (has_multiline) + m_lines.last() = line; + else + m_lines.append(line); + } } const String& Preprocessor::process() @@ -45,9 +63,28 @@ const String& Preprocessor::process() static void consume_whitespace(GenericLexer& lexer) { - lexer.ignore_while([](char ch) { return isspace(ch); }); - if (lexer.peek() == '/' && lexer.peek(1) == '/') - lexer.ignore_until([](char ch) { return ch == '\n'; }); + auto ignore_line = [&] { + for (;;) { + if (lexer.consume_specific("\\\n"sv)) { + lexer.ignore(2); + } else { + lexer.ignore_until('\n'); + break; + } + } + }; + for (;;) { + if (lexer.consume_specific("//"sv)) + ignore_line(); + else if (lexer.consume_specific("/*"sv)) + lexer.ignore_until("*/"); + else if (lexer.next_is("\\\n"sv)) + lexer.ignore(2); + else if (lexer.is_eof() || !lexer.next_is(isspace)) + break; + else + lexer.ignore(); + } } Preprocessor::PreprocessorKeyword Preprocessor::handle_preprocessor_line(const StringView& line) |