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