diff options
author | Itamar <itamar8910@gmail.com> | 2021-08-13 12:49:06 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-14 12:40:55 +0200 |
commit | f6c9071f0dff0a61e9a25408e1cd9ae0ed8ca64f (patch) | |
tree | 14fffa7546894cdb7b8e9bd97f447566c116a396 | |
parent | 8505fcb8ae313792d32550bffec0a72f86e60102 (diff) | |
download | serenity-f6c9071f0dff0a61e9a25408e1cd9ae0ed8ca64f.zip |
LibCpp: Evaluate function-like macro calls
-rw-r--r-- | Userland/Libraries/LibCpp/Preprocessor.cpp | 37 | ||||
-rw-r--r-- | Userland/Libraries/LibCpp/Preprocessor.h | 1 |
2 files changed, 35 insertions, 3 deletions
diff --git a/Userland/Libraries/LibCpp/Preprocessor.cpp b/Userland/Libraries/LibCpp/Preprocessor.cpp index 002f668993..35994175b4 100644 --- a/Userland/Libraries/LibCpp/Preprocessor.cpp +++ b/Userland/Libraries/LibCpp/Preprocessor.cpp @@ -250,14 +250,13 @@ size_t Preprocessor::do_substitution(Vector<Token> const& tokens, size_t token_i if (!macro_call.has_value()) return token_index; - // TODO: Evaluate macro call - auto processed_value = defined_value.value; Vector<Token> original_tokens; for (size_t i = token_index; i <= macro_call->end_token_index; ++i) { original_tokens.append(tokens[i]); } VERIFY(!original_tokens.is_empty()); + auto processed_value = evaluate_macro_call(*macro_call, defined_value); m_substitutions.append({ original_tokens, defined_value, processed_value }); Lexer lexer(processed_value); @@ -356,9 +355,41 @@ Optional<Preprocessor::Definition> Preprocessor::create_definition(StringView li ++token_index; } - definition.value = line.substring_view(tokens[token_index].start().column); + if (token_index < tokens.size()) + definition.value = line.substring_view(tokens[token_index].start().column); return definition; } +String Preprocessor::evaluate_macro_call(MacroCall const& macro_call, Definition const& definition) +{ + if (macro_call.arguments.size() != definition.parameters.size()) { + dbgln("mismatch in # of arguments for macro call: {}", macro_call.name.text()); + return {}; + } + + Lexer lexer { definition.value }; + auto tokens = lexer.lex(); + + StringBuilder processed_value; + for (auto& token : tokens) { + if (token.type() != Token::Type::Identifier) { + processed_value.append(token.text()); + continue; + } + + auto param_index = definition.parameters.find_first_index(token.text()); + if (!param_index.has_value()) { + processed_value.append(token.text()); + continue; + } + + auto& argument = macro_call.arguments[*param_index]; + for (auto& arg_token : argument.tokens) { + processed_value.append(arg_token.text()); + } + } + return processed_value.to_string(); +} + }; diff --git a/Userland/Libraries/LibCpp/Preprocessor.h b/Userland/Libraries/LibCpp/Preprocessor.h index f91ee965f3..ab5af75d1a 100644 --- a/Userland/Libraries/LibCpp/Preprocessor.h +++ b/Userland/Libraries/LibCpp/Preprocessor.h @@ -65,6 +65,7 @@ private: size_t end_token_index { 0 }; }; Optional<MacroCall> parse_macro_call(Vector<Token> const& tokens, size_t token_index); + String evaluate_macro_call(MacroCall const&, Definition const&); String m_filename; String m_program; |