#ifndef LLVM_TABLEGEN_DIRECTIVEEMITTER_H
 
#define LLVM_TABLEGEN_DIRECTIVEEMITTER_H
 
 
 
#include "llvm/ADT/StringExtras.h"
 
#include "llvm/TableGen/Record.h"
 
 
 
namespace llvm {
 
 
 
// Wrapper class that contains DirectiveLanguage's information defined in
 
// DirectiveBase.td and provides helper methods for accessing it.
 
class DirectiveLanguage {
 
public:
 
  explicit DirectiveLanguage(const llvm::RecordKeeper &Records)
 
      : Records(Records) {
 
    const auto &DirectiveLanguages = getDirectiveLanguages();
 
    Def = DirectiveLanguages[0];
 
  }
 
 
 
  StringRef getName() const { return Def->getValueAsString("name"); }
 
 
 
  StringRef getCppNamespace() const {
 
    return Def->getValueAsString("cppNamespace");
 
  }
 
 
 
  StringRef getDirectivePrefix() const {
 
    return Def->getValueAsString("directivePrefix");
 
  }
 
 
 
  StringRef getClausePrefix() const {
 
    return Def->getValueAsString("clausePrefix");
 
  }
 
 
 
  StringRef getClauseEnumSetClass() const {
 
    return Def->getValueAsString("clauseEnumSetClass");
 
  }
 
 
 
  StringRef getFlangClauseBaseClass() const {
 
    return Def->getValueAsString("flangClauseBaseClass");
 
  }
 
 
 
  bool hasMakeEnumAvailableInNamespace() const {
 
    return Def->getValueAsBit("makeEnumAvailableInNamespace");
 
  }
 
 
 
  bool hasEnableBitmaskEnumInNamespace() const {
 
    return Def->getValueAsBit("enableBitmaskEnumInNamespace");
 
  }
 
 
 
  std::vector<Record *> getDirectives() const {
 
    return Records.getAllDerivedDefinitions("Directive");
 
  }
 
 
 
  std::vector<Record *> getClauses() const {
 
    return Records.getAllDerivedDefinitions("Clause");
 
  }
 
 
 
  bool HasValidityErrors() const;
 
 
 
private:
 
  const llvm::Record *Def;
 
  const llvm::RecordKeeper &Records;
 
 
 
  std::vector<Record *> getDirectiveLanguages() const {
 
    return Records.getAllDerivedDefinitions("DirectiveLanguage");
 
  }
 
};
 
 
 
// Base record class used for Directive and Clause class defined in
 
// DirectiveBase.td.
 
class BaseRecord {
 
public:
 
  explicit BaseRecord(const llvm::Record *Def) : Def(Def) {}
 
 
 
  StringRef getName() const { return Def->getValueAsString("name"); }
 
 
 
  StringRef getAlternativeName() const {
 
    return Def->getValueAsString("alternativeName");
 
  }
 
 
 
  // Returns the name of the directive formatted for output. Whitespace are
 
  // replaced with underscores.
 
  std::string getFormattedName() {
 
    StringRef Name = Def->getValueAsString("name");
 
    std::string N = Name.str();
 
    std::replace(N.begin(), N.end(), ' ', '_');
 
    return N;
 
  }
 
 
 
  bool isDefault() const { return Def->getValueAsBit("isDefault"); }
 
 
 
  // Returns the record name.
 
  StringRef getRecordName() const { return Def->getName(); }
 
 
 
protected:
 
  const llvm::Record *Def;
 
};
 
 
 
// Wrapper class that contains a Directive's information defined in
 
// DirectiveBase.td and provides helper methods for accessing it.
 
class Directive : public BaseRecord {
 
public:
 
  explicit Directive(const llvm::Record *Def) : BaseRecord(Def) {}
 
 
 
  std::vector<Record *> getAllowedClauses() const {
 
    return Def->getValueAsListOfDefs("allowedClauses");
 
  }
 
 
 
  std::vector<Record *> getAllowedOnceClauses() const {
 
    return Def->getValueAsListOfDefs("allowedOnceClauses");
 
  }
 
 
 
  std::vector<Record *> getAllowedExclusiveClauses() const {
 
    return Def->getValueAsListOfDefs("allowedExclusiveClauses");
 
  }
 
 
 
  std::vector<Record *> getRequiredClauses() const {
 
    return Def->getValueAsListOfDefs("requiredClauses");
 
  }
 
};
 
 
 
// Wrapper class that contains Clause's information defined in DirectiveBase.td
 
// and provides helper methods for accessing it.
 
class Clause : public BaseRecord {
 
public:
 
  explicit Clause(const llvm::Record *Def) : BaseRecord(Def) {}
 
 
 
  // Optional field.
 
  StringRef getClangClass() const {
 
    return Def->getValueAsString("clangClass");
 
  }
 
 
 
  // Optional field.
 
  StringRef getFlangClass() const {
 
    return Def->getValueAsString("flangClass");
 
  }
 
 
 
  // Get the formatted name for Flang parser class. The generic formatted class
 
  // name is constructed from the name were the first letter of each word is
 
  // captitalized and the underscores are removed.
 
  // ex: async -> Async
 
  //     num_threads -> NumThreads
 
  std::string getFormattedParserClassName() {
 
    StringRef Name = Def->getValueAsString("name");
 
    std::string N = Name.str();
 
    bool Cap = true;
 
    std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) {
 
      if (Cap == true) {
 
        C = llvm::toUpper(C);
 
        Cap = false;
 
      } else if (C == '_') {
 
        Cap = true;
 
      }
 
      return C;
 
    });
 
    llvm::erase_value(N, '_');
 
    return N;
 
  }
 
 
 
  // Optional field.
 
  StringRef getEnumName() const {
 
    return Def->getValueAsString("enumClauseValue");
 
  }
 
 
 
  std::vector<Record *> getClauseVals() const {
 
    return Def->getValueAsListOfDefs("allowedClauseValues");
 
  }
 
 
 
  bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
 
 
 
  bool isValueList() const { return Def->getValueAsBit("isValueList"); }
 
 
 
  StringRef getDefaultValue() const {
 
    return Def->getValueAsString("defaultValue");
 
  }
 
 
 
  bool isImplicit() const { return Def->getValueAsBit("isImplicit"); }
 
 
 
  std::vector<StringRef> getAliases() const {
 
    return Def->getValueAsListOfStrings("aliases");
 
  }
 
 
 
  StringRef getPrefix() const { return Def->getValueAsString("prefix"); }
 
 
 
  bool isPrefixOptional() const {
 
    return Def->getValueAsBit("isPrefixOptional");
 
  }
 
};
 
 
 
// Wrapper class that contains VersionedClause's information defined in
 
// DirectiveBase.td and provides helper methods for accessing it.
 
class VersionedClause {
 
public:
 
  explicit VersionedClause(const llvm::Record *Def) : Def(Def) {}
 
 
 
  // Return the specific clause record wrapped in the Clause class.
 
  Clause getClause() const { return Clause{Def->getValueAsDef("clause")}; }
 
 
 
  int64_t getMinVersion() const { return Def->getValueAsInt("minVersion"); }
 
 
 
  int64_t getMaxVersion() const { return Def->getValueAsInt("maxVersion"); }
 
 
 
private:
 
  const llvm::Record *Def;
 
};
 
 
 
class ClauseVal : public BaseRecord {
 
public:
 
  explicit ClauseVal(const llvm::Record *Def) : BaseRecord(Def) {}
 
 
 
  int getValue() const { return Def->getValueAsInt("value"); }
 
 
 
  bool isUserVisible() const { return Def->getValueAsBit("isUserValue"); }
 
};
 
 
 
} // namespace llvm
 
 
 
#endif