10b57cec5SDimitry Andric //===- Tree.cpp -----------------------------------------------*- C++ -*-=====//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "clang/Tooling/Syntax/Tree.h"
90b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
100b57cec5SDimitry Andric #include "clang/Tooling/Syntax/Nodes.h"
1104eeddc0SDimitry Andric #include "llvm/ADT/BitVector.h"
12*fcaf7f86SDimitry Andric #include "llvm/Support/raw_ostream.h"
130b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
14480093f4SDimitry Andric #include <cassert>
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric using namespace clang;
170b57cec5SDimitry Andric
18480093f4SDimitry Andric namespace {
traverse(const syntax::Node * N,llvm::function_ref<void (const syntax::Node *)> Visit)19480093f4SDimitry Andric static void traverse(const syntax::Node *N,
20480093f4SDimitry Andric llvm::function_ref<void(const syntax::Node *)> Visit) {
21480093f4SDimitry Andric if (auto *T = dyn_cast<syntax::Tree>(N)) {
22e8d8bef9SDimitry Andric for (const syntax::Node &C : T->getChildren())
23e8d8bef9SDimitry Andric traverse(&C, Visit);
24480093f4SDimitry Andric }
25480093f4SDimitry Andric Visit(N);
26480093f4SDimitry Andric }
traverse(syntax::Node * N,llvm::function_ref<void (syntax::Node *)> Visit)27480093f4SDimitry Andric static void traverse(syntax::Node *N,
28480093f4SDimitry Andric llvm::function_ref<void(syntax::Node *)> Visit) {
29480093f4SDimitry Andric traverse(static_cast<const syntax::Node *>(N), [&](const syntax::Node *N) {
30480093f4SDimitry Andric Visit(const_cast<syntax::Node *>(N));
31480093f4SDimitry Andric });
32480093f4SDimitry Andric }
33480093f4SDimitry Andric } // namespace
34480093f4SDimitry Andric
Leaf(syntax::TokenManager::Key K)35*fcaf7f86SDimitry Andric syntax::Leaf::Leaf(syntax::TokenManager::Key K) : Node(NodeKind::Leaf), K(K) {}
360b57cec5SDimitry Andric
Node(NodeKind Kind)370b57cec5SDimitry Andric syntax::Node::Node(NodeKind Kind)
38e8d8bef9SDimitry Andric : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
39e8d8bef9SDimitry Andric Kind(static_cast<unsigned>(Kind)), Role(0), Original(false),
40e8d8bef9SDimitry Andric CanModify(false) {
415ffd83dbSDimitry Andric this->setRole(NodeRole::Detached);
425ffd83dbSDimitry Andric }
43480093f4SDimitry Andric
isDetached() const44e8d8bef9SDimitry Andric bool syntax::Node::isDetached() const {
45e8d8bef9SDimitry Andric return getRole() == NodeRole::Detached;
46e8d8bef9SDimitry Andric }
470b57cec5SDimitry Andric
setRole(NodeRole NR)485ffd83dbSDimitry Andric void syntax::Node::setRole(NodeRole NR) {
495ffd83dbSDimitry Andric this->Role = static_cast<unsigned>(NR);
505ffd83dbSDimitry Andric }
515ffd83dbSDimitry Andric
appendChildLowLevel(Node * Child,NodeRole Role)52e8d8bef9SDimitry Andric void syntax::Tree::appendChildLowLevel(Node *Child, NodeRole Role) {
53e8d8bef9SDimitry Andric assert(Child->getRole() == NodeRole::Detached);
54e8d8bef9SDimitry Andric assert(Role != NodeRole::Detached);
55e8d8bef9SDimitry Andric
56e8d8bef9SDimitry Andric Child->setRole(Role);
57e8d8bef9SDimitry Andric appendChildLowLevel(Child);
58e8d8bef9SDimitry Andric }
59e8d8bef9SDimitry Andric
appendChildLowLevel(Node * Child)60e8d8bef9SDimitry Andric void syntax::Tree::appendChildLowLevel(Node *Child) {
61e8d8bef9SDimitry Andric assert(Child->Parent == nullptr);
62e8d8bef9SDimitry Andric assert(Child->NextSibling == nullptr);
63e8d8bef9SDimitry Andric assert(Child->PreviousSibling == nullptr);
64e8d8bef9SDimitry Andric assert(Child->getRole() != NodeRole::Detached);
65e8d8bef9SDimitry Andric
66e8d8bef9SDimitry Andric Child->Parent = this;
67e8d8bef9SDimitry Andric if (this->LastChild) {
68e8d8bef9SDimitry Andric Child->PreviousSibling = this->LastChild;
69e8d8bef9SDimitry Andric this->LastChild->NextSibling = Child;
70e8d8bef9SDimitry Andric } else
71e8d8bef9SDimitry Andric this->FirstChild = Child;
72e8d8bef9SDimitry Andric
73e8d8bef9SDimitry Andric this->LastChild = Child;
74e8d8bef9SDimitry Andric }
750b57cec5SDimitry Andric
prependChildLowLevel(Node * Child,NodeRole Role)760b57cec5SDimitry Andric void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
77e8d8bef9SDimitry Andric assert(Child->getRole() == NodeRole::Detached);
780b57cec5SDimitry Andric assert(Role != NodeRole::Detached);
790b57cec5SDimitry Andric
805ffd83dbSDimitry Andric Child->setRole(Role);
815ffd83dbSDimitry Andric prependChildLowLevel(Child);
825ffd83dbSDimitry Andric }
835ffd83dbSDimitry Andric
prependChildLowLevel(Node * Child)845ffd83dbSDimitry Andric void syntax::Tree::prependChildLowLevel(Node *Child) {
855ffd83dbSDimitry Andric assert(Child->Parent == nullptr);
865ffd83dbSDimitry Andric assert(Child->NextSibling == nullptr);
87e8d8bef9SDimitry Andric assert(Child->PreviousSibling == nullptr);
88e8d8bef9SDimitry Andric assert(Child->getRole() != NodeRole::Detached);
895ffd83dbSDimitry Andric
900b57cec5SDimitry Andric Child->Parent = this;
91e8d8bef9SDimitry Andric if (this->FirstChild) {
920b57cec5SDimitry Andric Child->NextSibling = this->FirstChild;
93e8d8bef9SDimitry Andric this->FirstChild->PreviousSibling = Child;
94e8d8bef9SDimitry Andric } else
95e8d8bef9SDimitry Andric this->LastChild = Child;
96e8d8bef9SDimitry Andric
970b57cec5SDimitry Andric this->FirstChild = Child;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric
replaceChildRangeLowLevel(Node * Begin,Node * End,Node * New)100e8d8bef9SDimitry Andric void syntax::Tree::replaceChildRangeLowLevel(Node *Begin, Node *End,
101480093f4SDimitry Andric Node *New) {
102e8d8bef9SDimitry Andric assert((!Begin || Begin->Parent == this) &&
103e8d8bef9SDimitry Andric "`Begin` is not a child of `this`.");
104e8d8bef9SDimitry Andric assert((!End || End->Parent == this) && "`End` is not a child of `this`.");
105e8d8bef9SDimitry Andric assert(canModify() && "Cannot modify `this`.");
106480093f4SDimitry Andric
107480093f4SDimitry Andric #ifndef NDEBUG
108e8d8bef9SDimitry Andric for (auto *N = New; N; N = N->NextSibling) {
109480093f4SDimitry Andric assert(N->Parent == nullptr);
110e8d8bef9SDimitry Andric assert(N->getRole() != NodeRole::Detached && "Roles must be set");
1115e801ac6SDimitry Andric // FIXME: validate the role.
112480093f4SDimitry Andric }
113e8d8bef9SDimitry Andric
114e8d8bef9SDimitry Andric auto Reachable = [](Node *From, Node *N) {
115e8d8bef9SDimitry Andric if (!N)
116e8d8bef9SDimitry Andric return true;
117e8d8bef9SDimitry Andric for (auto *It = From; It; It = It->NextSibling)
118e8d8bef9SDimitry Andric if (It == N)
119e8d8bef9SDimitry Andric return true;
120e8d8bef9SDimitry Andric return false;
121e8d8bef9SDimitry Andric };
122e8d8bef9SDimitry Andric assert(Reachable(FirstChild, Begin) && "`Begin` is not reachable.");
123e8d8bef9SDimitry Andric assert(Reachable(Begin, End) && "`End` is not after `Begin`.");
124480093f4SDimitry Andric #endif
125480093f4SDimitry Andric
126e8d8bef9SDimitry Andric if (!New && Begin == End)
127e8d8bef9SDimitry Andric return;
128e8d8bef9SDimitry Andric
129e8d8bef9SDimitry Andric // Mark modification.
130e8d8bef9SDimitry Andric for (auto *T = this; T && T->Original; T = T->Parent)
131e8d8bef9SDimitry Andric T->Original = false;
132e8d8bef9SDimitry Andric
133e8d8bef9SDimitry Andric // Save the node before the range to be removed. Later we insert the `New`
134e8d8bef9SDimitry Andric // range after this node.
135e8d8bef9SDimitry Andric auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
136e8d8bef9SDimitry Andric
137480093f4SDimitry Andric // Detach old nodes.
138e8d8bef9SDimitry Andric for (auto *N = Begin; N != End;) {
139480093f4SDimitry Andric auto *Next = N->NextSibling;
140480093f4SDimitry Andric
1415ffd83dbSDimitry Andric N->setRole(NodeRole::Detached);
142480093f4SDimitry Andric N->Parent = nullptr;
143480093f4SDimitry Andric N->NextSibling = nullptr;
144e8d8bef9SDimitry Andric N->PreviousSibling = nullptr;
145480093f4SDimitry Andric if (N->Original)
146e8d8bef9SDimitry Andric traverse(N, [](Node *C) { C->Original = false; });
147480093f4SDimitry Andric
148480093f4SDimitry Andric N = Next;
149480093f4SDimitry Andric }
150480093f4SDimitry Andric
151e8d8bef9SDimitry Andric // Attach new range.
152e8d8bef9SDimitry Andric auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
153e8d8bef9SDimitry Andric auto *&NewLast = End ? End->PreviousSibling : LastChild;
154480093f4SDimitry Andric
155e8d8bef9SDimitry Andric if (!New) {
156e8d8bef9SDimitry Andric NewFirst = End;
157e8d8bef9SDimitry Andric NewLast = BeforeBegin;
158e8d8bef9SDimitry Andric return;
159e8d8bef9SDimitry Andric }
160e8d8bef9SDimitry Andric
161e8d8bef9SDimitry Andric New->PreviousSibling = BeforeBegin;
162e8d8bef9SDimitry Andric NewFirst = New;
163e8d8bef9SDimitry Andric
164e8d8bef9SDimitry Andric Node *LastInNew;
165e8d8bef9SDimitry Andric for (auto *N = New; N != nullptr; N = N->NextSibling) {
166e8d8bef9SDimitry Andric LastInNew = N;
167480093f4SDimitry Andric N->Parent = this;
168480093f4SDimitry Andric }
169e8d8bef9SDimitry Andric LastInNew->NextSibling = End;
170e8d8bef9SDimitry Andric NewLast = LastInNew;
171480093f4SDimitry Andric }
172480093f4SDimitry Andric
1730b57cec5SDimitry Andric namespace {
dumpNode(raw_ostream & OS,const syntax::Node * N,const syntax::TokenManager & TM,llvm::BitVector IndentMask)174e8d8bef9SDimitry Andric static void dumpNode(raw_ostream &OS, const syntax::Node *N,
175*fcaf7f86SDimitry Andric const syntax::TokenManager &TM, llvm::BitVector IndentMask) {
176e8d8bef9SDimitry Andric auto DumpExtraInfo = [&OS](const syntax::Node *N) {
177e8d8bef9SDimitry Andric if (N->getRole() != syntax::NodeRole::Unknown)
178e8d8bef9SDimitry Andric OS << " " << N->getRole();
179480093f4SDimitry Andric if (!N->isOriginal())
180e8d8bef9SDimitry Andric OS << " synthesized";
181480093f4SDimitry Andric if (!N->canModify())
182e8d8bef9SDimitry Andric OS << " unmodifiable";
183e8d8bef9SDimitry Andric };
184480093f4SDimitry Andric
185e8d8bef9SDimitry Andric assert(N);
186e8d8bef9SDimitry Andric if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
187e8d8bef9SDimitry Andric OS << "'";
188*fcaf7f86SDimitry Andric OS << TM.getText(L->getTokenKey());
189e8d8bef9SDimitry Andric OS << "'";
190e8d8bef9SDimitry Andric DumpExtraInfo(N);
1910b57cec5SDimitry Andric OS << "\n";
1920b57cec5SDimitry Andric return;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
195e8d8bef9SDimitry Andric const auto *T = cast<syntax::Tree>(N);
196e8d8bef9SDimitry Andric OS << T->getKind();
197e8d8bef9SDimitry Andric DumpExtraInfo(N);
198e8d8bef9SDimitry Andric OS << "\n";
1990b57cec5SDimitry Andric
200e8d8bef9SDimitry Andric for (const syntax::Node &It : T->getChildren()) {
20104eeddc0SDimitry Andric for (unsigned Idx = 0; Idx < IndentMask.size(); ++Idx) {
20204eeddc0SDimitry Andric if (IndentMask[Idx])
2030b57cec5SDimitry Andric OS << "| ";
2040b57cec5SDimitry Andric else
2050b57cec5SDimitry Andric OS << " ";
2060b57cec5SDimitry Andric }
207e8d8bef9SDimitry Andric if (!It.getNextSibling()) {
2080b57cec5SDimitry Andric OS << "`-";
2090b57cec5SDimitry Andric IndentMask.push_back(false);
2100b57cec5SDimitry Andric } else {
2110b57cec5SDimitry Andric OS << "|-";
2120b57cec5SDimitry Andric IndentMask.push_back(true);
2130b57cec5SDimitry Andric }
214*fcaf7f86SDimitry Andric dumpNode(OS, &It, TM, IndentMask);
2150b57cec5SDimitry Andric IndentMask.pop_back();
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric } // namespace
2190b57cec5SDimitry Andric
dump(const TokenManager & TM) const220*fcaf7f86SDimitry Andric std::string syntax::Node::dump(const TokenManager &TM) const {
2210b57cec5SDimitry Andric std::string Str;
2220b57cec5SDimitry Andric llvm::raw_string_ostream OS(Str);
223*fcaf7f86SDimitry Andric dumpNode(OS, this, TM, /*IndentMask=*/{});
2240b57cec5SDimitry Andric return std::move(OS.str());
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric
dumpTokens(const TokenManager & TM) const227*fcaf7f86SDimitry Andric std::string syntax::Node::dumpTokens(const TokenManager &TM) const {
2280b57cec5SDimitry Andric std::string Storage;
2290b57cec5SDimitry Andric llvm::raw_string_ostream OS(Storage);
2300b57cec5SDimitry Andric traverse(this, [&](const syntax::Node *N) {
231e8d8bef9SDimitry Andric if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
232*fcaf7f86SDimitry Andric OS << TM.getText(L->getTokenKey());
233480093f4SDimitry Andric OS << " ";
234e8d8bef9SDimitry Andric }
2350b57cec5SDimitry Andric });
2360eae32dcSDimitry Andric return Storage;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
assertInvariants() const239480093f4SDimitry Andric void syntax::Node::assertInvariants() const {
240480093f4SDimitry Andric #ifndef NDEBUG
241480093f4SDimitry Andric if (isDetached())
242e8d8bef9SDimitry Andric assert(getParent() == nullptr);
243480093f4SDimitry Andric else
244e8d8bef9SDimitry Andric assert(getParent() != nullptr);
245480093f4SDimitry Andric
246e8d8bef9SDimitry Andric const auto *T = dyn_cast<Tree>(this);
247480093f4SDimitry Andric if (!T)
248480093f4SDimitry Andric return;
249e8d8bef9SDimitry Andric for (const Node &C : T->getChildren()) {
250480093f4SDimitry Andric if (T->isOriginal())
251e8d8bef9SDimitry Andric assert(C.isOriginal());
252e8d8bef9SDimitry Andric assert(!C.isDetached());
253e8d8bef9SDimitry Andric assert(C.getParent() == T);
254e8d8bef9SDimitry Andric const auto *Next = C.getNextSibling();
255e8d8bef9SDimitry Andric assert(!Next || &C == Next->getPreviousSibling());
256e8d8bef9SDimitry Andric if (!C.getNextSibling())
257e8d8bef9SDimitry Andric assert(&C == T->getLastChild() &&
258e8d8bef9SDimitry Andric "Last child is reachable by advancing from the first child.");
259480093f4SDimitry Andric }
260e8d8bef9SDimitry Andric
261e8d8bef9SDimitry Andric const auto *L = dyn_cast<List>(T);
262e8d8bef9SDimitry Andric if (!L)
263e8d8bef9SDimitry Andric return;
264e8d8bef9SDimitry Andric for (const Node &C : T->getChildren()) {
265e8d8bef9SDimitry Andric assert(C.getRole() == NodeRole::ListElement ||
266e8d8bef9SDimitry Andric C.getRole() == NodeRole::ListDelimiter);
267e8d8bef9SDimitry Andric if (C.getRole() == NodeRole::ListDelimiter) {
268e8d8bef9SDimitry Andric assert(isa<Leaf>(C));
269*fcaf7f86SDimitry Andric // FIXME: re-enable it when there is way to retrieve token kind in Leaf.
270*fcaf7f86SDimitry Andric // assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
271e8d8bef9SDimitry Andric }
272e8d8bef9SDimitry Andric }
273e8d8bef9SDimitry Andric
274480093f4SDimitry Andric #endif
275480093f4SDimitry Andric }
276480093f4SDimitry Andric
assertInvariantsRecursive() const277480093f4SDimitry Andric void syntax::Node::assertInvariantsRecursive() const {
278480093f4SDimitry Andric #ifndef NDEBUG
279480093f4SDimitry Andric traverse(this, [&](const syntax::Node *N) { N->assertInvariants(); });
280480093f4SDimitry Andric #endif
281480093f4SDimitry Andric }
282480093f4SDimitry Andric
findFirstLeaf() const283e8d8bef9SDimitry Andric const syntax::Leaf *syntax::Tree::findFirstLeaf() const {
284e8d8bef9SDimitry Andric for (const Node &C : getChildren()) {
285e8d8bef9SDimitry Andric if (const auto *L = dyn_cast<syntax::Leaf>(&C))
286480093f4SDimitry Andric return L;
287e8d8bef9SDimitry Andric if (const auto *L = cast<syntax::Tree>(C).findFirstLeaf())
288480093f4SDimitry Andric return L;
289480093f4SDimitry Andric }
290480093f4SDimitry Andric return nullptr;
291480093f4SDimitry Andric }
292480093f4SDimitry Andric
findLastLeaf() const293e8d8bef9SDimitry Andric const syntax::Leaf *syntax::Tree::findLastLeaf() const {
294e8d8bef9SDimitry Andric for (const auto *C = getLastChild(); C; C = C->getPreviousSibling()) {
295e8d8bef9SDimitry Andric if (const auto *L = dyn_cast<syntax::Leaf>(C))
296e8d8bef9SDimitry Andric return L;
297e8d8bef9SDimitry Andric if (const auto *L = cast<syntax::Tree>(C)->findLastLeaf())
298e8d8bef9SDimitry Andric return L;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric return nullptr;
3010b57cec5SDimitry Andric }
302e8d8bef9SDimitry Andric
findChild(NodeRole R) const303e8d8bef9SDimitry Andric const syntax::Node *syntax::Tree::findChild(NodeRole R) const {
304e8d8bef9SDimitry Andric for (const Node &C : getChildren()) {
305e8d8bef9SDimitry Andric if (C.getRole() == R)
306e8d8bef9SDimitry Andric return &C;
307e8d8bef9SDimitry Andric }
308e8d8bef9SDimitry Andric return nullptr;
309e8d8bef9SDimitry Andric }
310e8d8bef9SDimitry Andric
311e8d8bef9SDimitry Andric std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
getElementsAsNodesAndDelimiters()312e8d8bef9SDimitry Andric syntax::List::getElementsAsNodesAndDelimiters() {
313e8d8bef9SDimitry Andric if (!getFirstChild())
314e8d8bef9SDimitry Andric return {};
315e8d8bef9SDimitry Andric
316e8d8bef9SDimitry Andric std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
317e8d8bef9SDimitry Andric syntax::Node *ElementWithoutDelimiter = nullptr;
318e8d8bef9SDimitry Andric for (Node &C : getChildren()) {
319e8d8bef9SDimitry Andric switch (C.getRole()) {
320e8d8bef9SDimitry Andric case syntax::NodeRole::ListElement: {
321e8d8bef9SDimitry Andric if (ElementWithoutDelimiter) {
322e8d8bef9SDimitry Andric Children.push_back({ElementWithoutDelimiter, nullptr});
323e8d8bef9SDimitry Andric }
324e8d8bef9SDimitry Andric ElementWithoutDelimiter = &C;
325e8d8bef9SDimitry Andric break;
326e8d8bef9SDimitry Andric }
327e8d8bef9SDimitry Andric case syntax::NodeRole::ListDelimiter: {
328e8d8bef9SDimitry Andric Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&C)});
329e8d8bef9SDimitry Andric ElementWithoutDelimiter = nullptr;
330e8d8bef9SDimitry Andric break;
331e8d8bef9SDimitry Andric }
332e8d8bef9SDimitry Andric default:
333e8d8bef9SDimitry Andric llvm_unreachable(
334e8d8bef9SDimitry Andric "A list can have only elements and delimiters as children.");
335e8d8bef9SDimitry Andric }
336e8d8bef9SDimitry Andric }
337e8d8bef9SDimitry Andric
338e8d8bef9SDimitry Andric switch (getTerminationKind()) {
339e8d8bef9SDimitry Andric case syntax::List::TerminationKind::Separated: {
340e8d8bef9SDimitry Andric Children.push_back({ElementWithoutDelimiter, nullptr});
341e8d8bef9SDimitry Andric break;
342e8d8bef9SDimitry Andric }
343e8d8bef9SDimitry Andric case syntax::List::TerminationKind::Terminated:
344e8d8bef9SDimitry Andric case syntax::List::TerminationKind::MaybeTerminated: {
345e8d8bef9SDimitry Andric if (ElementWithoutDelimiter) {
346e8d8bef9SDimitry Andric Children.push_back({ElementWithoutDelimiter, nullptr});
347e8d8bef9SDimitry Andric }
348e8d8bef9SDimitry Andric break;
349e8d8bef9SDimitry Andric }
350e8d8bef9SDimitry Andric }
351e8d8bef9SDimitry Andric
352e8d8bef9SDimitry Andric return Children;
353e8d8bef9SDimitry Andric }
354e8d8bef9SDimitry Andric
355e8d8bef9SDimitry Andric // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
356e8d8bef9SDimitry Andric // ignoring delimiters
getElementsAsNodes()357e8d8bef9SDimitry Andric std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
358e8d8bef9SDimitry Andric if (!getFirstChild())
359e8d8bef9SDimitry Andric return {};
360e8d8bef9SDimitry Andric
361e8d8bef9SDimitry Andric std::vector<syntax::Node *> Children;
362e8d8bef9SDimitry Andric syntax::Node *ElementWithoutDelimiter = nullptr;
363e8d8bef9SDimitry Andric for (Node &C : getChildren()) {
364e8d8bef9SDimitry Andric switch (C.getRole()) {
365e8d8bef9SDimitry Andric case syntax::NodeRole::ListElement: {
366e8d8bef9SDimitry Andric if (ElementWithoutDelimiter) {
367e8d8bef9SDimitry Andric Children.push_back(ElementWithoutDelimiter);
368e8d8bef9SDimitry Andric }
369e8d8bef9SDimitry Andric ElementWithoutDelimiter = &C;
370e8d8bef9SDimitry Andric break;
371e8d8bef9SDimitry Andric }
372e8d8bef9SDimitry Andric case syntax::NodeRole::ListDelimiter: {
373e8d8bef9SDimitry Andric Children.push_back(ElementWithoutDelimiter);
374e8d8bef9SDimitry Andric ElementWithoutDelimiter = nullptr;
375e8d8bef9SDimitry Andric break;
376e8d8bef9SDimitry Andric }
377e8d8bef9SDimitry Andric default:
378e8d8bef9SDimitry Andric llvm_unreachable("A list has only elements or delimiters.");
379e8d8bef9SDimitry Andric }
380e8d8bef9SDimitry Andric }
381e8d8bef9SDimitry Andric
382e8d8bef9SDimitry Andric switch (getTerminationKind()) {
383e8d8bef9SDimitry Andric case syntax::List::TerminationKind::Separated: {
384e8d8bef9SDimitry Andric Children.push_back(ElementWithoutDelimiter);
385e8d8bef9SDimitry Andric break;
386e8d8bef9SDimitry Andric }
387e8d8bef9SDimitry Andric case syntax::List::TerminationKind::Terminated:
388e8d8bef9SDimitry Andric case syntax::List::TerminationKind::MaybeTerminated: {
389e8d8bef9SDimitry Andric if (ElementWithoutDelimiter) {
390e8d8bef9SDimitry Andric Children.push_back(ElementWithoutDelimiter);
391e8d8bef9SDimitry Andric }
392e8d8bef9SDimitry Andric break;
393e8d8bef9SDimitry Andric }
394e8d8bef9SDimitry Andric }
395e8d8bef9SDimitry Andric
396e8d8bef9SDimitry Andric return Children;
397e8d8bef9SDimitry Andric }
398e8d8bef9SDimitry Andric
getDelimiterTokenKind() const399e8d8bef9SDimitry Andric clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const {
400e8d8bef9SDimitry Andric switch (this->getKind()) {
401e8d8bef9SDimitry Andric case NodeKind::NestedNameSpecifier:
402e8d8bef9SDimitry Andric return clang::tok::coloncolon;
403e8d8bef9SDimitry Andric case NodeKind::CallArguments:
404e8d8bef9SDimitry Andric case NodeKind::ParameterDeclarationList:
405e8d8bef9SDimitry Andric case NodeKind::DeclaratorList:
406e8d8bef9SDimitry Andric return clang::tok::comma;
407e8d8bef9SDimitry Andric default:
408e8d8bef9SDimitry Andric llvm_unreachable("This is not a subclass of List, thus "
409e8d8bef9SDimitry Andric "getDelimiterTokenKind() cannot be called");
410e8d8bef9SDimitry Andric }
411e8d8bef9SDimitry Andric }
412e8d8bef9SDimitry Andric
getTerminationKind() const413e8d8bef9SDimitry Andric syntax::List::TerminationKind syntax::List::getTerminationKind() const {
414e8d8bef9SDimitry Andric switch (this->getKind()) {
415e8d8bef9SDimitry Andric case NodeKind::NestedNameSpecifier:
416e8d8bef9SDimitry Andric return TerminationKind::Terminated;
417e8d8bef9SDimitry Andric case NodeKind::CallArguments:
418e8d8bef9SDimitry Andric case NodeKind::ParameterDeclarationList:
419e8d8bef9SDimitry Andric case NodeKind::DeclaratorList:
420e8d8bef9SDimitry Andric return TerminationKind::Separated;
421e8d8bef9SDimitry Andric default:
422e8d8bef9SDimitry Andric llvm_unreachable("This is not a subclass of List, thus "
423e8d8bef9SDimitry Andric "getTerminationKind() cannot be called");
424e8d8bef9SDimitry Andric }
425e8d8bef9SDimitry Andric }
426e8d8bef9SDimitry Andric
canBeEmpty() const427e8d8bef9SDimitry Andric bool syntax::List::canBeEmpty() const {
428e8d8bef9SDimitry Andric switch (this->getKind()) {
429e8d8bef9SDimitry Andric case NodeKind::NestedNameSpecifier:
430e8d8bef9SDimitry Andric return false;
431e8d8bef9SDimitry Andric case NodeKind::CallArguments:
432e8d8bef9SDimitry Andric return true;
433e8d8bef9SDimitry Andric case NodeKind::ParameterDeclarationList:
434e8d8bef9SDimitry Andric return true;
435e8d8bef9SDimitry Andric case NodeKind::DeclaratorList:
436e8d8bef9SDimitry Andric return true;
437e8d8bef9SDimitry Andric default:
438e8d8bef9SDimitry Andric llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "
439e8d8bef9SDimitry Andric "cannot be called");
440e8d8bef9SDimitry Andric }
441e8d8bef9SDimitry Andric }
442