AbstrSynTree.cpp
#include "AbstrSynTree.h"
#include "../Utilities/Utilities.h"
using namespace CodeAnalysis;
ASTNode::ASTNode()
: type_("anonymous"), parentType_("namespace"), name_("none"), startLineCount_(0), endLineCount_(0), complexity_(0) {}
ASTNode::ASTNode(const Type& type, const Name& name)
: type_(type), parentType_("namespace"), name_(name), startLineCount_(0), endLineCount_(0), complexity_(0) {}
ASTNode::~ASTNode()
{
for (auto pNode : children_)
delete pNode;
for (auto pNode : statements_)
delete pNode;
for (auto node : decl_)
{
delete node.pTc;
}
}
std::string ASTNode::show(bool details)
{
std::ostringstream temp;
temp << "(";
temp << type_ << ", ";
temp << parentType_ << ", ";
if(name_ != "none")
temp << name_ << ", ";
if(type_ == "namespace" || type_ == "class" || type_ == "interface" || type_ == "struct" || type_ == "function")
temp << package_ << ", ";
if (details)
{
temp << "num children: " << children_.size() << ", ";
temp << "num statements: " << statements_.size() << ", ";
}
temp << "line: " << startLineCount_ << ", ";
int size = static_cast<int>(endLineCount_ - startLineCount_ + 1);
if (size <= 0)
size = 1;
temp << "size: " << size << ", ";
temp << "cplx: " << complexity_;
temp << ")";
return temp.str();
}
AbstrSynTree::AbstrSynTree(ScopeStack<ASTNode*>& stack) : stack_(stack)
{
pGlobalNamespace_ = new ASTNode("namespace", "Global Namespace");
pGlobalNamespace_->startLineCount_ = 1;
pGlobalNamespace_->endLineCount_ = 1;
stack_.push(pGlobalNamespace_);
}
AbstrSynTree::~AbstrSynTree()
{
delete pGlobalNamespace_;
}
ASTNode*& AbstrSynTree::root()
{
return pGlobalNamespace_;
}
AbstrSynTree::TypeMap& AbstrSynTree::typeMap()
{
return typeMap_;
}
void AbstrSynTree::add(ASTNode* pNode)
{
if (stack_.size() > 0)
{
pNode->parentType_ = stack_.top()->type_;
stack_.top()->children_.push_back(pNode); }
else
{
pNode->parentType_ = "";
}
stack_.push(pNode); if (pNode->type_ == "class" || pNode->type_ == "struct" || pNode->type_ == "interface")
typeMap_[pNode->name_] = pNode;
}
ASTNode* AbstrSynTree::pop()
{
if(stack_.size() > 0)
return stack_.pop();
return nullptr;
}
ASTNode* AbstrSynTree::find(const ClassName& className)
{
auto iter = typeMap_.find(className);
if (iter != typeMap_.end())
{
return iter->second;
}
return nullptr;
}
#ifdef TEST_ABSTRSYNTREE
#include <functional>
#include <iostream>
using Utils = Utilities::StringHelper;
int main()
{
Utils::Title("Testing AbstrSynTree and ASTNode");
ScopeStack<ASTNode*> stack;
AbstrSynTree ast(stack);
ASTNode* pX = new ASTNode("class", "X");
ast.add(pX); ASTNode* pf1 = new ASTNode("function", "f1");
ast.add(pf1); ASTNode* pc1 = new ASTNode("control", "if");
ast.add(pc1); ASTNode* pf2 = new ASTNode("function", "f2");
ast.add(pf2);
std::function<void(ASTNode*, size_t)> co = [](ASTNode* pNode, size_t indentLevel)
{
std::cout << "\n " << std::string(2 * indentLevel, ' ') << pNode->show();
};
ASTWalk(ast.root(), co);
std::cout << "\n";
Utils::title("testing AbstrSynTree::find");
ASTNode* pFind = ast.find("X");
if (pFind != nullptr)
std::cout << "\n " << pFind->show();
else
std::cout << "\n could not find ASTNode for class X";
std::cout << "\n\n";
}
#endif