/* * 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(DeprecatedString const& filename, StringView program); Vector process_and_lex(); Vector included_paths() const { return m_included_paths; } struct Definition { DeprecatedString key; Vector parameters; DeprecatedString value; FlyString filename; size_t line { 0 }; size_t column { 0 }; }; using Definitions = HashMap; struct Substitution { Vector original_tokens; Definition defined_value; DeprecatedString 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_ignore_invalid_statements(bool ignore) { m_options.ignore_invalid_statements = ignore; } void set_keep_include_statements(bool keep) { m_options.keep_include_statements = keep; } Function definitions_in_header_callback { nullptr }; Vector const& unprocessed_tokens() const { return m_unprocessed_tokens; } private: void handle_preprocessor_statement(StringView); void handle_include_statement(StringView); void handle_preprocessor_keyword(StringView keyword, GenericLexer& line_lexer); DeprecatedString remove_escaped_newlines(StringView 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); DeprecatedString evaluate_macro_call(MacroCall const&, Definition const&); DeprecatedString m_filename; DeprecatedString m_program; Vector m_unprocessed_tokens; 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 ignore_invalid_statements { false }; bool keep_include_statements { false }; } m_options; }; }