Translating an AST with clang RecursiveASTVisitor - c++

The RecursiveASTVisitor class implements a stateless visitor for the AST of some source. I would like to process the AST into some JSON that describes the parent classes, methods and their arguments, etc. RecursiveASTVisitor doesn't really seem to have facilities for returning stuff up to parent node visits or passing stuff down to child node visitors, so I'm not sure how I'm meant to maintain the context of the tree traversal.
What's the right way to traverse the AST while building up my own tree?

Related

What is the difference between AST traversal by Cursors and Nodes

I'm playing with libclang to parse small c++ files. I've seen examples about how to parse the AST trees.
As I understood AST constitutes of ASTNodes which has the type of either Decl or Stmt. To traverse the tree I can either use the ASTConsumer which visits ASTNodes or CxCursors.
What is the difference between these two traversal methods?
Both are part of the same method of AST traversal as the cursors are pointers on AST nodes. If you look for a different method of AST traversal you should look into AST matchers. With that method you define a model of AST that you want to match against the AST of a source file. It can be a powerful method.
Here is an introduction to matching with Clang: https://clang.llvm.org/docs/LibASTMatchers.html
After having read some pages, I found some information about this subject. According to the clang Tooling documentation there are two tools (among other clang tools) :
- Libclang
- Libtooling
The CxCursors belongs to the Libclang library. The Libclang library provides the cursors to traverse the AST although the control on the AST is limited.
The classes Decl and Stmt are the part of the Libtooling. By defining a RecursiveASTVisitor and its corresponding visiting function one can traverse these nodes. With this method one can have full control over on the AST.

ParseTree traversal in antlr4

I am using antlr4 c++.
I have a ParseTree and I am trying to recreate the tree structure.
To to this I am using a Visitor my_Visitor and my own node object(s).
My problem is that visitChildren(tree::RuleNode*) calls the visit functions of all children, so I am losing the information when one child tree is traversed and the next child tree is visited.
Assume a tree like this:
A
/ \
B C
When I call visitChildren(A) (using overloaded visitExpression(ExpressionContext*) functions for B and C), I can extract the information that the visit sequence is A,B,C.
This sequence could also result from:
A
|
B
|
C
To recreate the tree I think I would need something like
antlrcpp::Any my_Visitor::my_visitChildren(tree::RuleNode* A){
for(int i=0;i<A->children.size();i++){
//create a new node in my own tree representation as child of A
visit(A->children[i]);
}
}
and call my_visitChildren in my overloaded visitExpression functions.
The problem here is that A->children[i] is a Tree and visit(.) needs a ParseTree.
Can I somehow create a ParseTree from children[i] or is there a better approach to do this?
I am also thinking about using a map from tree->parent to my objects and just attach my new node there, but this is not optimal if I wanted to omit some nodes (e.g. for an AST).
The differentiation between a ParseTree and a Tree is purely artificial and in fact of no real use. The children of a tree node are in fact all ParseTree instances. There are a few tree classes that are never used in the runtime, except for building the base classes of ParseTree. Hence later on I have removed Tree, SyntaxTree and RuleNode and put all that together into the ParseTree class.
To answer your question: you can safely cast the child nodes to ParseTree for your tree walk.

How to visit only decl nodes behind a specified class declaration in Clang?

I'm writing a clang tool that parses a given interface header in C++, and I need to only visit the nodes behind the declaration of the given interface class (i.e. only the member functions that belongs to the class and its parameters, ignoring the includes, attributes, and other stuff).
I'm using a RecursiveASTVisitor inherited class, so all its traverse and visitor methods are available. Maybe I don't understand at all the behaviour of the RecursiveASTVisitor, but until now I've tried to override the TraverseCXXRecordDecl, then check if the decl name is the same that the interface I'm looking for and finally visit all its children nodes. In this case the problem is that I don't know how to get an iterator or something that gives a reference to the children of a given Decl. I've looked in the API of clang, but I hadn't seen any function for this purpose. Also, I want to know if that is a good approach. Somebody has some other solution ?

Tree source code with modification

I'm looking for a tree implementation that has functionality that allows you to insert a child at a given location. Most trees out there, you can only do plain old insert, Tree.insert(x), and depending on the tree type, it goes to a particular tree location.
I seek code that supports something like Tree.insert(node, x), which means to make x the direct child of node
IF anyone knows of a somewhat efficient tree source code (C++ or C) that doesn't use the STL and satifies the above, it would be greatly appreciated.
Check out tree.hh, which provides an STL-like tree interface. There are insert and append_child member functions that accept an iterator and a value to insert, just as you describe. Unless you have very specialised needs, it’s almost certainly sufficient performancewise.

Issue while designing B+Tree template class in C++

I'm trying to write a generic C++ implementation of B+Tree. My problem comes from the fact that there are two kinds of nodes in a B+Tree; the internal nodes, which contain keys and pointers to child nodes, and leaf nodes, which contain keys and values, and pointers in an internal node can either point to other internal nodes, or leaf nodes.
I can't figure how to model such a relationship with templates (I don't want to use casts or virtual classes).
Hope there is a solution to my problem or a better way to implement B+Tree in C++.
The simplest way:
bool mIsInternalPointer;
union {
InternalNode<T>* mInternalNode;
LeafNode<T>* mLeafNode;
};
This can be somewhat simplified by using boost::variant :)