11#include "llvm/ADT/BitVector.h"
12#include "llvm/Support/raw_ostream.h"
20 if (
auto *
T = dyn_cast<syntax::Tree>(N)) {
37 :
Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
47void syntax::Node::setRole(
NodeRole NR) {
48 this->Role =
static_cast<unsigned>(NR);
51void syntax::Tree::appendChildLowLevel(Node *Child,
NodeRole Role) {
56 appendChildLowLevel(Child);
59void syntax::Tree::appendChildLowLevel(
Node *Child) {
60 assert(Child->Parent ==
nullptr);
61 assert(Child->NextSibling ==
nullptr);
62 assert(Child->PreviousSibling ==
nullptr);
66 if (this->LastChild) {
67 Child->PreviousSibling = this->LastChild;
68 this->LastChild->NextSibling = Child;
70 this->FirstChild = Child;
72 this->LastChild = Child;
75void syntax::Tree::prependChildLowLevel(
Node *Child,
NodeRole Role) {
80 prependChildLowLevel(Child);
83void syntax::Tree::prependChildLowLevel(Node *Child) {
84 assert(Child->Parent ==
nullptr);
85 assert(Child->NextSibling ==
nullptr);
86 assert(Child->PreviousSibling ==
nullptr);
90 if (this->FirstChild) {
91 Child->NextSibling = this->FirstChild;
92 this->FirstChild->PreviousSibling = Child;
94 this->LastChild = Child;
96 this->FirstChild = Child;
99void syntax::Tree::replaceChildRangeLowLevel(Node *
Begin, Node *End,
102 "`Begin` is not a child of `this`.");
103 assert((!End || End->Parent ==
this) &&
"`End` is not a child of `this`.");
104 assert(canModify() &&
"Cannot modify `this`.");
107 for (
auto *N =
New; N; N = N->NextSibling) {
108 assert(N->Parent ==
nullptr);
113 auto Reachable = [](
Node *From,
Node *N) {
116 for (
auto *It = From; It; It = It->NextSibling)
121 assert(Reachable(FirstChild,
Begin) &&
"`Begin` is not reachable.");
122 assert(Reachable(
Begin, End) &&
"`End` is not after `Begin`.");
129 for (
auto *
T =
this;
T &&
T->Original;
T =
T->Parent)
134 auto *BeforeBegin =
Begin ?
Begin->PreviousSibling : LastChild;
138 auto *Next = N->NextSibling;
142 N->NextSibling =
nullptr;
143 N->PreviousSibling =
nullptr;
145 traverse(N, [](Node *
C) {
C->Original =
false; });
151 auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
152 auto *&NewLast = End ? End->PreviousSibling : LastChild;
156 NewLast = BeforeBegin;
160 New->PreviousSibling = BeforeBegin;
164 for (
auto *N =
New; N !=
nullptr; N = N->NextSibling) {
168 LastInNew->NextSibling = End;
173static void dumpNode(raw_ostream &OS,
const syntax::Node *N,
179 OS <<
" synthesized";
181 OS <<
" unmodifiable";
185 if (
const auto *L = dyn_cast<syntax::Leaf>(N)) {
187 OS << TM.
getText(L->getTokenKey());
194 const auto *
T = cast<syntax::Tree>(N);
200 for (
unsigned Idx = 0; Idx < IndentMask.size(); ++Idx) {
206 if (!It.getNextSibling()) {
208 IndentMask.push_back(
false);
211 IndentMask.push_back(
true);
213 dumpNode(OS, &It, TM, IndentMask);
214 IndentMask.pop_back();
221 llvm::raw_string_ostream OS(Str);
222 dumpNode(OS,
this, TM, {});
223 return std::move(OS.str());
228 llvm::raw_string_ostream OS(Storage);
230 if (
const auto *L = dyn_cast<syntax::Leaf>(N)) {
231 OS << TM.
getText(L->getTokenKey());
241 assert(getParent() ==
nullptr);
243 assert(getParent() !=
nullptr);
245 const auto *
T = dyn_cast<Tree>(
this);
248 for (
const Node &
C :
T->getChildren()) {
250 assert(
C.isOriginal());
251 assert(!
C.isDetached());
252 assert(
C.getParent() ==
T);
253 const auto *Next =
C.getNextSibling();
254 assert(!Next || &
C == Next->getPreviousSibling());
255 if (!
C.getNextSibling())
256 assert(&
C ==
T->getLastChild() &&
257 "Last child is reachable by advancing from the first child.");
260 const auto *L = dyn_cast<List>(
T);
263 for (
const Node &
C :
T->getChildren()) {
267 assert(isa<Leaf>(
C));
283 for (
const Node &
C : getChildren()) {
284 if (
const auto *L = dyn_cast<syntax::Leaf>(&
C))
286 if (
const auto *L = cast<syntax::Tree>(
C).findFirstLeaf())
293 for (
const auto *
C = getLastChild();
C;
C =
C->getPreviousSibling()) {
294 if (
const auto *L = dyn_cast<syntax::Leaf>(
C))
296 if (
const auto *L = cast<syntax::Tree>(
C)->findLastLeaf())
303 for (
const Node &
C : getChildren()) {
304 if (
C.getRole() == R)
310std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
312 if (!getFirstChild())
315 std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
317 for (
Node &
C : getChildren()) {
318 switch (
C.getRole()) {
320 if (ElementWithoutDelimiter) {
321 Children.push_back({ElementWithoutDelimiter,
nullptr});
323 ElementWithoutDelimiter = &
C;
327 Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&
C)});
328 ElementWithoutDelimiter =
nullptr;
333 "A list can have only elements and delimiters as children.");
337 switch (getTerminationKind()) {
339 Children.push_back({ElementWithoutDelimiter,
nullptr});
344 if (ElementWithoutDelimiter) {
345 Children.push_back({ElementWithoutDelimiter,
nullptr});
357 if (!getFirstChild())
360 std::vector<syntax::Node *> Children;
362 for (
Node &
C : getChildren()) {
363 switch (
C.getRole()) {
365 if (ElementWithoutDelimiter) {
366 Children.push_back(ElementWithoutDelimiter);
368 ElementWithoutDelimiter = &
C;
372 Children.push_back(ElementWithoutDelimiter);
373 ElementWithoutDelimiter =
nullptr;
377 llvm_unreachable(
"A list has only elements or delimiters.");
381 switch (getTerminationKind()) {
383 Children.push_back(ElementWithoutDelimiter);
388 if (ElementWithoutDelimiter) {
389 Children.push_back(ElementWithoutDelimiter);
400 case NodeKind::NestedNameSpecifier:
401 return clang::tok::coloncolon;
402 case NodeKind::CallArguments:
403 case NodeKind::ParameterDeclarationList:
404 case NodeKind::DeclaratorList:
405 return clang::tok::comma;
407 llvm_unreachable(
"This is not a subclass of List, thus "
408 "getDelimiterTokenKind() cannot be called");
414 case NodeKind::NestedNameSpecifier:
415 return TerminationKind::Terminated;
416 case NodeKind::CallArguments:
417 case NodeKind::ParameterDeclarationList:
418 case NodeKind::DeclaratorList:
419 return TerminationKind::Separated;
421 llvm_unreachable(
"This is not a subclass of List, thus "
422 "getTerminationKind() cannot be called");
428 case NodeKind::NestedNameSpecifier:
430 case NodeKind::CallArguments:
432 case NodeKind::ParameterDeclarationList:
434 case NodeKind::DeclaratorList:
437 llvm_unreachable(
"This is not a subclass of List, thus canBeEmpty() "
static Decl::Kind getKind(const Decl *D)
Defines the clang::TokenKind enum and support functions.
A leaf node points to a single token.
Leaf(TokenManager::Key K)
bool canBeEmpty() const
Whether this list can be empty in syntactically and semantically correct code.
std::vector< Node * > getElementsAsNodes()
Returns the elements of the list.
std::vector< ElementAndDelimiter< Node > > getElementsAsNodesAndDelimiters()
Returns the elements and corresponding delimiters.
TerminationKind getTerminationKind() const
clang::tok::TokenKind getDelimiterTokenKind() const
Returns the appropriate delimiter for this list.
void assertInvariants() const
Asserts invariants on this node of the tree and its immediate children.
bool canModify() const
If this function return false, the tree cannot be modified because there is no reasonable way to prod...
void assertInvariantsRecursive() const
Runs checkInvariants on all nodes in the subtree. No-op if NDEBUG is set.
Node(NodeKind Kind)
Newly created nodes are detached from a tree, parent and sibling links are set when the node is added...
std::string dump(const TokenManager &SM) const
Dumps the structure of a subtree. For debugging and testing purposes.
std::string dumpTokens(const TokenManager &SM) const
Dumps the tokens forming this subtree.
bool isOriginal() const
Whether the node was created from the AST backed by the source code rather than added later through m...
bool isDetached() const
Whether the node is detached from a tree, i.e. does not have a parent.
Defines interfaces for operating "Token" in the clang syntax-tree.
uintptr_t Key
A key to identify a specific token.
virtual llvm::StringRef getText(Key K) const =0
const Leaf * findLastLeaf() const
const Leaf * findFirstLeaf() const
const Node * findChild(NodeRole R) const
Find the first node with a corresponding role.
internal::Matcher< T > traverse(TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
NodeRole
A relation between a parent and child node, e.g.
@ ListElement
List API roles.
@ Detached
A node without a parent.
@ Unknown
Children of an unknown semantic nature, e.g. skipped tokens, comments.
NodeKind
A kind of a syntax node, used for implementing casts.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
The JSON file list parser is used to communicate input to InstallAPI.
for(const auto &A :T->param_types())
const FunctionProtoType * T