Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Parser/C++/syn/dumper.cc
    1| // Synopsis C++ Parser: dumper.cc source file
    2| // Implementation of the TypeFormatter and Dumper classes
    3| 
    4| // $Id: dumper.cc,v 1.23 2003/01/27 06:53:37 chalky Exp $
    5| //
    6| // This file is a part of Synopsis.
    7| // Copyright (C) 2002 Stephen Davies
    8| //
    9| // Synopsis is free software; you can redistribute it and/or modify it
   10| // under the terms of the GNU General Public License as published by
   11| // the Free Software Foundation; either version 2 of the License, or
   12| // (at your option) any later version.
   13| //
   14| // This program is distributed in the hope that it will be useful,
   15| // but WITHOUT ANY WARRANTY; without even the implied warranty of
   16| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17| // General Public License for more details.
   18| //
   19| // You should have received a copy of the GNU General Public License
   20| // along with this program; if not, write to the Free Software
   21| // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   22| // 02111-1307, USA.
   23| 
   24| // $Log: dumper.cc,v $
   25| // Revision 1.23  2003/01/27 06:53:37  chalky
   26| // Added macro support for C++.
   27| //
   28| // Revision 1.22  2002/12/09 04:01:00  chalky
   29| // Added multiple file support to parsers, changed AST datastructure to handle
   30| // new information, added a demo to demo/C++. AST Declarations now have a
   31| // reference to a SourceFile (which includes a filename) instead of a filename.
   32| //
   33| // Revision 1.21  2002/11/17 12:11:43  chalky
   34| // Reformatted all files with astyle --style=ansi, renamed fakegc.hh
   35| //
   36| //
   37| 
   38| 
   39| #include "common.hh"
   40| #include "dumper.hh"
   41| #include <iostream>
   42| 
   43| //
   44| //
   45| // TypeFormatter
   46| //
   47| //
   48| 
   49| TypeFormatter::TypeFormatter()
   50|         : m_fptr_id(NULL)
   51| {
   52|     m_scope_stack.push_back(ScopedName());
   53| }
   54| 
   55| void TypeFormatter::push_scope(const ScopedName& scope)
   56| {
   57|     m_scope_stack.push_back(m_scope);
   58|     m_scope = scope;
   59| }
   60| 
   61| void TypeFormatter::pop_scope()
   62| {
   63|     m_scope = m_scope_stack.back();
   64|     m_scope_stack.pop_back();
   65| }
   66| 
   67| std::string TypeFormatter::colonate(const ScopedName& name)
   68| {
   69|     std::string str;
   70|     ScopedName::const_iterator n_iter = name.begin();
   71|     ScopedName::const_iterator s_iter = m_scope.begin();
   72|     // Skip identical scopes
   73|     while ((n_iter != name.end()) && (s_iter != m_scope.end()) && (*n_iter == *s_iter))
   74|         ++n_iter, ++s_iter;
   75|     // If name == scope, just return last eg: struct S { S* ptr; };
   76|     if (n_iter == name.end())
   77|         return name.back();
   78|     // Join the rest in name with colons
   79|     str = *n_iter++;
   80|     while (n_iter != name.end())
   81|         str += "::" + *n_iter++;
   82|     return str;
   83| }
   84| 
   85| 
   86| 
   87| //
   88| // Type Visitor
   89| //
   90| 
   91| std::string TypeFormatter::format(const Types::Type* type, const std::string** id)
   92| {
   93|     if (!type)
   94|         return "(unknown)";
   95|     const std::string** save = NULL;
   96|     if (id)
   97|     {
   98|         save = m_fptr_id;
   99|         m_fptr_id = id;
  100|     }
  101|     const_cast<Types::Type*>(type)->accept(this);
  102|     if (id)
  103|         m_fptr_id = save;
  104|     return m_type;
  105| }
  106| 
  107| void TypeFormatter::visit_type(Types::Type* type)
  108| {
  109|     m_type = "(unknown)";
  110| }
  111| 
  112| void TypeFormatter::visit_unknown(Types::Unknown* type)
  113| {
  114|     m_type = colonate(type->name());
  115| }
  116| 
  117| void TypeFormatter::visit_modifier(Types::Modifier* type)
  118| {
  119|     // Premods
  120|     std::string pre = "";
  121|     Types::Type::Mods::iterator iter = type->pre().begin();
  122|     while (iter != type->pre().end())
  123|         if (*iter == "*" || *iter == "&")
  124|             pre += *iter++;
  125|         else
  126|             pre += *iter++ + " ";
  127|     // Alias
  128|     m_type = pre + format(type->alias());
  129|     // Postmods
  130|     iter = type->post().begin();
  131|     while (iter != type->post().end())
  132|         if (*iter == "*" || *iter == "&")
  133|             m_type += *iter++;
  134|         else
  135|             m_type += " " + *iter++;
  136| }
  137| 
  138| void TypeFormatter::visit_named(Types::Named* type)
  139| {
  140|     m_type = colonate(type->name());
  141| }
  142| 
  143| void TypeFormatter::visit_base(Types::Base* type)
  144| {
  145|     m_type = colonate(type->name());
  146| }
  147| 
  148| void TypeFormatter::visit_declared(Types::Declared* type)
  149| {
  150|     m_type = colonate(type->name());
  151| }
  152| 
  153| void TypeFormatter::visit_template_type(Types::Template* type)
  154| {
  155|     m_type = colonate(type->name());
  156| }
  157| 
  158| void TypeFormatter::visit_parameterized(Types::Parameterized* type)
  159| {
  160|     std::string str;
  161|     if (type->template_type())
  162|         str = colonate(type->template_type()->name()) + "<";
  163|     else
  164|         str = "(unknown)<";
  165|     if (type->parameters().size())
  166|     {
  167|         str += format(type->parameters().front());
  168|         Types::Type::vector::iterator iter = type->parameters().begin();
  169|         while (++iter != type->parameters().end())
  170|             str += "," + format(*iter);
  171|     }
  172|     m_type = str + ">";
  173| }
  174| 
  175| void TypeFormatter::visit_func_ptr(Types::FuncPtr* type)
  176| {
  177|     std::string str = format(type->return_type()) + "(";
  178|     Types::Type::Mods::iterator i_pre = type->pre().begin();
  179|     while (i_pre != type->pre().end())
  180|         str += *i_pre++;
  181|     if (m_fptr_id)
  182|     {
  183|         str += **m_fptr_id;
  184|         *m_fptr_id = NULL;
  185|     }
  186|     str += ")(";
  187|     if (type->parameters().size())
  188|     {
  189|         str += format(type->parameters().front());
  190|         Types::Type::vector::iterator iter = type->parameters().begin();
  191|         while (++iter != type->parameters().end())
  192|             str += "," + format(*iter);
  193|     }
  194|     m_type = str + ")";
  195| 
  196| }
  197| 
  198| 
  199| 
  200| 
  201| 
  202| //
  203| //
  204| // Dumper
  205| //
  206| //
  207| 
  208| Dumper::Dumper()
  209| {
  210|     m_indent = 0;
  211|     m_indent_string = "";
  212| }
  213| 
  214| void Dumper::onlyShow(const std::string &fname)
  215| {
  216|     m_filename = fname;
  217| }
  218| 
  219| void Dumper::indent()
  220| {
  221|     ++m_indent;
  222|     m_indent_string.assign(m_indent' ');
  223| }
  224| 
  225| void Dumper::undent()
  226| {
  227|     --m_indent;
  228|     m_indent_string.assign(m_indent' ');
  229| }
  230| 
  231| std::string append(const std::vector<std::string>& strs, const std::string &sep = " ")
  232| {
  233|     std::vector<std::string>::const_iterator iter = strs.begin();
  234|     std::string str = "";
  235|     while (iter != strs.end())
  236|         str += *iter++ + sep;
  237|     return str;
  238| }
  239| 
  240| //. Utility method
  241| // string colonate(const Types::Name& name)
  242| // {
  243| //     if (!name.size()) return "";
  244| //     string str = name[0];
  245| //     Types::Name::const_iterator iter = name.begin();
  246| //     while (++iter != name.end())
  247| //      str += "::" + *
  248| //     return str;
  249| // }
  250| 
  251| //
  252| // AST Visitor
  253| //
  254| 
  255| void Dumper::visit(const std::vector<AST::Declaration*>& decls)
  256| {
  257|     std::vector<AST::Declaration*>::const_iterator iterend;
  258|     iter = decls.begin(), end = decls.end();
  259|     for (; iter != end; ++iter)
  260|         if (!m_filename.size() || (*iter)->file()->filename() == m_filename)
  261|             (*iter)->accept(this);
  262| }
  263| 
  264| void Dumper::visit(const std::vector<AST::Comment*>& comms)
  265| {
  266|     std::vector<AST::Comment*>::const_iterator iter = comms.begin();
  267|     while (iter != comms.end())
  268|     {
  269|         std::cout << m_indent_string << (*iter++)->text() << std::endl;
  270|     }
  271| }
  272| 
  273| // Format a Parameter
  274| std::string Dumper::formatParam(AST::Parameter* param)
  275| {
  276|     std::string str;
  277|     AST::Parameter::Mods::iterator imod = param->premodifier().begin();
  278|     while (imod != param->premodifier().end())
  279|         str += " " + *imod++;
  280|     const std::stringname = &param->name();
  281|     if (param->type())
  282|         str += " " + format(param->type(), &name);
  283|     if (name && param->name().size())
  284|         str += " " + param->name();
  285|     if (param->value().size())
  286|         str += " = " + param->value();
  287|     imod = param->postmodifier().begin();
  288|     while (imod != param->postmodifier().end())
  289|         str += " " + *imod++;
  290|     return str;
  291| }
  292| 
  293| void Dumper::visit_declaration(AST::Declaration* decl)
  294| {
  295|     visit(decl->comments());
  296|     if (decl->type() == "dummy")
  297|         return;
  298|     std::cout << m_indent_string << "DECL " << decl->name() << std::endl;
  299| }
  300| 
  301| void Dumper::visit_macro(AST::Macro* macro)
  302| {
  303|     std::cout << m_indent_string << "#define " << macro->name().back();
  304|     const AST::Macro::Parametersparams = macro->parameters();
  305|     if (params)
  306|     {
  307|         std::cout << "(";
  308|         AST::Macro::Parameters::const_iterator iter = params->begin();
  309|         if (iter != params->end())
  310|             std::cout << *iter++;
  311|         while (iter != params->end())
  312|             std::cout << ", " << *iter++;
  313|         std::cout << ")";
  314|     }
  315|     std::cout << " ";
  316|     std::cout << macro->text();
  317|     std::cout << "\n";
  318| }
  319| 
  320| void Dumper::visit_scope(AST::Scope* scope)
  321| {
  322|     // Generally the File scope..
  323|     visit(scope->declarations());
  324| }
  325| 
  326| void Dumper::visit_namespace(AST::Namespace* ns)
  327| {
  328|     visit(ns->comments());
  329|     std::cout << m_indent_string << "namespace " << ns->name() << " {" << std::endl;
  330|     indent();
  331|     m_scope.push_back(ns->name().back());
  332|     visit(ns->declarations());
  333|     m_scope.pop_back();
  334|     undent();
  335|     std::cout << m_indent_string << "}" << std::endl;
  336| }
  337| 
  338| void Dumper::visit_forward(AST::Forward* forward)
  339| {
  340|     visit(forward->comments());
  341|     if (forward->template_type())
  342|     {
  343|         m_scope.push_back(forward->name().back());
  344|         Types::Templatetempl = forward->template_type();
  345|         std::cout << m_indent_string << "template<";
  346|         std::vector<std::stringnames;
  347|         AST::Parameter::vector::iterator iter = templ->parameters().begin();
  348|         while (iter != templ->parameters().end())
  349|             names.push_back(formatParam(*iter++));
  350|         std::cout << join(names", ") << ">" << std::endl;
  351|         m_scope.pop_back();
  352|         if (forward->type().substr(09) == "template ")
  353|             std::cout << m_indent_string << (forward->type().c_str()+9) << " " << forward->name();
  354|         else
  355|             std::cout << m_indent_string << forward->type() << " " << forward->name() << ";" << std::endl;
  356|     }
  357|     else
  358|         std::cout << m_indent_string << forward->name() << ";" << std::endl;
  359| }
  360| 
  361| 
  362| void Dumper::visit_class(AST::Class* clas)
  363| {
  364|     visit(clas->comments());
  365|     if (clas->template_type())
  366|     {
  367|         m_scope.push_back(clas->name().back());
  368|         Types::Templatetempl = clas->template_type();
  369|         std::cout << m_indent_string << "template<";
  370|         std::vector<std::stringnames;
  371|         AST::Parameter::vector::iterator iter = templ->parameters().begin();
  372|         while (iter != templ->parameters().end())
  373|             names.push_back(formatParam(*iter++));
  374|         std::cout << join(names", ") << ">" << std::endl;
  375|         m_scope.pop_back();
  376|         if (clas->type().substr(09) == "template ")
  377|             std::cout << m_indent_string << (clas->type().c_str()+9) << " " << clas->name();
  378|         else
  379|             std::cout << m_indent_string << clas->type() << " " << clas->name();
  380|     }
  381|     else
  382|         std::cout << m_indent_string << clas->type() << " " << clas->name();
  383|     if (clas->parents().size())
  384|     {
  385|         std::cout << ": ";
  386|         std::vector<std::stringinherits;
  387|         std::vector<AST::Inheritance*>::iterator iter = clas->parents().begin();
  388|         for (;iter != clas->parents().end(); ++iter)
  389|             inherits.push_back(append((*iter)->attributes()) + format((*iter)->parent()));
  390|         std::cout << join(inherits", ");
  391|     }
  392|     std::cout << " {" << std::endl;
  393|     indent();
  394|     m_scope.push_back(clas->name().back());
  395|     visit(clas->declarations());
  396|     m_scope.pop_back();
  397|     undent();
  398|     std::cout << m_indent_string << "};" << std::endl;
  399| }
  400| 
  401| 
  402| // Utility func that returns true if name[-1] == name[-2]
  403| // ie: constructor or destructor
  404| bool isStructor(const AST::Function* func)
  405| {
  406|     const ScopedNamename = func->name();
  407|     if (name.size() < 2)
  408|         return false;
  409|     std::string realname = func->realname();
  410|     if (realname[0] == '~')
  411|         return true;
  412|     ScopedName::const_iterator second_last;
  413|     second_last = name.end() - 2;
  414|     return (realname == *second_last);
  415| }
  416| 
  417| void Dumper::visit_function(AST::Function* func)
  418| {
  419|     visit(func->comments());
  420|     std::cout << m_indent_string;
  421|     if (func->template_type())
  422|     {
  423|         m_scope.push_back(func->name().back());
  424|         Types::Templatetempl = func->template_type();
  425|         std::cout << m_indent_string << "template<";
  426|         std::vector<std::stringnames;
  427|         AST::Parameter::vector::iterator iter = templ->parameters().begin();
  428|         while (iter != templ->parameters().end())
  429|             names.push_back(formatParam(*iter++));
  430|         std::cout << join(names", ") << ">" << std::endl;
  431|         m_scope.pop_back();
  432|     }
  433|     if (!isStructor(func) && func->return_type())
  434|         std::cout << format(func->return_type()) + " ";
  435|     std::cout << func->realname() << "(";
  436|     if (func->parameters().size())
  437|     {
  438|         std::cout << formatParam(func->parameters().front());
  439|         std::vector<AST::Parameter*>::iterator iter = func->parameters().begin();
  440|         while (++iter != func->parameters().end())
  441|             std::cout << "," << formatParam(*iter);
  442|     }
  443|     std::cout << ");" << std::endl;
  444| }
  445| 
  446| void Dumper::visit_variable(AST::Variable* var)
  447| {
  448|     visit(var->comments());
  449|     std::cout << m_indent_string << format(var->vtype()) << " " << var->name().back() << ";" << std::endl;
  450| }
  451| 
  452| void Dumper::visit_typedef(AST::Typedef* tdef)
  453| {
  454|     visit(tdef->comments());
  455|     std::cout << m_indent_string << "typedef " << format(tdef->alias()) << " " << tdef->name().back() << ";" << std::endl;
  456| }
  457| 
  458| void Dumper::visit_enum(AST::Enum* decl)
  459| {
  460|     visit(decl->comments());
  461|     std::cout << m_indent_string << "enum " << decl->name().back() << "{" << std::endl;
  462|     indent();
  463|     std::vector<AST::Enumerator*>::iterator iter = decl->enumerators().begin();
  464|     while (iter != decl->enumerators().end())
  465|         (*iter++)->accept(this);
  466|     undent();
  467|     std::cout << m_indent_string << "};" << std::endl;
  468| }
  469| 
  470| void Dumper::visit_enumerator(AST::Enumerator* enumor)
  471| {
  472|     visit(enumor->comments());
  473|     if (enumor->type() == "dummy")
  474|         return;
  475|     std::cout << m_indent_string << enumor->name().back();
  476|     if (enumor->value().size())
  477|         std::cout << " = " << enumor->value();
  478|     std::cout << "," << std::endl;
  479| }
  480| 
  481| 
  482| // vim: set ts=8 sts=4 sw=4 et: