Skip to content
Snippets Groups Projects
Commit 206793d7 authored by Erik Verbruggen's avatar Erik Verbruggen
Browse files

Pimped the ast dumping and added symbol dumping.

parent e9f33fb8
No related branches found
No related tags found
No related merge requests found
......@@ -40,6 +40,7 @@
#include <Names.h>
#include <CoreTypes.h>
#include <CppDocument.h>
#include <SymbolVisitor.h>
#include <QFile>
#include <QList>
......@@ -51,6 +52,7 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <cxxabi.h>
......@@ -63,27 +65,71 @@ public:
: ASTVisitor(unit) {}
void operator()(AST *ast) {
std::cout << "digraph AST {" << std::endl;
QByteArray basename = translationUnit()->fileName();
int dotIdx = basename.lastIndexOf('.');
if (dotIdx != -1)
basename.truncate(dotIdx);
basename.append(".ast.dot");
out.open(basename.constData());
out << "digraph AST {" << std::endl;
// std::cout << "rankdir = \"LR\";" << std::endl;
accept(ast);
std::cout << "}" << std::endl;
foreach (const QByteArray &terminalShape, _terminalShapes) {
out << std::string(terminalShape) << " [shape=rect]" << std::endl;
}
alignTerminals();
out << "}" << std::endl;
out.close();
std::cout << basename.constData() << std::endl;
}
protected:
std::string name(AST *ast) const {
void alignTerminals() {
out<<"{ rank=same; ";
foreach (const QByteArray &terminalShape, _terminalShapes) {
out << std::string(terminalShape) << "; ";
}
out<<"}"<<std::endl;
}
QByteArray addTerminalInfo(AST *ast) const {
if (SimpleNameAST *simpleName = ast->asSimpleName()) {
return spell(simpleName->identifier_token);
} else if (BinaryExpressionAST *binExpr = ast->asBinaryExpression()) {
return spell(binExpr->binary_op_token);
} else if (SimpleSpecifierAST *simpleSpec = ast->asSimpleSpecifier()) {
return spell(simpleSpec->specifier_token);
} else if (NumericLiteralAST *numLit = ast->asNumericLiteral()) {
return spell(numLit->literal_token);
} else if (StringLiteralAST *strLit = ast->asStringLiteral()) {
return spell(strLit->literal_token);
} else if (BoolLiteralAST *boolLit = ast->asBoolLiteral()) {
return spell(boolLit->literal_token);
} else {
return QByteArray();
}
}
std::string name(AST *ast) {
QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 11;
name.truncate(name.length() - 3);
name = QByteArray::number(_id.value(ast)) + ". " + name;
if (ast->lastToken() - ast->firstToken() == 1) {
const char *x = spell(ast->firstToken());
name += ' ';
name += x;
QByteArray info = addTerminalInfo(ast);
if (!info.isEmpty()) {
name.append("\\n");
name.append(info);
}
name.prepend('"');
name.append('"');
if (!info.isEmpty())
_terminalShapes.insert(name);
return std::string(name);
}
......@@ -92,7 +138,7 @@ protected:
_id[ast] = count++;
if (! _stack.isEmpty())
std::cout << name(_stack.last()) << " -> " << name(ast) << ";" << std::endl;
out << name(_stack.last()) << " -> " << name(ast) << ";" << std::endl;
_stack.append(ast);
......@@ -106,6 +152,151 @@ protected:
private:
QHash<AST *, int> _id;
QList<AST *> _stack;
QSet<QByteArray> _terminalShapes;
std::ofstream out;
};
class SymbolDump: protected SymbolVisitor
{
public:
SymbolDump(TranslationUnit *unit)
: translationUnit(unit)
{}
void operator()(Symbol *s) {
QByteArray basename = translationUnit->fileName();
int dotIdx = basename.lastIndexOf('.');
if (dotIdx != -1)
basename.truncate(dotIdx);
basename.append(".symbols.dot");
out.open(basename.constData());
out << "digraph Symbols {" << std::endl;
// std::cout << "rankdir = \"LR\";" << std::endl;
accept(s);
for (int i = 0; i < _connections.size(); ++i) {
QPair<Symbol*,Symbol*> connection = _connections.at(i);
QByteArray from = _id.value(connection.first);
if (from.isEmpty())
from = name(connection.first);
QByteArray to = _id.value(connection.second);
if (to.isEmpty())
to = name(connection.second);
out << from.constData() << " -> " << to.constData() << ";" << std::endl;
}
out << "}" << std::endl;
out.close();
std::cout << basename.constData() << std::endl;
}
protected:
QByteArray name(Symbol *s) {
QByteArray name = abi::__cxa_demangle(typeid(*s).name(), 0, 0, 0) + 11;
if (s->identifier()) {
name.append("\\nid: ");
name.append(s->identifier()->chars());
}
return name;
}
virtual bool preVisit(Symbol *s) {
static int count = 0;
QByteArray nodeId("s");
nodeId.append(QByteArray::number(++count));
_id[s] = nodeId;
if (!_stack.isEmpty())
_connections.append(qMakePair(_stack.last(), s));
_stack.append(s);
return true;
}
virtual void postVisit(Symbol *) {
_stack.removeLast();
}
virtual void simpleNode(Symbol *symbol) {
out << _id[symbol].constData() << " [label=\"" << name(symbol).constData() << "\"];" << std::endl;
}
void generateTemplateParams(const char *from, TemplateParameters *params) {
if (!params)
return;
static int templateCount = 0;
QByteArray id("t");
id.append(QByteArray::number(++templateCount));
out << from << " -> " << id.constData() << ";" << std::endl;
out << id.constData() << " [shape=record label=\"";
for (unsigned i = 0; i < params->scope()->symbolCount(); ++i) {
if (i > 0)
out<<"|";
Symbol *s = params->scope()->symbolAt(i);
if (s->identifier()) {
out<<s->identifier()->chars();
} else {
out << "<anonymous>";
}
}
out << "\"];" << std::endl;
}
virtual bool visit(Class *symbol) {
const char *id = _id.value(symbol).constData();
out << id << " [label=\"";
if (symbol->isClass()) {
out << "class";
} else if (symbol->isStruct()) {
out << "struct";
} else if (symbol->isUnion()) {
out << "union";
} else {
out << "UNKNOWN";
}
out << "\\nid: ";
if (symbol->identifier()) {
out << symbol->identifier()->chars();
} else {
out << "NO ID";
}
out << "\"];" << std::endl;
generateTemplateParams(id, symbol->templateParameters());
return true;
}
virtual bool visit(UsingNamespaceDirective *symbol) { simpleNode(symbol); return true; }
virtual bool visit(UsingDeclaration *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Declaration *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Argument *symbol) { simpleNode(symbol); return true; }
virtual bool visit(TypenameArgument *symbol) { simpleNode(symbol); return true; }
virtual bool visit(BaseClass *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Enum *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Function *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Namespace *symbol) { simpleNode(symbol); return true; }
virtual bool visit(Block *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ForwardClassDeclaration *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCBaseClass *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCBaseProtocol *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCClass *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCForwardClassDeclaration *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCProtocol *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCForwardProtocolDeclaration *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCMethod *symbol) { simpleNode(symbol); return true; }
virtual bool visit(ObjCPropertyDeclaration *symbol) { simpleNode(symbol); return true; }
private:
TranslationUnit *translationUnit;
QHash<Symbol *, QByteArray> _id;
QList<QPair<Symbol *,Symbol*> >_connections;
QList<Symbol *> _stack;
std::ofstream out;
};
int main(int argc, char *argv[])
......@@ -117,8 +308,11 @@ int main(int argc, char *argv[])
foreach (const QString &fileName, files) {
QFile file(fileName);
if (! file.open(QFile::ReadOnly))
if (! file.open(QFile::ReadOnly)) {
std::cerr << "Cannot open \"" << qPrintable(fileName)
<< "\", skipping it." << std::endl;
continue;
}
const QByteArray source = file.readAll();
file.close();
......@@ -128,8 +322,13 @@ int main(int argc, char *argv[])
doc->setSource(source);
doc->parse();
doc->check();
ASTDump dump(doc->translationUnit());
dump(doc->translationUnit()->ast());
SymbolDump dump2(doc->translationUnit());
dump2(doc->globalNamespace());
}
return EXIT_SUCCESS;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment