11#include "llvm/ADT/BitVector.h"
12#include "llvm/Support/raw_ostream.h"
20 if (
auto *
T = dyn_cast<syntax::Tree>(N)) {
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;
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,
101 assert((!Begin || Begin->Parent ==
this) &&
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`.");
125 if (!
New && Begin == End)
129 for (
auto *
T =
this;
T &&
T->Original;
T =
T->Parent)
134 auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
137 for (
auto *N = Begin; N != End;) {
138 auto *
Next = N->NextSibling;
142 N->NextSibling =
nullptr;
143 N->PreviousSibling =
nullptr;
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,
174 const syntax::TokenManager &TM, llvm::BitVector IndentMask) {
175 auto DumpExtraInfo = [&
OS](
const syntax::Node *N) {
179 OS <<
" synthesized";
181 OS <<
" unmodifiable";
185 if (
const auto *L = dyn_cast<syntax::Leaf>(N)) {
199 for (
const syntax::Node &It :
T->getChildren()) {
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());
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()) {
284 if (
const auto *L = dyn_cast<syntax::Leaf>(&
C))
294 if (
const auto *L = dyn_cast<syntax::Leaf>(
C))
304 if (
C.getRole() == R)
310std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
315 std::vector<syntax::List::ElementAndDelimiter<Node>>
Children;
318 switch (
C.getRole()) {
320 if (ElementWithoutDelimiter) {
321 Children.push_back({ElementWithoutDelimiter,
nullptr});
323 ElementWithoutDelimiter = &
C;
328 ElementWithoutDelimiter =
nullptr;
333 "A list can have only elements and delimiters as children.");
339 Children.push_back({ElementWithoutDelimiter,
nullptr});
344 if (ElementWithoutDelimiter) {
345 Children.push_back({ElementWithoutDelimiter,
nullptr});
360 std::vector<syntax::Node *>
Children;
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.");
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:
416 case NodeKind::CallArguments:
417 case NodeKind::ParameterDeclarationList:
418 case NodeKind::DeclaratorList:
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...
const Tree * getParent() const
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
Node(NodeKind Kind)
Newly created nodes are detached from a tree, parent and sibling links are set when the node is added...
const Node * findChild(NodeRole R) const
Find the first node with a corresponding role.
llvm::iterator_range< ChildIterator > getChildren()
internal::Matcher< T > traverse(TraversalKind TK, const internal::Matcher< T > &InnerMatcher)
Causes all nested matchers to be matched with the specified traversal kind.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
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.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
U cast(CodeGen::Address addr)