File: BracketTest.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (117 lines) | stat: -rw-r--r-- 3,805 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//===--- BracketTest.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang-pseudo/Bracket.h"
#include "clang-pseudo/Token.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/Testing/Support/Annotations.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace clang {
namespace pseudo {

// Return a version of Code with each paired bracket marked with ^.
std::string decorate(llvm::StringRef Code, const TokenStream &Stream) {
  std::string Result;
  const char *Pos = Code.data();
  for (const Token &Tok : Stream.tokens()) {
    if (Tok.Pair == 0)
      continue;
    const char *NewPos = Tok.text().begin();
    assert(NewPos >= Code.begin() && NewPos < Code.end());
    Result.append(Pos, NewPos - Pos);
    Result.push_back('^');
    Pos = NewPos;
  }
  Result.append(Pos, Code.end() - Pos);
  return Result;
}

// Checks that the brackets matched in Stream are those annotated in MarkedCode.
void verifyMatchedSet(llvm::StringRef Code, llvm::StringRef MarkedCode,
                      const TokenStream &Stream) {
  EXPECT_EQ(MarkedCode, decorate(Code, Stream));
}

// Checks that paired brackets within the stream nest properly.
void verifyNesting(const TokenStream &Stream) {
  std::vector<const Token *> Stack;
  for (const auto &Tok : Stream.tokens()) {
    if (Tok.Pair > 0)
      Stack.push_back(&Tok);
    else if (Tok.Pair < 0) {
      ASSERT_FALSE(Stack.empty()) << Tok;
      ASSERT_EQ(Stack.back(), Tok.pair())
          << *Stack.back() << " != " << *Tok.pair() << " = pair of " << Tok;
      Stack.pop_back();
    }
  }
  ASSERT_THAT(Stack, testing::IsEmpty());
}

// Checks that ( pairs with a ) on its right, etc.
void verifyMatchKind(const TokenStream &Stream) {
  for (const auto &Tok : Stream.tokens()) {
    if (Tok.Pair == 0)
      continue;
    auto Want = [&]() -> std::pair<bool, tok::TokenKind> {
      switch (Tok.Kind) {
      case tok::l_paren:
        return {true, tok::r_paren};
      case tok::r_paren:
        return {false, tok::l_paren};
      case tok::l_brace:
        return {true, tok::r_brace};
      case tok::r_brace:
        return {false, tok::l_brace};
      case tok::l_square:
        return {true, tok::r_square};
      case tok::r_square:
        return {false, tok::l_square};
      default:
        ADD_FAILURE() << "Paired non-bracket " << Tok;
        return {false, tok::eof};
      }
    }();
    EXPECT_EQ(Tok.Pair > 0, Want.first) << Tok;
    EXPECT_EQ(Tok.pair()->Kind, Want.second) << Tok;
  }
}

// Verifies an expected bracket pairing like:
//   ^( [ ^)
// The input is annotated code, with the brackets expected to be matched marked.
//
// The input doesn't specify which bracket matches with which, but we verify:
//  - exactly the marked subset are paired
//  - ( is paired to a later ), etc
//  - brackets properly nest
// This uniquely determines the bracket structure, so we indirectly verify it.
// If particular tests should emphasize which brackets are paired, use comments.
void verifyBrackets(llvm::StringRef MarkedCode) {
  SCOPED_TRACE(MarkedCode);
  llvm::Annotations A(MarkedCode);
  std::string Code = A.code().str();
  LangOptions LangOpts;
  auto Stream = lex(Code, LangOpts);
  pairBrackets(Stream);

  verifyMatchedSet(Code, MarkedCode, Stream);
  verifyNesting(Stream);
  verifyMatchKind(Stream);
}

TEST(Bracket, SimplePair) {
  verifyBrackets("^{ ^[ ^( ^)  ^( ^) ^] ^}");
  verifyBrackets(") ^{ ^[ ^] ^} (");
  verifyBrackets("{ [ ( ] }"); // FIXME
}

} // namespace pseudo
} // namespace clang