blob: 8872761c7d2dc19ef8ac789ab088a154132c31f0 [file] [log] [blame]
peter klauslerdd9923b2018-02-16 19:42:171#ifndef FORTRAN_PARSER_PREPROCESSOR_H_
2#define FORTRAN_PARSER_PREPROCESSOR_H_
peter klausler90cd9ba2018-01-30 19:54:313
4// A Fortran-aware preprocessing module used by the prescanner to implement
5// preprocessing directives and macro replacement. Intended to be efficient
6// enough to always run on all source files even when no preprocessing is
peter klausler783d5622018-02-13 20:50:477// performed, so that special compiler command options &/or source file name
peter klausler90cd9ba2018-01-30 19:54:318// extensions for preprocessing will not be necessary.
9
peter klausler09865ff2018-02-09 22:04:1110#include "provenance.h"
peter klausler783d5622018-02-13 20:50:4711#include "token-sequence.h"
peter klausler90cd9ba2018-01-30 19:54:3112#include <list>
peter klausler16c6f532018-02-05 22:29:2613#include <stack>
peter klausler90cd9ba2018-01-30 19:54:3114#include <string>
15#include <unordered_map>
16#include <vector>
17
18namespace Fortran {
peter klausler0ba1a142018-02-07 20:04:4219namespace parser {
peter klausler90cd9ba2018-01-30 19:54:3120
peter klausler90cd9ba2018-01-30 19:54:3121class Prescanner;
22
peter klausler90cd9ba2018-01-30 19:54:3123// Defines a macro
24class Definition {
peter klauslerbdea10d2018-02-05 20:54:3625public:
peter klausler90cd9ba2018-01-30 19:54:3126 Definition(const TokenSequence &, size_t firstToken, size_t tokens);
27 Definition(const std::vector<std::string> &argNames, const TokenSequence &,
peter klausler16c6f532018-02-05 22:29:2628 size_t firstToken, size_t tokens, bool isVariadic = false);
peter klausler97a7c502018-02-12 22:43:1629 Definition(const std::string &predefined, AllSources *);
peter klausler90cd9ba2018-01-30 19:54:3130
31 bool isFunctionLike() const { return isFunctionLike_; }
32 size_t argumentCount() const { return argumentCount_; }
33 bool isVariadic() const { return isVariadic_; }
34 bool isDisabled() const { return isDisabled_; }
peter klauslerad7125f2018-02-01 23:01:2335 bool isPredefined() const { return isPredefined_; }
peter klausler90cd9ba2018-01-30 19:54:3136 const TokenSequence &replacement() const { return replacement_; }
37
38 bool set_isDisabled(bool disable);
39
peter klausler97a7c502018-02-12 22:43:1640 TokenSequence Apply(
peter klausler5b61bea2018-02-13 20:24:5441 const std::vector<TokenSequence> &args, const AllSources &);
peter klausler90cd9ba2018-01-30 19:54:3142
peter klauslerbdea10d2018-02-05 20:54:3643private:
peter klausler90cd9ba2018-01-30 19:54:3144 static TokenSequence Tokenize(const std::vector<std::string> &argNames,
peter klausler16c6f532018-02-05 22:29:2645 const TokenSequence &token, size_t firstToken, size_t tokens);
peter klausler90cd9ba2018-01-30 19:54:3146
47 bool isFunctionLike_{false};
48 size_t argumentCount_{0};
49 bool isVariadic_{false};
50 bool isDisabled_{false};
peter klauslerad7125f2018-02-01 23:01:2351 bool isPredefined_{false};
peter klausler90cd9ba2018-01-30 19:54:3152 TokenSequence replacement_;
53};
54
55// Preprocessing state
56class Preprocessor {
peter klauslerbdea10d2018-02-05 20:54:3657public:
peter klausler5b61bea2018-02-13 20:24:5458 explicit Preprocessor(AllSources *);
peter klausler90cd9ba2018-01-30 19:54:3159
60 // When the input contains macros to be replaced, the new token sequence
61 // is appended to the output and the returned value is true. When
62 // no macro replacement is necessary, the output is unmodified and the
63 // return value is false.
peter klausler5b61bea2018-02-13 20:24:5464 bool MacroReplacement(
65 const TokenSequence &, const Prescanner &, TokenSequence *);
peter klausler90cd9ba2018-01-30 19:54:3166
peter klausler55fe4d22018-02-02 23:52:4367 // Implements a preprocessor directive; returns true when no fatal error.
peter klausler5b61bea2018-02-13 20:24:5468 bool Directive(const TokenSequence &, Prescanner *);
peter klausler90cd9ba2018-01-30 19:54:3169
peter klauslerbdea10d2018-02-05 20:54:3670private:
peter klausler93cf3ae2018-02-01 20:08:0271 enum class IsElseActive { No, Yes };
72 enum class CanDeadElseAppear { No, Yes };
peter klauslerad7125f2018-02-01 23:01:2373
peter klausler97a7c502018-02-12 22:43:1674 CharPointerWithLength SaveTokenAsName(const CharPointerWithLength &);
peter klausler93cf3ae2018-02-01 20:08:0275 bool IsNameDefined(const CharPointerWithLength &);
peter klausler5b61bea2018-02-13 20:24:5476 TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &);
peter klausler206db2512018-02-17 00:57:4077 bool SkipDisabledConditionalCode(const std::string &, IsElseActive, Prescanner *);
peter klausler16c6f532018-02-05 22:29:2678 bool IsIfPredicateTrue(
peter klausler5b61bea2018-02-13 20:24:5479 const TokenSequence &expr, size_t first, size_t exprTokens, Prescanner *);
peter klausler93cf3ae2018-02-01 20:08:0280
peter klausler5b61bea2018-02-13 20:24:5481 AllSources *allSources_;
peter klausler90cd9ba2018-01-30 19:54:3182 std::list<std::string> names_;
83 std::unordered_map<CharPointerWithLength, Definition> definitions_;
peter klausler93cf3ae2018-02-01 20:08:0284 std::stack<CanDeadElseAppear> ifStack_;
peter klausler90cd9ba2018-01-30 19:54:3185};
peter klausler0ba1a142018-02-07 20:04:4286} // namespace parser
peter klausler90cd9ba2018-01-30 19:54:3187} // namespace Fortran
peter klauslerdd9923b2018-02-16 19:42:1788#endif // FORTRAN_PARSER_PREPROCESSOR_H_