token_kind.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. #ifndef TOOLCHAIN_LEXER_TOKEN_KIND_H_
  5. #define TOOLCHAIN_LEXER_TOKEN_KIND_H_
  6. #include <cstdint>
  7. #include <initializer_list>
  8. #include <iterator>
  9. #include "llvm/ADT/StringRef.h"
  10. namespace Carbon {
  11. class TokenKind {
  12. // Note that this must be declared earlier in the class so that its type can
  13. // be used, for example in the conversion operator.
  14. enum class KindEnum : int8_t {
  15. #define CARBON_TOKEN(TokenName) TokenName,
  16. #include "toolchain/lexer/token_registry.def"
  17. };
  18. public:
  19. // The formatting for this macro is weird due to a `clang-format` bug. See
  20. // https://bugs.llvm.org/show_bug.cgi?id=48320 for details.
  21. #define CARBON_TOKEN(TokenName) \
  22. static constexpr auto TokenName()->TokenKind { \
  23. return TokenKind(KindEnum::TokenName); \
  24. }
  25. #include "toolchain/lexer/token_registry.def"
  26. // The default constructor is deleted as objects of this type should always be
  27. // constructed using the above factory functions for each unique kind.
  28. TokenKind() = delete;
  29. friend auto operator==(TokenKind lhs, TokenKind rhs) -> bool {
  30. return lhs.kind_value_ == rhs.kind_value_;
  31. }
  32. friend auto operator!=(TokenKind lhs, TokenKind rhs) -> bool {
  33. return lhs.kind_value_ != rhs.kind_value_;
  34. }
  35. // Get a friendly name for the token for logging or debugging.
  36. [[nodiscard]] auto Name() const -> llvm::StringRef;
  37. // Test whether this kind of token is a simple symbol sequence (punctuation,
  38. // not letters) that appears directly in the source text and can be
  39. // unambiguously lexed with `starts_with` logic. While these may appear
  40. // inside of other tokens, outside of the contents of other tokens they
  41. // don't require any specific characters before or after to distinguish them
  42. // in the source. Returns false otherwise.
  43. [[nodiscard]] auto IsSymbol() const -> bool;
  44. // Test whether this kind of token is a grouping symbol (part of an opening
  45. // and closing pair that must always be matched in the token stream).
  46. [[nodiscard]] auto IsGroupingSymbol() const -> bool;
  47. // Test whether this kind of token is an opening symbol for a group.
  48. [[nodiscard]] auto IsOpeningSymbol() const -> bool;
  49. // Returns the associated closing symbol for an opening symbol.
  50. //
  51. // The token kind must be an opening symbol.
  52. [[nodiscard]] auto GetClosingSymbol() const -> TokenKind;
  53. // Test whether this kind of token is a closing symbol for a group.
  54. [[nodiscard]] auto IsClosingSymbol() const -> bool;
  55. // Returns the associated opening symbol for a closing symbol.
  56. //
  57. // The token kind must be a closing symbol.
  58. [[nodiscard]] auto GetOpeningSymbol() const -> TokenKind;
  59. // Test whether this kind of token is a keyword.
  60. [[nodiscard]] auto IsKeyword() const -> bool;
  61. // Test whether this kind of token is a sized type literal.
  62. [[nodiscard]] auto IsSizedTypeLiteral() const -> bool;
  63. // If this token kind has a fixed spelling when in source code, returns it.
  64. // Otherwise returns an empty string.
  65. [[nodiscard]] auto GetFixedSpelling() const -> llvm::StringRef;
  66. // Test whether this token kind is in the provided list.
  67. [[nodiscard]] auto IsOneOf(std::initializer_list<TokenKind> kinds) const
  68. -> bool {
  69. for (TokenKind kind : kinds) {
  70. if (*this == kind) {
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. // Enable conversion to our private enum, including in a `constexpr` context,
  77. // to enable usage in `switch` and `case`. The enum remains private and
  78. // nothing else should be using this.
  79. // NOLINTNEXTLINE(google-explicit-constructor)
  80. constexpr operator KindEnum() const { return kind_value_; }
  81. private:
  82. constexpr explicit TokenKind(KindEnum kind_value) : kind_value_(kind_value) {}
  83. KindEnum kind_value_;
  84. };
  85. } // namespace Carbon
  86. #endif // TOOLCHAIN_LEXER_TOKEN_KIND_H_