//===-- include/flang/Parser/user-state.h -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_PARSER_USER_STATE_H_
#define FORTRAN_PARSER_USER_STATE_H_
// Instances of ParseState (parse-state.h) incorporate instances of this
// UserState class, which encapsulates any semantic information necessary for
// parse tree construction so as to avoid any need for representing
// state in static data.
#include "flang/Common/Fortran-features.h"
#include "flang/Common/idioms.h"
#include "flang/Parser/char-block.h"
#include "flang/Parser/parse-tree.h"
#include "llvm/Support/raw_ostream.h"
#include <cinttypes>
#include <optional>
#include <set>
#include <unordered_map>
namespace Fortran::parser {
class AllCookedSources;
class ParsingLog;
class ParseState;
class Success {}; // for when one must return something that's present
class UserState {
public:
UserState(const AllCookedSources &allCooked,
common::LanguageFeatureControl features)
: allCooked_{allCooked}, features_{features} {}
const AllCookedSources &allCooked() const { return allCooked_; }
const common::LanguageFeatureControl &features() const { return features_; }
llvm::raw_ostream *debugOutput() const { return debugOutput_; }
UserState &set_debugOutput(llvm::raw_ostream &out) {
debugOutput_ = &out;
return *this;
}
ParsingLog *log() const { return log_; }
UserState &set_log(ParsingLog *log) {
log_ = log;
return *this;
}
bool instrumentedParse() const { return instrumentedParse_; }
UserState &set_instrumentedParse(bool yes) {
instrumentedParse_ = yes;
return *this;
}
void NewSubprogram() {
doLabels_.clear();
nonlabelDoConstructNestingDepth_ = 0;
oldStructureComponents_.clear();
}
using Label = std::uint64_t;
bool IsDoLabel(Label label) const {
auto iter{doLabels_.find(label)};
return iter != doLabels_.end() &&
iter->second >= nonlabelDoConstructNestingDepth_;
}
void NewDoLabel(Label label) {
doLabels_[label] = nonlabelDoConstructNestingDepth_;
}
void EnterNonlabelDoConstruct() { ++nonlabelDoConstructNestingDepth_; }
void LeaveDoConstruct() {
if (nonlabelDoConstructNestingDepth_ > 0) {
--nonlabelDoConstructNestingDepth_;
}
}
void NoteOldStructureComponent(const CharBlock &name) {
oldStructureComponents_.insert(name);
}
bool IsOldStructureComponent(const CharBlock &name) const {
return oldStructureComponents_.find(name) != oldStructureComponents_.end();
}
private:
const AllCookedSources &allCooked_;
llvm::raw_ostream *debugOutput_{nullptr};
ParsingLog *log_{nullptr};
bool instrumentedParse_{false};
std::unordered_map<Label, int> doLabels_;
int nonlabelDoConstructNestingDepth_{0};
std::set<CharBlock> oldStructureComponents_;
common::LanguageFeatureControl features_;
};
// Definitions of parser classes that manipulate the UserState.
struct StartNewSubprogram {
using resultType = Success;
static std::optional<Success> Parse(ParseState &);
};
struct CapturedLabelDoStmt {
using resultType = Statement<common::Indirection<LabelDoStmt>>;
static std::optional<resultType> Parse(ParseState &);
};
struct EndDoStmtForCapturedLabelDoStmt {
using resultType = Statement<common::Indirection<EndDoStmt>>;
static std::optional<resultType> Parse(ParseState &);
};
struct EnterNonlabelDoConstruct {
using resultType = Success;
static std::optional<Success> Parse(ParseState &);
};
struct LeaveDoConstruct {
using resultType = Success;
static std::optional<Success> Parse(ParseState &);
};
struct OldStructureComponentName {
using resultType = Name;
static std::optional<Name> Parse(ParseState &);
};
struct StructureComponents {
using resultType = DataComponentDefStmt;
static std::optional<DataComponentDefStmt> Parse(ParseState &);
};
struct NestedStructureStmt {
using resultType = StructureStmt;
static std::optional<StructureStmt> Parse(ParseState &);
};
} // namespace Fortran::parser
#endif // FORTRAN_PARSER_USER_STATE_H_