ClangCommentCommandInfoEmitter.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This tablegen backend emits command lists and efficient matchers for command
  11. // names that are used in documentation comments.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/TableGen/Record.h"
  15. #include "llvm/TableGen/StringMatcher.h"
  16. #include "llvm/TableGen/TableGenBackend.h"
  17. #include <vector>
  18. using namespace llvm;
  19. namespace clang {
  20. void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
  21. emitSourceFileHeader("A list of commands useable in documentation "
  22. "comments", OS);
  23. OS << "namespace {\n"
  24. "const CommandInfo Commands[] = {\n";
  25. std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
  26. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  27. Record &Tag = *Tags[i];
  28. OS << " { "
  29. << "\"" << Tag.getValueAsString("Name") << "\", "
  30. << "\"" << Tag.getValueAsString("EndCommandName") << "\", "
  31. << i << ", "
  32. << Tag.getValueAsInt("NumArgs") << ", "
  33. << Tag.getValueAsBit("IsInlineCommand") << ", "
  34. << Tag.getValueAsBit("IsBlockCommand") << ", "
  35. << Tag.getValueAsBit("IsBriefCommand") << ", "
  36. << Tag.getValueAsBit("IsReturnsCommand") << ", "
  37. << Tag.getValueAsBit("IsParamCommand") << ", "
  38. << Tag.getValueAsBit("IsTParamCommand") << ", "
  39. << Tag.getValueAsBit("IsThrowsCommand") << ", "
  40. << Tag.getValueAsBit("IsDeprecatedCommand") << ", "
  41. << Tag.getValueAsBit("IsHeaderfileCommand") << ", "
  42. << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
  43. << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
  44. << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
  45. << Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
  46. << Tag.getValueAsBit("IsDeclarationCommand") << ", "
  47. << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", "
  48. << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", "
  49. << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", "
  50. << /* IsUnknownCommand = */ "0"
  51. << " }";
  52. if (i + 1 != e)
  53. OS << ",";
  54. OS << "\n";
  55. }
  56. OS << "};\n"
  57. "} // unnamed namespace\n\n";
  58. std::vector<StringMatcher::StringPair> Matches;
  59. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  60. Record &Tag = *Tags[i];
  61. std::string Name = Tag.getValueAsString("Name");
  62. std::string Return;
  63. raw_string_ostream(Return) << "return &Commands[" << i << "];";
  64. Matches.emplace_back(std::move(Name), std::move(Return));
  65. }
  66. OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
  67. << " StringRef Name) {\n";
  68. StringMatcher("Name", Matches, OS).Emit();
  69. OS << " return NULL;\n"
  70. << "}\n\n";
  71. }
  72. static std::string MangleName(StringRef Str) {
  73. std::string Mangled;
  74. for (unsigned i = 0, e = Str.size(); i != e; ++i) {
  75. switch (Str[i]) {
  76. default:
  77. Mangled += Str[i];
  78. break;
  79. case '[':
  80. Mangled += "lsquare";
  81. break;
  82. case ']':
  83. Mangled += "rsquare";
  84. break;
  85. case '{':
  86. Mangled += "lbrace";
  87. break;
  88. case '}':
  89. Mangled += "rbrace";
  90. break;
  91. case '$':
  92. Mangled += "dollar";
  93. break;
  94. case '/':
  95. Mangled += "slash";
  96. break;
  97. }
  98. }
  99. return Mangled;
  100. }
  101. void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
  102. emitSourceFileHeader("A list of commands useable in documentation "
  103. "comments", OS);
  104. OS << "#ifndef COMMENT_COMMAND\n"
  105. << "# define COMMENT_COMMAND(NAME)\n"
  106. << "#endif\n";
  107. std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
  108. for (size_t i = 0, e = Tags.size(); i != e; ++i) {
  109. Record &Tag = *Tags[i];
  110. std::string MangledName = MangleName(Tag.getValueAsString("Name"));
  111. OS << "COMMENT_COMMAND(" << MangledName << ")\n";
  112. }
  113. }
  114. } // end namespace clang