1 //===-- include/flang/Parser/user-state.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_USER_STATE_H_ 10 #define FORTRAN_PARSER_USER_STATE_H_ 11 12 // Instances of ParseState (parse-state.h) incorporate instances of this 13 // UserState class, which encapsulates any semantic information necessary for 14 // parse tree construction so as to avoid any need for representing 15 // state in static data. 16 17 #include "flang/Common/Fortran-features.h" 18 #include "flang/Common/idioms.h" 19 #include "flang/Parser/char-block.h" 20 #include "flang/Parser/parse-tree.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cinttypes> 23 #include <optional> 24 #include <set> 25 #include <unordered_map> 26 27 namespace Fortran::parser { 28 29 class AllCookedSources; 30 class ParsingLog; 31 class ParseState; 32 33 class Success {}; // for when one must return something that's present 34 35 class UserState { 36 public: UserState(const AllCookedSources & allCooked,common::LanguageFeatureControl features)37 UserState(const AllCookedSources &allCooked, 38 common::LanguageFeatureControl features) 39 : allCooked_{allCooked}, features_{features} {} 40 allCooked()41 const AllCookedSources &allCooked() const { return allCooked_; } features()42 const common::LanguageFeatureControl &features() const { return features_; } 43 debugOutput()44 llvm::raw_ostream *debugOutput() const { return debugOutput_; } set_debugOutput(llvm::raw_ostream & out)45 UserState &set_debugOutput(llvm::raw_ostream &out) { 46 debugOutput_ = &out; 47 return *this; 48 } 49 log()50 ParsingLog *log() const { return log_; } set_log(ParsingLog * log)51 UserState &set_log(ParsingLog *log) { 52 log_ = log; 53 return *this; 54 } 55 instrumentedParse()56 bool instrumentedParse() const { return instrumentedParse_; } set_instrumentedParse(bool yes)57 UserState &set_instrumentedParse(bool yes) { 58 instrumentedParse_ = yes; 59 return *this; 60 } 61 NewSubprogram()62 void NewSubprogram() { 63 doLabels_.clear(); 64 nonlabelDoConstructNestingDepth_ = 0; 65 oldStructureComponents_.clear(); 66 } 67 68 using Label = std::uint64_t; IsDoLabel(Label label)69 bool IsDoLabel(Label label) const { 70 auto iter{doLabels_.find(label)}; 71 return iter != doLabels_.end() && 72 iter->second >= nonlabelDoConstructNestingDepth_; 73 } NewDoLabel(Label label)74 void NewDoLabel(Label label) { 75 doLabels_[label] = nonlabelDoConstructNestingDepth_; 76 } 77 EnterNonlabelDoConstruct()78 void EnterNonlabelDoConstruct() { ++nonlabelDoConstructNestingDepth_; } LeaveDoConstruct()79 void LeaveDoConstruct() { 80 if (nonlabelDoConstructNestingDepth_ > 0) { 81 --nonlabelDoConstructNestingDepth_; 82 } 83 } 84 NoteOldStructureComponent(const CharBlock & name)85 void NoteOldStructureComponent(const CharBlock &name) { 86 oldStructureComponents_.insert(name); 87 } IsOldStructureComponent(const CharBlock & name)88 bool IsOldStructureComponent(const CharBlock &name) const { 89 return oldStructureComponents_.find(name) != oldStructureComponents_.end(); 90 } 91 92 private: 93 const AllCookedSources &allCooked_; 94 95 llvm::raw_ostream *debugOutput_{nullptr}; 96 97 ParsingLog *log_{nullptr}; 98 bool instrumentedParse_{false}; 99 100 std::unordered_map<Label, int> doLabels_; 101 int nonlabelDoConstructNestingDepth_{0}; 102 103 std::set<CharBlock> oldStructureComponents_; 104 105 common::LanguageFeatureControl features_; 106 }; 107 108 // Definitions of parser classes that manipulate the UserState. 109 struct StartNewSubprogram { 110 using resultType = Success; 111 static std::optional<Success> Parse(ParseState &); 112 }; 113 114 struct CapturedLabelDoStmt { 115 using resultType = Statement<common::Indirection<LabelDoStmt>>; 116 static std::optional<resultType> Parse(ParseState &); 117 }; 118 119 struct EndDoStmtForCapturedLabelDoStmt { 120 using resultType = Statement<common::Indirection<EndDoStmt>>; 121 static std::optional<resultType> Parse(ParseState &); 122 }; 123 124 struct EnterNonlabelDoConstruct { 125 using resultType = Success; 126 static std::optional<Success> Parse(ParseState &); 127 }; 128 129 struct LeaveDoConstruct { 130 using resultType = Success; 131 static std::optional<Success> Parse(ParseState &); 132 }; 133 134 struct OldStructureComponentName { 135 using resultType = Name; 136 static std::optional<Name> Parse(ParseState &); 137 }; 138 139 struct StructureComponents { 140 using resultType = DataComponentDefStmt; 141 static std::optional<DataComponentDefStmt> Parse(ParseState &); 142 }; 143 } // namespace Fortran::parser 144 #endif // FORTRAN_PARSER_USER_STATE_H_ 145