Synopsis - Cross-Reference
File: /tests/Cxx/src/SymbolLookup.cc1#include <Synopsis/Trace.hh> 2#include <Synopsis/Buffer.hh> 3#include <Synopsis/Lexer.hh> 4#include <Synopsis/Parser.hh> 5#include <Synopsis/PTree.hh> 6#include <Synopsis/PTree/Display.hh> 7#include <Synopsis/PTree/Writer.hh> 8#include <Synopsis/SymbolLookup.hh> 9#include <iostream> 10#include <iomanip> 11#include <fstream> 12 13using namespace Synopsis; 14using namespace SymbolLookup; 15 16class SymbolFinder : private Walker 17{ 18public: 19 SymbolFinder(Buffer const &buffer, Scope *scope, std::ostream &os) 20 : Walker(scope), my_buffer(buffer), my_os(os), my_in_template_decl(false) {} 21 void find(PTree::Node *node) { node->accept(this);} 22private: 23 using Walker::visit; 24 virtual void visit(PTree::Identifier *iden) 25 { 26 Trace trace("SymbolFinder::visit(Identifier)", Trace::SYMBOLLOOKUP); 27 PTree::Encoding name = PTree::Encoding::simple_name(iden); 28 my_os << "Identifier : " << name.unmangled() << std::endl; 29 lookup(name); 30 } 31 32 virtual void visit(PTree::Block *node) 33 { 34 Trace trace("SymbolFinder::visit(Block)", Trace::SYMBOLLOOKUP); 35 Walker::visit(node); 36 } 37 38 virtual void visit(PTree::Typedef *typed) 39 { 40 Trace trace("SymbolFinder::visit(Typedef)", Trace::SYMBOLLOOKUP); 41 // We need to figure out how to reproduce the (encoded) name of 42 // the type being aliased. 43 my_os << "Type : " << "<not implemented yet>" << std::endl; 44// lookup(name); 45 PTree::third(typed)->accept(this); 46 } 47 48 virtual void visit(PTree::TemplateDecl *tdecl) 49 { 50 Trace trace("SymbolFinder::visit(TemplateDecl)", Trace::SYMBOLLOOKUP); 51 traverse_parameters(tdecl); 52 bool saved_in_template_decl = my_in_template_decl; 53 my_in_template_decl = true; 54 PTree::Node *fourth = PTree::nth(tdecl, 4); 55 if (!fourth->is_atom()) 56 fourth->accept(this); // This is a declaration. 57 else 58 { 59 // We are in a template template parameter. 60 // Visit the identifier and the default type, if present. 61 PTree::Node *fifth = PTree::nth(tdecl, 5); 62 if (fifth) fifth->accept(this); // This is an identifier 63 } 64 my_in_template_decl = saved_in_template_decl; 65 } 66 67 virtual void visit(PTree::NamespaceSpec *node) 68 { 69 Trace trace("SymbolFinder::visit(NamespaceSpec)", Trace::SYMBOLLOOKUP); 70 PTree::Node const *name = PTree::second(node); 71 PTree::Encoding ename; 72 if (name) ename.simple_name(name); 73 else ename.append_with_length("<anonymous>"); 74 my_os << "Namespace : " << ename.unmangled() << std::endl; 75 lookup(ename); 76 traverse_body(node); 77 } 78 79 virtual void visit(PTree::Declaration *node) 80 { 81 Trace trace("SymbolFinder::visit(Declaration)", Trace::SYMBOLLOOKUP); 82 PTree::Node *type_spec = PTree::second(node); 83 // FIXME: what about compound types ? 84 if (type_spec && type_spec->is_atom()) 85 { 86 PTree::Atom const *name = static_cast<PTree::Atom *>(type_spec); 87 PTree::Encoding type = PTree::Encoding::simple_name(name); 88 my_os << "Type : " << type.unmangled() << std::endl; 89 lookup(type, Scope::DEFAULT, true); 90 PTree::third(node)->accept(this); 91 } 92 else 93 Walker::visit(node); 94 } 95 96 virtual void visit(PTree::UsingDirective *udir) 97 { 98 PTree::Node *node = PTree::third(udir); 99 PTree::Encoding name = node->encoded_name(); 100 my_os << "Namespace : " << name.unmangled() << std::endl; 101 lookup(name); 102 } 103 virtual void visit(PTree::UsingDeclaration *udecl) 104 { visit(static_cast<PTree::List *>(udecl));} 105 virtual void visit(PTree::NamespaceAlias *alias) 106 { 107 { 108 PTree::Node *node = PTree::second(alias); 109 PTree::Encoding name = PTree::Encoding::simple_name(static_cast<PTree::Atom *>(node)); 110 my_os << "Namespace : " << name.unmangled() << std::endl; 111 lookup(name); 112 } 113 { 114 PTree::Node *node = PTree::nth(alias, 3); 115 PTree::Encoding name = node->encoded_name(); 116 my_os << "Namespace : " << name.unmangled() << std::endl; 117 lookup(name); 118 } 119 } 120 121 virtual void visit(PTree::FunctionDefinition *node) 122 { 123 Trace trace("SymbolFinder::visit(FunctionDefinition)", Trace::SYMBOLLOOKUP); 124 PTree::Node *decl = PTree::third(node); 125 visit(static_cast<PTree::Declarator *>(decl)); // visit the declarator 126 try { traverse_body(node);} 127 catch (Undefined const &e) {} // just ignore 128 } 129 130 virtual void visit(PTree::Declarator *decl) 131 { 132 Trace trace("SymbolFinder::visit(Declarator)", Trace::SYMBOLLOOKUP); 133 PTree::Encoding name = decl->encoded_name(); 134 // FIXME: The parser currently parses type specifiers that contain a template_id 135 // such that in contains declarators with empty names. 136 // Ignore these until the parser is fixed. 137 if (name.empty()) return; 138 PTree::Encoding type = decl->encoded_type(); 139 my_os << "Declarator : " << name.unmangled() << std::endl; 140 lookup(name, Scope::DECLARATION); 141 if (type.is_function()) return; 142 if (PTree::Node *initializer = decl->initializer()) 143 initializer->accept(this); 144 } 145 146 virtual void visit(PTree::Name *n) 147 { 148 Trace trace("SymbolFinder::visit(Name)", Trace::SYMBOLLOOKUP); 149 PTree::Encoding name = n->encoded_name(); 150 my_os << "Name : " << name.unmangled() << std::endl; 151 lookup(name); 152 } 153 154 virtual void visit(PTree::ClassSpec *node) 155 { 156 Trace trace("SymbolFinder::visit(ClassSpec)", Trace::SYMBOLLOOKUP); 157 PTree::Encoding name = node->encoded_name(); 158 my_os << "ClassSpec : " << name.unmangled() << std::endl; 159 // FIXME: A ClassSpec may correspond to a class template, in which case 160 // we shouldn't do a elaborate lookup. The visit(TemplateDecl) 161 // method above will thus deal with the lookup itself. 162 if (my_in_template_decl) 163 lookup(name); 164 else 165 lookup(name, Scope::ELABORATE); 166 167 for (PTree::Node const *base_clause = node->base_clause(); 168 base_clause; 169 base_clause = PTree::rest(PTree::rest(base_clause))) 170 { 171 PTree::Node const *parent = PTree::last(PTree::second(base_clause))->car(); 172 const_cast<PTree::Node *>(parent)->accept(this); 173 } 174 traverse_body(node); 175 } 176 177 virtual void visit(PTree::FuncallExpr *node) 178 { 179 Trace trace("SymbolFinder::visit(FuncallExpr)", Trace::SYMBOLLOOKUP); 180 PTree::Node *function = node->car(); 181 PTree::Encoding name; 182 if (function->is_atom()) name.simple_name(function); 183 else name = function->encoded_name(); // function is a 'PTree::Name' 184 my_os << "Function : " << name.unmangled() << std::endl; 185 lookup(name); 186 } 187 188 void lookup(PTree::Encoding const &name, 189 Scope::LookupContext c = Scope::DEFAULT, 190 bool type = false) 191 { 192 Trace trace("SymbolFinder::lookup", Trace::SYMBOLLOOKUP); 193 SymbolSet symbols = current_scope()->lookup(name, c); 194 if (!symbols.empty()) 195 { 196 if (type) // Expect a single match that is a type-name. 197 { 198 TypeName const *type = dynamic_cast<TypeName const *>(*symbols.begin()); 199 if (type) 200 { 201 std::string filename; 202 unsigned long line_number = my_buffer.origin(type->ptree()->begin(), filename); 203 my_os << "declared at line " << line_number << " in " << filename << std::endl; 204 return; 205 } 206 else my_os << "only non-types found" << std::endl; 207 } 208 209 for (SymbolSet::iterator s = symbols.begin(); s != symbols.end(); ++s) 210 { 211 std::string filename; 212 unsigned long line_number = my_buffer.origin((*s)->ptree()->begin(), filename); 213 my_os << "declared at line " << line_number << " in " << filename << std::endl; 214 } 215 } 216 else 217 my_os << "undeclared ! " << std::endl; 218 } 219 220 Buffer const &my_buffer; 221 std::ostream &my_os; 222 bool my_in_template_decl; 223}; 224 225int main(int argc, char **argv) 226{ 227 if (argc < 3) 228 { 229 std::cerr << "Usage: " << argv[0] << " [-d] <output> <input>" << std::endl; 230 exit(-1); 231 } 232 try 233 { 234 std::string output; 235 std::string input; 236 if (argv[1] == std::string("-d")) 237 { 238 Trace::enable(Trace::SYMBOLLOOKUP); 239 output = argv[2]; 240 input = argv[3]; 241 } 242 else 243 { 244 output = argv[1]; 245 input = argv[2]; 246 } 247 std::ofstream ofs(output.c_str()); 248 std::ifstream ifs(input.c_str()); 249 Buffer buffer(ifs.rdbuf(), "<input>"); 250 Lexer lexer(&buffer); 251 SymbolFactory symbols; 252 Parser parser(lexer, symbols); 253 PTree::Node *node = parser.parse(); 254 const Parser::ErrorList &errors = parser.errors(); 255 for (Parser::ErrorList::const_iterator i = errors.begin(); i != errors.end(); ++i) 256 (*i)->write(ofs); 257 if (errors.empty()) 258 { 259 SymbolFinder finder(buffer, symbols.current_scope(), ofs); 260 finder.find(node); 261 } 262 } 263 catch (std::exception const &e) 264 { 265 std::cerr << "Caught exception : " << e.what() << std::endl; 266 } 267}