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 CookedSource; 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 CookedSource & cooked,common::LanguageFeatureControl features)37 UserState(const CookedSource &cooked, common::LanguageFeatureControl features) 38 : cooked_{cooked}, features_{features} {} 39 cooked()40 const CookedSource &cooked() const { return cooked_; } features()41 const common::LanguageFeatureControl &features() const { return features_; } 42 debugOutput()43 llvm::raw_ostream *debugOutput() const { return debugOutput_; } set_debugOutput(llvm::raw_ostream & out)44 UserState &set_debugOutput(llvm::raw_ostream &out) { 45 debugOutput_ = &out; 46 return *this; 47 } 48 log()49 ParsingLog *log() const { return log_; } set_log(ParsingLog * log)50 UserState &set_log(ParsingLog *log) { 51 log_ = log; 52 return *this; 53 } 54 instrumentedParse()55 bool instrumentedParse() const { return instrumentedParse_; } set_instrumentedParse(bool yes)56 UserState &set_instrumentedParse(bool yes) { 57 instrumentedParse_ = yes; 58 return *this; 59 } 60 NewSubprogram()61 void NewSubprogram() { 62 doLabels_.clear(); 63 nonlabelDoConstructNestingDepth_ = 0; 64 oldStructureComponents_.clear(); 65 } 66 67 using Label = std::uint64_t; IsDoLabel(Label label)68 bool IsDoLabel(Label label) const { 69 auto iter{doLabels_.find(label)}; 70 return iter != doLabels_.end() && 71 iter->second >= nonlabelDoConstructNestingDepth_; 72 } NewDoLabel(Label label)73 void NewDoLabel(Label label) { 74 doLabels_[label] = nonlabelDoConstructNestingDepth_; 75 } 76 EnterNonlabelDoConstruct()77 void EnterNonlabelDoConstruct() { ++nonlabelDoConstructNestingDepth_; } LeaveDoConstruct()78 void LeaveDoConstruct() { 79 if (nonlabelDoConstructNestingDepth_ > 0) { 80 --nonlabelDoConstructNestingDepth_; 81 } 82 } 83 NoteOldStructureComponent(const CharBlock & name)84 void NoteOldStructureComponent(const CharBlock &name) { 85 oldStructureComponents_.insert(name); 86 } IsOldStructureComponent(const CharBlock & name)87 bool IsOldStructureComponent(const CharBlock &name) const { 88 return oldStructureComponents_.find(name) != oldStructureComponents_.end(); 89 } 90 91 private: 92 const CookedSource &cooked_; 93 94 llvm::raw_ostream *debugOutput_{nullptr}; 95 96 ParsingLog *log_{nullptr}; 97 bool instrumentedParse_{false}; 98 99 std::unordered_map<Label, int> doLabels_; 100 int nonlabelDoConstructNestingDepth_{0}; 101 102 std::set<CharBlock> oldStructureComponents_; 103 104 common::LanguageFeatureControl features_; 105 }; 106 107 // Definitions of parser classes that manipulate the UserState. 108 struct StartNewSubprogram { 109 using resultType = Success; 110 static std::optional<Success> Parse(ParseState &); 111 }; 112 113 struct CapturedLabelDoStmt { 114 using resultType = Statement<common::Indirection<LabelDoStmt>>; 115 static std::optional<resultType> Parse(ParseState &); 116 }; 117 118 struct EndDoStmtForCapturedLabelDoStmt { 119 using resultType = Statement<common::Indirection<EndDoStmt>>; 120 static std::optional<resultType> Parse(ParseState &); 121 }; 122 123 struct EnterNonlabelDoConstruct { 124 using resultType = Success; 125 static std::optional<Success> Parse(ParseState &); 126 }; 127 128 struct LeaveDoConstruct { 129 using resultType = Success; 130 static std::optional<Success> Parse(ParseState &); 131 }; 132 133 struct OldStructureComponentName { 134 using resultType = Name; 135 static std::optional<Name> Parse(ParseState &); 136 }; 137 138 struct StructureComponents { 139 using resultType = DataComponentDefStmt; 140 static std::optional<DataComponentDefStmt> Parse(ParseState &); 141 }; 142 } // namespace Fortran::parser 143 #endif // FORTRAN_PARSER_USER_STATE_H_ 144