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 class Preprocessor; 32 33 // Defines a macro 34 class Definition { 35 public: 36 Definition(const TokenSequence &, std::size_t firstToken, std::size_t tokens); 37 Definition(const std::vector<std::string> &argNames, const TokenSequence &, 38 std::size_t firstToken, std::size_t tokens, bool isVariadic = false); 39 Definition(const std::string &predefined, AllSources &); 40 isFunctionLike()41 bool isFunctionLike() const { return isFunctionLike_; } argumentCount()42 std::size_t argumentCount() const { return argumentCount_; } isVariadic()43 bool isVariadic() const { return isVariadic_; } isDisabled()44 bool isDisabled() const { return isDisabled_; } isPredefined()45 bool isPredefined() const { return isPredefined_; } replacement()46 const TokenSequence &replacement() const { return replacement_; } 47 48 bool set_isDisabled(bool disable); 49 50 TokenSequence Apply(const std::vector<TokenSequence> &args, Prescanner &); 51 52 private: 53 static TokenSequence Tokenize(const std::vector<std::string> &argNames, 54 const TokenSequence &token, std::size_t firstToken, std::size_t tokens); 55 56 bool isFunctionLike_{false}; 57 std::size_t argumentCount_{0}; 58 bool isVariadic_{false}; 59 bool isDisabled_{false}; 60 bool isPredefined_{false}; 61 TokenSequence replacement_; 62 }; 63 64 // Preprocessing state 65 class Preprocessor { 66 public: 67 explicit Preprocessor(AllSources &); 68 allSources()69 const AllSources &allSources() const { return allSources_; } allSources()70 AllSources &allSources() { return allSources_; } 71 72 void Define(std::string macro, std::string value); 73 void Undefine(std::string macro); 74 bool IsNameDefined(const CharBlock &); 75 76 std::optional<TokenSequence> MacroReplacement( 77 const TokenSequence &, Prescanner &); 78 79 // Implements a preprocessor directive. 80 void Directive(const TokenSequence &, Prescanner *); 81 82 private: 83 enum class IsElseActive { No, Yes }; 84 enum class CanDeadElseAppear { No, Yes }; 85 86 CharBlock SaveTokenAsName(const CharBlock &); 87 TokenSequence ReplaceMacros(const TokenSequence &, Prescanner &); 88 void SkipDisabledConditionalCode( 89 const std::string &, IsElseActive, Prescanner *, ProvenanceRange); 90 bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first, 91 std::size_t exprTokens, Prescanner *); 92 93 AllSources &allSources_; 94 std::list<std::string> names_; 95 std::unordered_map<CharBlock, Definition> definitions_; 96 std::stack<CanDeadElseAppear> ifStack_; 97 }; 98 } // namespace Fortran::parser 99 #endif // FORTRAN_PARSER_PREPROCESSOR_H_ 100