format_providers.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/diagnostics/format_providers.h"
  5. #include "common/check.h"
  6. #include "llvm/ADT/StringExtras.h"
  7. auto llvm::format_provider<Carbon::Diagnostics::BoolAsSelect>::format(
  8. const Carbon::Diagnostics::BoolAsSelect& wrapper, raw_ostream& out,
  9. StringRef style) -> void {
  10. if (style.empty()) {
  11. llvm::format_provider<bool>::format(wrapper.value, out, style);
  12. return;
  13. }
  14. auto sep = style.find('|');
  15. CARBON_CHECK(
  16. sep != llvm::StringRef::npos,
  17. "BoolAsSelect requires a `|` separating true and false results: `{0}`",
  18. style);
  19. CARBON_CHECK(style.find('|', sep + 1) == llvm::StringRef::npos,
  20. "BoolAsSelect only allows one `|`: `{0}`", style);
  21. if (wrapper.value) {
  22. out << style.take_front(sep);
  23. } else {
  24. out << style.drop_front(sep + 1);
  25. }
  26. }
  27. auto llvm::format_provider<Carbon::Diagnostics::IntAsSelect>::format(
  28. const Carbon::Diagnostics::IntAsSelect& wrapper, raw_ostream& out,
  29. StringRef style) -> void {
  30. if (style == "s") {
  31. if (wrapper.value != 1) {
  32. out << "s";
  33. }
  34. return;
  35. } else if (style.empty()) {
  36. llvm::format_provider<int>::format(wrapper.value, out, style);
  37. return;
  38. }
  39. auto cursor = style;
  40. while (!cursor.empty()) {
  41. auto case_sep = cursor.find("|");
  42. auto token = cursor.substr(0, case_sep);
  43. if (case_sep == llvm::StringRef::npos) {
  44. cursor = llvm::StringRef();
  45. } else {
  46. cursor = cursor.drop_front(case_sep + 1);
  47. }
  48. auto pair_sep = token.find(':');
  49. CARBON_CHECK(pair_sep != llvm::StringRef::npos,
  50. "IntAsSelect requires a `:` separating each comparison and "
  51. "output string: `{0}`",
  52. style);
  53. auto comp = token.take_front(pair_sep);
  54. auto output_string = token.drop_front(pair_sep + 1);
  55. if (comp.empty()) {
  56. // Default case.
  57. CARBON_CHECK(cursor.empty(),
  58. "IntAsSelect requires the default case be last: `{0}`",
  59. style);
  60. out << output_string;
  61. return;
  62. } else if (auto op = comp.take_while(
  63. [](char c) { return c == '<' || c == '=' || c == '>'; });
  64. !op.empty()) {
  65. // Comparison.
  66. comp = comp.drop_front(op.size());
  67. int value;
  68. CARBON_CHECK(to_integer(comp, value),
  69. "IntAsSelect has invalid value in comparison: `{0}`", style);
  70. auto result = llvm::StringSwitch<std::optional<bool>>(op)
  71. .Case("=", wrapper.value == value)
  72. .Case("<", wrapper.value < value)
  73. .Case("<=", wrapper.value <= value)
  74. .Case(">", wrapper.value > value)
  75. .Case(">=", wrapper.value >= value)
  76. .Default(std::nullopt);
  77. if (!result) {
  78. CARBON_FATAL("IntAsSelect has unrecognized comparison: `{0}`", style);
  79. }
  80. if (*result) {
  81. out << output_string;
  82. return;
  83. }
  84. } else {
  85. CARBON_FATAL("IntAsSelect has unrecognized syntax: `{0}`", style);
  86. }
  87. }
  88. CARBON_FATAL("IntAsSelect doesn't handle `{0}`: `{1}`", wrapper.value, style);
  89. }