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|
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 iter, end;
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::string* name = ¶m->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::Parameters* params = 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::Template* templ = forward->template_type();
345| std::cout << m_indent_string << "template<";
346| std::vector<std::string> names;
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(0, 9) == "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::Template* templ = clas->template_type();
369| std::cout << m_indent_string << "template<";
370| std::vector<std::string> names;
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(0, 9) == "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::string> inherits;
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|
403|
404| bool isStructor(const AST::Function* func)
405| {
406| const ScopedName& name = 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::Template* templ = func->template_type();
425| std::cout << m_indent_string << "template<";
426| std::vector<std::string> names;
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|