/* * Copyright (c) 2021, Itamar S. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Cpp { class Preprocessor { public: explicit Preprocessor(const String& filename, const StringView& program); Vector process_and_lex(); Vector included_paths() const { return m_included_paths; } struct Definition { String key; Vector parameters; String value; FlyString filename; size_t line { 0 }; size_t column { 0 }; }; using Definitions = HashMap; struct Substitution { Vector original_tokens; Definition defined_value; String processed_value; }; Definitions const& definitions() const { return m_definitions; } Vector const& substitutions() const { return m_substitutions; } void set_ignore_unsupported_keywords(bool ignore) { m_options.ignore_unsupported_keywords = ignore; } void set_keep_include_statements(bool keep) { m_options.keep_include_statements = keep; } Function definitions_in_header_callback { nullptr }; private: void handle_preprocessor_statement(StringView const&); void handle_include_statement(StringView const&); void handle_preprocessor_keyword(StringView const& keyword, GenericLexer& line_lexer); String remove_escaped_newlines(StringView const& value); size_t do_substitution(Vector const& tokens, size_t token_index, Definition const&); Optional create_definition(StringView line); struct MacroCall { Token name; struct Argument { Vector tokens; }; Vector arguments; size_t end_token_index { 0 }; }; Optional parse_macro_call(Vector const& tokens, size_t token_index); String evaluate_macro_call(MacroCall const&, Definition const&); String m_filename; String m_program; Vector m_processed_tokens; Definitions m_definitions; Vector m_substitutions; size_t m_current_line { 0 }; size_t m_current_depth { 0 }; Vector m_depths_of_taken_branches; Vector m_depths_of_not_taken_branches; enum class State { Normal, SkipIfBranch, SkipElseBranch }; State m_state { State::Normal }; Vector m_included_paths; struct Options { bool ignore_unsupported_keywords { false }; bool keep_include_statements { false }; } m_options; }; }