1 //===-- lib/Parser/preprocessor.h -------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_PARSER_PREPROCESSOR_H_ 10 #define FORTRAN_PARSER_PREPROCESSOR_H_ 11 12 // A Fortran-aware preprocessing module used by the prescanner to implement 13 // preprocessing directives and macro replacement. Intended to be efficient 14 // enough to always run on all source files even when no preprocessing is 15 // performed, so that special compiler command options &/or source file name 16 // extensions for preprocessing will not be necessary. 17 18 #include "token-sequence.h" 19 #include "flang/Parser/char-block.h" 20 #include "flang/Parser/provenance.h" 21 #include <cstddef> 22 #include <list> 23 #include <stack> 24 #include <string> 25 #include <unordered_map> 26 #include <vector> 27 28 namespace Fortran::parser { 29 30 class Prescanner; 31 32 // Defines a macro 33 class Definition { 34 public: 35 Definition(const TokenSequence &, std::size_t firstToken, std::size_t tokens); 36 Definition(const std::vector<std::string> &argNames, const TokenSequence &, 37 std::size_t firstToken, std::size_t tokens, bool isVariadic = false); 38 Definition(const std::string &predefined, AllSources &); 39 40 bool isFunctionLike() const { return isFunctionLike_; } 41 std::size_t argumentCount() const { return argumentCount_; } 42 bool isVariadic() const { return isVariadic_; } 43 bool isDisabled() const { return isDisabled_; } 44 bool isPredefined() const { return isPredefined_; } 45 const TokenSequence &replacement() const { return replacement_; } 46 47 bool set_isDisabled(bool disable); 48 49 TokenSequence Apply(const std::vector<TokenSequence> &args, AllSources &); 50 51 private: 52 static TokenSequence Tokenize(const std::vector<std::string> &argNames, 53 const TokenSequence &token, std::size_t firstToken, std::size_t tokens); 54 55 bool isFunctionLike_{false}; 56 std::size_t argumentCount_{0}; 57 bool isVariadic_{false}; 58 bool isDisabled_{false}; 59 bool isPredefined_{false}; 60 TokenSequence replacement_; 61 }; 62 63 // Preprocessing state 64 class Preprocessor { 65 public: 66 explicit Preprocessor(AllSources &); 67 68 void Define(std::string macro, std::string value); 69 void Undefine(std::string macro); 70 71 std::optional<TokenSequence> MacroReplacement( 72 const TokenSequence &, const Prescanner &); 73 74 // Implements a preprocessor directive. 75 void Directive(const TokenSequence &, Prescanner *); 76 77 private: 78 enum class IsElseActive { No, Yes }; 79 enum class CanDeadElseAppear { No, Yes }; 80 81 CharBlock SaveTokenAsName(const CharBlock &); 82 bool IsNameDefined(const CharBlock &); 83 TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &); 84 void SkipDisabledConditionalCode( 85 const std::string &, IsElseActive, Prescanner *, ProvenanceRange); 86 bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first, 87 std::size_t exprTokens, Prescanner *); 88 89 AllSources &allSources_; 90 std::list<std::string> names_; 91 std::unordered_map<CharBlock, Definition> definitions_; 92 std::stack<CanDeadElseAppear> ifStack_; 93 }; 94 } // namespace Fortran::parser 95 #endif // FORTRAN_PARSER_PREPROCESSOR_H_ 96