blob: e0a50c7b68967a245ef2fa9bb6cda173054d5dc6 [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 klausler424ec7b2018-03-20 17:59:0710#include "char-block.h"
peter klausler09865ff2018-02-09 22:04:1111#include "provenance.h"
peter klausler783d5622018-02-13 20:50:4712#include "token-sequence.h"
peter klausler424ec7b2018-03-20 17:59:0713#include <cstddef>
peter klausler90cd9ba2018-01-30 19:54:3114#include <list>
peter klausler16c6f532018-02-05 22:29:2615#include <stack>
peter klausler90cd9ba2018-01-30 19:54:3116#include <string>
17#include <unordered_map>
18#include <vector>
19
20namespace Fortran {
peter klausler0ba1a142018-02-07 20:04:4221namespace parser {
peter klausler90cd9ba2018-01-30 19:54:3122
peter klausler90cd9ba2018-01-30 19:54:3123class Prescanner;
24
peter klausler90cd9ba2018-01-30 19:54:3125// Defines a macro
26class Definition {
peter klauslerbdea10d2018-02-05 20:54:3627public:
peter klausler424ec7b2018-03-20 17:59:0728 Definition(const TokenSequence &, std::size_t firstToken, std::size_t tokens);
peter klausler90cd9ba2018-01-30 19:54:3129 Definition(const std::vector<std::string> &argNames, const TokenSequence &,
peter klausler424ec7b2018-03-20 17:59:0730 std::size_t firstToken, std::size_t tokens, bool isVariadic = false);
peter klausler75b29332018-03-23 22:14:5231 Definition(const std::string &predefined, AllSources &);
peter klausler90cd9ba2018-01-30 19:54:3132
33 bool isFunctionLike() const { return isFunctionLike_; }
peter klausler424ec7b2018-03-20 17:59:0734 std::size_t argumentCount() const { return argumentCount_; }
peter klausler90cd9ba2018-01-30 19:54:3135 bool isVariadic() const { return isVariadic_; }
36 bool isDisabled() const { return isDisabled_; }
peter klauslerad7125f2018-02-01 23:01:2337 bool isPredefined() const { return isPredefined_; }
peter klausler90cd9ba2018-01-30 19:54:3138 const TokenSequence &replacement() const { return replacement_; }
39
40 bool set_isDisabled(bool disable);
41
peter klausler75b29332018-03-23 22:14:5242 TokenSequence Apply(const std::vector<TokenSequence> &args, AllSources &);
peter klausler90cd9ba2018-01-30 19:54:3143
peter klauslerbdea10d2018-02-05 20:54:3644private:
peter klausler90cd9ba2018-01-30 19:54:3145 static TokenSequence Tokenize(const std::vector<std::string> &argNames,
peter klausler424ec7b2018-03-20 17:59:0746 const TokenSequence &token, std::size_t firstToken, std::size_t tokens);
peter klausler90cd9ba2018-01-30 19:54:3147
48 bool isFunctionLike_{false};
peter klausler424ec7b2018-03-20 17:59:0749 std::size_t argumentCount_{0};
peter klausler90cd9ba2018-01-30 19:54:3150 bool isVariadic_{false};
51 bool isDisabled_{false};
peter klauslerad7125f2018-02-01 23:01:2352 bool isPredefined_{false};
peter klausler90cd9ba2018-01-30 19:54:3153 TokenSequence replacement_;
54};
55
56// Preprocessing state
57class Preprocessor {
peter klauslerbdea10d2018-02-05 20:54:3658public:
peter klausler75b29332018-03-23 22:14:5259 explicit Preprocessor(AllSources &);
peter klausler90cd9ba2018-01-30 19:54:3160
peter klausler0983fbc2018-03-16 23:13:4961 void Define(std::string macro, std::string value);
62 void Undefine(std::string macro);
63
peter klausler75b29332018-03-23 22:14:5264 std::optional<TokenSequence> MacroReplacement(
65 const TokenSequence &, const Prescanner &);
peter klausler90cd9ba2018-01-30 19:54:3166
peter klausler0983fbc2018-03-16 23:13:4967 // Implements a preprocessor directive.
68 void 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 klausler424ec7b2018-03-20 17:59:0774 CharBlock SaveTokenAsName(const CharBlock &);
75 bool IsNameDefined(const CharBlock &);
peter klausler5b61bea2018-02-13 20:24:5476 TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &);
peter klausler0983fbc2018-03-16 23:13:4977 void SkipDisabledConditionalCode(
peter klausler554a5642018-03-19 18:48:4978 const std::string &, IsElseActive, Prescanner *, Provenance);
peter klausler424ec7b2018-03-20 17:59:0779 bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first,
80 std::size_t exprTokens, Prescanner *);
peter klausler93cf3ae2018-02-01 20:08:0281
peter klausler75b29332018-03-23 22:14:5282 AllSources &allSources_;
peter klausler90cd9ba2018-01-30 19:54:3183 std::list<std::string> names_;
peter klausler424ec7b2018-03-20 17:59:0784 std::unordered_map<CharBlock, Definition> definitions_;
peter klausler93cf3ae2018-02-01 20:08:0285 std::stack<CanDeadElseAppear> ifStack_;
peter klausler90cd9ba2018-01-30 19:54:3186};
peter klausler0ba1a142018-02-07 20:04:4287} // namespace parser
peter klausler90cd9ba2018-01-30 19:54:3188} // namespace Fortran
peter klauslerdd9923b2018-02-16 19:42:1789#endif // FORTRAN_PARSER_PREPROCESSOR_H_