11#include "llvm/ADT/BitVector.h"
12#include "llvm/Support/raw_ostream.h"
13#include "llvm/Support/Casting.h"
21 if (
auto *
T = dyn_cast<syntax::Tree>(N)) {
38 :
Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
48void syntax::Node::setRole(
NodeRole NR) {
49 this->Role =
static_cast<unsigned>(NR);
52void syntax::Tree::appendChildLowLevel(Node *Child,
NodeRole Role) {
57 appendChildLowLevel(Child);
60void syntax::Tree::appendChildLowLevel(
Node *Child) {
61 assert(Child->Parent ==
nullptr);
62 assert(Child->NextSibling ==
nullptr);
63 assert(Child->PreviousSibling ==
nullptr);
67 if (this->LastChild) {
68 Child->PreviousSibling = this->LastChild;
69 this->LastChild->NextSibling = Child;
71 this->FirstChild = Child;
73 this->LastChild = Child;
76void syntax::Tree::prependChildLowLevel(Node *Child,
NodeRole Role) {
81 prependChildLowLevel(Child);
84void syntax::Tree::prependChildLowLevel(Node *Child) {
85 assert(Child->Parent ==
nullptr);
86 assert(Child->NextSibling ==
nullptr);
87 assert(Child->PreviousSibling ==
nullptr);
91 if (this->FirstChild) {
92 Child->NextSibling = this->FirstChild;
93 this->FirstChild->PreviousSibling = Child;
95 this->LastChild = Child;
97 this->FirstChild = Child;
100void syntax::Tree::replaceChildRangeLowLevel(Node *
Begin, Node *End,
103 "`Begin` is not a child of `this`.");
104 assert((!End || End->Parent ==
this) &&
"`End` is not a child of `this`.");
105 assert(canModify() &&
"Cannot modify `this`.");
108 for (
auto *N = New; N; N = N->NextSibling) {
109 assert(N->Parent ==
nullptr);
114 auto Reachable = [](
Node *From,
Node *N) {
117 for (
auto *It = From; It; It = It->NextSibling)
122 assert(Reachable(FirstChild,
Begin) &&
"`Begin` is not reachable.");
123 assert(Reachable(
Begin, End) &&
"`End` is not after `Begin`.");
126 if (!New &&
Begin == End)
130 for (
auto *
T =
this;
T &&
T->Original;
T =
T->Parent)
135 auto *BeforeBegin =
Begin ?
Begin->PreviousSibling : LastChild;
139 auto *Next = N->NextSibling;
143 N->NextSibling =
nullptr;
144 N->PreviousSibling =
nullptr;
146 traverse(N, [](Node *
C) {
C->Original =
false; });
152 auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
153 auto *&NewLast = End ? End->PreviousSibling : LastChild;
157 NewLast = BeforeBegin;
161 New->PreviousSibling = BeforeBegin;
165 for (
auto *N = New; N !=
nullptr; N = N->NextSibling) {
169 LastInNew->NextSibling = End;
174static void dumpNode(raw_ostream &OS,
const syntax::Node *N,
180 OS <<
" synthesized";
182 OS <<
" unmodifiable";
186 if (
const auto *L = dyn_cast<syntax::Leaf>(N)) {
188 OS << TM.
getText(L->getTokenKey());
195 const auto *
T = cast<syntax::Tree>(N);
201 for (
unsigned Idx = 0; Idx < IndentMask.size(); ++Idx) {
207 if (!It.getNextSibling()) {
209 IndentMask.push_back(
false);
212 IndentMask.push_back(
true);
214 dumpNode(OS, &It, TM, IndentMask);
215 IndentMask.pop_back();
222 llvm::raw_string_ostream OS(Str);
223 dumpNode(OS,
this, TM, {});
224 return std::move(OS.str());
229 llvm::raw_string_ostream OS(Storage);
231 if (
const auto *L = dyn_cast<syntax::Leaf>(N)) {
232 OS << TM.
getText(L->getTokenKey());
242 assert(getParent() ==
nullptr);
244 assert(getParent() !=
nullptr);
246 const auto *
T = dyn_cast<Tree>(
this);
249 for (
const Node &
C :
T->getChildren()) {
251 assert(
C.isOriginal());
252 assert(!
C.isDetached());
253 assert(
C.getParent() ==
T);
254 const auto *Next =
C.getNextSibling();
255 assert(!Next || &
C == Next->getPreviousSibling());
256 if (!
C.getNextSibling())
257 assert(&
C ==
T->getLastChild() &&
258 "Last child is reachable by advancing from the first child.");
261 const auto *L = dyn_cast<List>(
T);
264 for (
const Node &
C :
T->getChildren()) {
268 assert(isa<Leaf>(
C));
284 for (
const Node &
C : getChildren()) {
285 if (
const auto *L = dyn_cast<syntax::Leaf>(&
C))
287 if (
const auto *L = cast<syntax::Tree>(
C).findFirstLeaf())
294 for (
const auto *
C = getLastChild();
C;
C =
C->getPreviousSibling()) {
295 if (
const auto *L = dyn_cast<syntax::Leaf>(
C))
297 if (
const auto *L = cast<syntax::Tree>(
C)->findLastLeaf())
304 for (
const Node &
C : getChildren()) {
305 if (
C.getRole() == R)
311std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
313 if (!getFirstChild())
316 std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
318 for (
Node &
C : getChildren()) {
319 switch (
C.getRole()) {
321 if (ElementWithoutDelimiter) {
322 Children.push_back({ElementWithoutDelimiter,
nullptr});
324 ElementWithoutDelimiter = &
C;
328 Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(&
C)});
329 ElementWithoutDelimiter =
nullptr;
334 "A list can have only elements and delimiters as children.");
338 switch (getTerminationKind()) {
340 Children.push_back({ElementWithoutDelimiter,
nullptr});
345 if (ElementWithoutDelimiter) {
346 Children.push_back({ElementWithoutDelimiter,
nullptr});
358 if (!getFirstChild())
361 std::vector<syntax::Node *> Children;
363 for (
Node &
C : getChildren()) {
364 switch (
C.getRole()) {
366 if (ElementWithoutDelimiter) {
367 Children.push_back(ElementWithoutDelimiter);
369 ElementWithoutDelimiter = &
C;
373 Children.push_back(ElementWithoutDelimiter);
374 ElementWithoutDelimiter =
nullptr;
378 llvm_unreachable(
"A list has only elements or delimiters.");
382 switch (getTerminationKind()) {
384 Children.push_back(ElementWithoutDelimiter);
389 if (ElementWithoutDelimiter) {
390 Children.push_back(ElementWithoutDelimiter);
401 case NodeKind::NestedNameSpecifier:
402 return clang::tok::coloncolon;
403 case NodeKind::CallArguments:
404 case NodeKind::ParameterDeclarationList:
405 case NodeKind::DeclaratorList:
406 return clang::tok::comma;
408 llvm_unreachable(
"This is not a subclass of List, thus "
409 "getDelimiterTokenKind() cannot be called");
415 case NodeKind::NestedNameSpecifier:
416 return TerminationKind::Terminated;
417 case NodeKind::CallArguments:
418 case NodeKind::ParameterDeclarationList:
419 case NodeKind::DeclaratorList:
420 return TerminationKind::Separated;
422 llvm_unreachable(
"This is not a subclass of List, thus "
423 "getTerminationKind() cannot be called");
429 case NodeKind::NestedNameSpecifier:
431 case NodeKind::CallArguments:
433 case NodeKind::ParameterDeclarationList:
435 case NodeKind::DeclaratorList:
438 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