// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef FORTRAN_PARSER_PREPROCESSOR_H_ #define FORTRAN_PARSER_PREPROCESSOR_H_ // A Fortran-aware preprocessing module used by the prescanner to implement // preprocessing directives and macro replacement. Intended to be efficient // enough to always run on all source files even when no preprocessing is // performed, so that special compiler command options &/or source file name // extensions for preprocessing will not be necessary. #include "char-block.h" #include "provenance.h" #include "token-sequence.h" #include #include #include #include #include #include namespace Fortran::parser { class Prescanner; // Defines a macro class Definition { public: Definition(const TokenSequence &, std::size_t firstToken, std::size_t tokens); Definition(const std::vector &argNames, const TokenSequence &, std::size_t firstToken, std::size_t tokens, bool isVariadic = false); Definition(const std::string &predefined, AllSources &); bool isFunctionLike() const { return isFunctionLike_; } std::size_t argumentCount() const { return argumentCount_; } bool isVariadic() const { return isVariadic_; } bool isDisabled() const { return isDisabled_; } bool isPredefined() const { return isPredefined_; } const TokenSequence &replacement() const { return replacement_; } bool set_isDisabled(bool disable); TokenSequence Apply(const std::vector &args, AllSources &); private: static TokenSequence Tokenize(const std::vector &argNames, const TokenSequence &token, std::size_t firstToken, std::size_t tokens); bool isFunctionLike_{false}; std::size_t argumentCount_{0}; bool isVariadic_{false}; bool isDisabled_{false}; bool isPredefined_{false}; TokenSequence replacement_; }; // Preprocessing state class Preprocessor { public: explicit Preprocessor(AllSources &); void Define(std::string macro, std::string value); void Undefine(std::string macro); std::optional MacroReplacement( const TokenSequence &, const Prescanner &); // Implements a preprocessor directive. void Directive(const TokenSequence &, Prescanner *); private: enum class IsElseActive { No, Yes }; enum class CanDeadElseAppear { No, Yes }; CharBlock SaveTokenAsName(const CharBlock &); bool IsNameDefined(const CharBlock &); TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &); void SkipDisabledConditionalCode( const std::string &, IsElseActive, Prescanner *, ProvenanceRange); bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first, std::size_t exprTokens, Prescanner *); AllSources &allSources_; std::list names_; std::unordered_map definitions_; std::stack ifStack_; }; } // namespace Fortran::parser #endif // FORTRAN_PARSER_PREPROCESSOR_H_