1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 06:48:12 +00:00

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".
This commit is contained in:
Ali Mohammad Pur 2021-07-28 05:04:39 +04:30 committed by Andreas Kling
parent 8fefbfd5ac
commit dc68c765b7
3 changed files with 62 additions and 7 deletions

View file

@ -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)