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