peter klausler | dd9923b | 2018-02-16 19:42:17 | [diff] [blame] | 1 | #ifndef FORTRAN_PARSER_PREPROCESSOR_H_ |
| 2 | #define FORTRAN_PARSER_PREPROCESSOR_H_ |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 3 | |
| 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 klausler | 783d562 | 2018-02-13 20:50:47 | [diff] [blame] | 7 | // performed, so that special compiler command options &/or source file name |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 8 | // extensions for preprocessing will not be necessary. |
| 9 | |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 10 | #include "char-block.h" |
peter klausler | 09865ff | 2018-02-09 22:04:11 | [diff] [blame] | 11 | #include "provenance.h" |
peter klausler | 783d562 | 2018-02-13 20:50:47 | [diff] [blame] | 12 | #include "token-sequence.h" |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 13 | #include <cstddef> |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 14 | #include <list> |
peter klausler | 16c6f53 | 2018-02-05 22:29:26 | [diff] [blame] | 15 | #include <stack> |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 16 | #include <string> |
| 17 | #include <unordered_map> |
| 18 | #include <vector> |
| 19 | |
| 20 | namespace Fortran { |
peter klausler | 0ba1a14 | 2018-02-07 20:04:42 | [diff] [blame] | 21 | namespace parser { |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 22 | |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 23 | class Prescanner; |
| 24 | |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 25 | // Defines a macro |
| 26 | class Definition { |
peter klausler | bdea10d | 2018-02-05 20:54:36 | [diff] [blame] | 27 | public: |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 28 | Definition(const TokenSequence &, std::size_t firstToken, std::size_t tokens); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 29 | Definition(const std::vector<std::string> &argNames, const TokenSequence &, |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 30 | std::size_t firstToken, std::size_t tokens, bool isVariadic = false); |
peter klausler | 97a7c50 | 2018-02-12 22:43:16 | [diff] [blame] | 31 | Definition(const std::string &predefined, AllSources *); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 32 | |
| 33 | bool isFunctionLike() const { return isFunctionLike_; } |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 34 | std::size_t argumentCount() const { return argumentCount_; } |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 35 | bool isVariadic() const { return isVariadic_; } |
| 36 | bool isDisabled() const { return isDisabled_; } |
peter klausler | ad7125f | 2018-02-01 23:01:23 | [diff] [blame] | 37 | bool isPredefined() const { return isPredefined_; } |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 38 | const TokenSequence &replacement() const { return replacement_; } |
| 39 | |
| 40 | bool set_isDisabled(bool disable); |
| 41 | |
peter klausler | 03aecfc | 2018-02-16 19:14:11 | [diff] [blame] | 42 | TokenSequence Apply(const std::vector<TokenSequence> &args, AllSources *); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 43 | |
peter klausler | bdea10d | 2018-02-05 20:54:36 | [diff] [blame] | 44 | private: |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 45 | static TokenSequence Tokenize(const std::vector<std::string> &argNames, |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 46 | const TokenSequence &token, std::size_t firstToken, std::size_t tokens); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 47 | |
| 48 | bool isFunctionLike_{false}; |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 49 | std::size_t argumentCount_{0}; |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 50 | bool isVariadic_{false}; |
| 51 | bool isDisabled_{false}; |
peter klausler | ad7125f | 2018-02-01 23:01:23 | [diff] [blame] | 52 | bool isPredefined_{false}; |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 53 | TokenSequence replacement_; |
| 54 | }; |
| 55 | |
| 56 | // Preprocessing state |
| 57 | class Preprocessor { |
peter klausler | bdea10d | 2018-02-05 20:54:36 | [diff] [blame] | 58 | public: |
peter klausler | 5b61bea | 2018-02-13 20:24:54 | [diff] [blame] | 59 | explicit Preprocessor(AllSources *); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 60 | |
peter klausler | 0983fbc | 2018-03-16 23:13:49 | [diff] [blame] | 61 | void Define(std::string macro, std::string value); |
| 62 | void Undefine(std::string macro); |
| 63 | |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 64 | // When the input contains macros to be replaced, the new token sequence |
| 65 | // is appended to the output and the returned value is true. When |
| 66 | // no macro replacement is necessary, the output is unmodified and the |
| 67 | // return value is false. |
peter klausler | 5b61bea | 2018-02-13 20:24:54 | [diff] [blame] | 68 | bool MacroReplacement( |
| 69 | const TokenSequence &, const Prescanner &, TokenSequence *); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 70 | |
peter klausler | 0983fbc | 2018-03-16 23:13:49 | [diff] [blame] | 71 | // Implements a preprocessor directive. |
| 72 | void Directive(const TokenSequence &, Prescanner *); |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 73 | |
peter klausler | bdea10d | 2018-02-05 20:54:36 | [diff] [blame] | 74 | private: |
peter klausler | 93cf3ae | 2018-02-01 20:08:02 | [diff] [blame] | 75 | enum class IsElseActive { No, Yes }; |
| 76 | enum class CanDeadElseAppear { No, Yes }; |
peter klausler | ad7125f | 2018-02-01 23:01:23 | [diff] [blame] | 77 | |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 78 | CharBlock SaveTokenAsName(const CharBlock &); |
| 79 | bool IsNameDefined(const CharBlock &); |
peter klausler | 5b61bea | 2018-02-13 20:24:54 | [diff] [blame] | 80 | TokenSequence ReplaceMacros(const TokenSequence &, const Prescanner &); |
peter klausler | 0983fbc | 2018-03-16 23:13:49 | [diff] [blame] | 81 | void SkipDisabledConditionalCode( |
peter klausler | 554a564 | 2018-03-19 18:48:49 | [diff] [blame] | 82 | const std::string &, IsElseActive, Prescanner *, Provenance); |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 83 | bool IsIfPredicateTrue(const TokenSequence &expr, std::size_t first, |
| 84 | std::size_t exprTokens, Prescanner *); |
peter klausler | 93cf3ae | 2018-02-01 20:08:02 | [diff] [blame] | 85 | |
peter klausler | 5b61bea | 2018-02-13 20:24:54 | [diff] [blame] | 86 | AllSources *allSources_; |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 87 | std::list<std::string> names_; |
peter klausler | 424ec7b | 2018-03-20 17:59:07 | [diff] [blame^] | 88 | std::unordered_map<CharBlock, Definition> definitions_; |
peter klausler | 93cf3ae | 2018-02-01 20:08:02 | [diff] [blame] | 89 | std::stack<CanDeadElseAppear> ifStack_; |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 90 | }; |
peter klausler | 0ba1a14 | 2018-02-07 20:04:42 | [diff] [blame] | 91 | } // namespace parser |
peter klausler | 90cd9ba | 2018-01-30 19:54:31 | [diff] [blame] | 92 | } // namespace Fortran |
peter klausler | dd9923b | 2018-02-16 19:42:17 | [diff] [blame] | 93 | #endif // FORTRAN_PARSER_PREPROCESSOR_H_ |