token_kind_test.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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/lex/token_kind.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include "llvm/ADT/StringRef.h"
  8. namespace Carbon::Lex {
  9. namespace {
  10. using ::testing::MatchesRegex;
  11. // We restrict symbols to punctuation characters that are expected to be widely
  12. // available on modern keyboards used for programming.
  13. constexpr llvm::StringLiteral SymbolRegex =
  14. R"([\[\]{}!@#%^&*()/?\\|;:.,<>=+~-]+)";
  15. // We restrict keywords to be lowercase ASCII letters and underscores with a few
  16. // specific exceptions.
  17. constexpr llvm::StringLiteral KeywordRegex = "[a-z_]+|Self|String";
  18. #define CARBON_TOKEN(TokenName) \
  19. TEST(TokenKindTest, TokenName) { \
  20. EXPECT_FALSE(TokenKind::TokenName.is_symbol()); \
  21. EXPECT_FALSE(TokenKind::TokenName.is_keyword()); \
  22. EXPECT_EQ("", TokenKind::TokenName.fixed_spelling()); \
  23. }
  24. #define CARBON_SYMBOL_TOKEN(TokenName, Spelling) \
  25. TEST(TokenKindTest, TokenName) { \
  26. EXPECT_TRUE(TokenKind::TokenName.is_symbol()); \
  27. EXPECT_FALSE(TokenKind::TokenName.is_grouping_symbol()); \
  28. EXPECT_FALSE(TokenKind::TokenName.is_opening_symbol()); \
  29. EXPECT_FALSE(TokenKind::TokenName.is_closing_symbol()); \
  30. EXPECT_FALSE(TokenKind::TokenName.is_keyword()); \
  31. EXPECT_EQ(Spelling, TokenKind::TokenName.fixed_spelling()); \
  32. EXPECT_THAT(Spelling, MatchesRegex(SymbolRegex.str())); \
  33. }
  34. #define CARBON_OPENING_GROUP_SYMBOL_TOKEN(TokenName, Spelling, ClosingName) \
  35. TEST(TokenKindTest, TokenName) { \
  36. EXPECT_TRUE(TokenKind::TokenName.is_symbol()); \
  37. EXPECT_TRUE(TokenKind::TokenName.is_grouping_symbol()); \
  38. EXPECT_TRUE(TokenKind::TokenName.is_opening_symbol()); \
  39. EXPECT_EQ(TokenKind::ClosingName, TokenKind::TokenName.closing_symbol()); \
  40. EXPECT_FALSE(TokenKind::TokenName.is_closing_symbol()); \
  41. EXPECT_FALSE(TokenKind::TokenName.is_keyword()); \
  42. EXPECT_EQ(Spelling, TokenKind::TokenName.fixed_spelling()); \
  43. EXPECT_THAT(Spelling, MatchesRegex(SymbolRegex.str())); \
  44. }
  45. #define CARBON_CLOSING_GROUP_SYMBOL_TOKEN(TokenName, Spelling, OpeningName) \
  46. TEST(TokenKindTest, TokenName) { \
  47. EXPECT_TRUE(TokenKind::TokenName.is_symbol()); \
  48. EXPECT_TRUE(TokenKind::TokenName.is_grouping_symbol()); \
  49. EXPECT_FALSE(TokenKind::TokenName.is_opening_symbol()); \
  50. EXPECT_TRUE(TokenKind::TokenName.is_closing_symbol()); \
  51. EXPECT_EQ(TokenKind::OpeningName, TokenKind::TokenName.opening_symbol()); \
  52. EXPECT_FALSE(TokenKind::TokenName.is_keyword()); \
  53. EXPECT_EQ(Spelling, TokenKind::TokenName.fixed_spelling()); \
  54. EXPECT_THAT(Spelling, MatchesRegex(SymbolRegex.str())); \
  55. }
  56. #define CARBON_KEYWORD_TOKEN(TokenName, Spelling) \
  57. TEST(TokenKindTest, TokenName) { \
  58. EXPECT_FALSE(TokenKind::TokenName.is_symbol()); \
  59. EXPECT_TRUE(TokenKind::TokenName.is_keyword()); \
  60. EXPECT_EQ(Spelling, TokenKind::TokenName.fixed_spelling()); \
  61. EXPECT_THAT(Spelling, MatchesRegex(KeywordRegex.str())); \
  62. }
  63. #include "toolchain/lex/token_kind.def"
  64. // Verify that the symbol tokens are sorted from longest to shortest. This is
  65. // important to ensure that simply in-order testing will identify tokens
  66. // following the max-munch rule.
  67. TEST(TokenKindTest, SymbolsInDescendingLength) {
  68. int previous_length = INT_MAX;
  69. #define CARBON_SYMBOL_TOKEN(TokenName, Spelling) \
  70. EXPECT_LE(llvm::StringRef(Spelling).size(), previous_length) \
  71. << "Symbol token not in descending length order: " << #TokenName; \
  72. previous_length = llvm::StringRef(Spelling).size();
  73. #include "toolchain/lex/token_kind.def"
  74. EXPECT_GT(previous_length, 0);
  75. }
  76. } // namespace
  77. } // namespace Carbon::Lex