KDevelop API Documentation

lib/antlr/src/ASTFactory.cpp

Go to the documentation of this file.
00001 /* ANTLR Translator Generator 00002 * Project led by Terence Parr at http://www.jGuru.com 00003 * Software rights: http://www.antlr.org/RIGHTS.html 00004 * 00005 * $Id: ASTFactory.cpp,v 1.2 2003/05/02 00:36:20 okellogg Exp $ 00006 */ 00007 00008 #include "antlr/CommonAST.hpp" 00009 #include "antlr/ANTLRException.hpp" 00010 #include "antlr/IOException.hpp" 00011 #include "antlr/ASTFactory.hpp" 00012 #include "antlr/ANTLRUtil.hpp" 00013 00014 #include <iostream> 00015 00016 using namespace std; 00017 00018 #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE 00019 namespace antlr { 00020 #endif 00021 00037 00038 ASTFactory::ASTFactory() 00039 : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(static_cast<const char*>("CommonAST"),&CommonAST::factory)) 00040 { 00041 nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); 00042 } 00043 00048 ASTFactory::ASTFactory( const char* factory_node_name, factory_type fact ) 00049 : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(factory_node_name, fact)) 00050 { 00051 nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); 00052 } 00053 00055 ASTFactory::~ASTFactory() 00056 { 00057 factory_descriptor_list::iterator i = nodeFactories.begin(); 00058 00059 while( i != nodeFactories.end() ) 00060 { 00061 if( *i != &default_factory_descriptor ) 00062 delete *i; 00063 i++; 00064 } 00065 } 00066 00068 void ASTFactory::registerFactory( int type, const char* ast_name, factory_type factory ) 00069 { 00070 // check validity of arguments... 00071 if( type < Token::MIN_USER_TYPE ) 00072 throw ANTLRException("Internal parser error invalid type passed to RegisterFactory"); 00073 if( factory == 0 ) 00074 throw ANTLRException("Internal parser error 0 factory passed to RegisterFactory"); 00075 00076 // resize up to and including 'type' and initalize any gaps to default 00077 // factory. 00078 if( nodeFactories.size() < (static_cast<unsigned int>(type)+1) ) 00079 nodeFactories.resize( type+1, &default_factory_descriptor ); 00080 00081 // And add new thing.. 00082 nodeFactories[type] = new ANTLR_USE_NAMESPACE(std)pair<const char*, factory_type>( ast_name, factory ); 00083 } 00084 00085 void ASTFactory::setMaxNodeType( int type ) 00086 { 00087 if( nodeFactories.size() < (static_cast<unsigned int>(type)+1) ) 00088 nodeFactories.resize( type+1, &default_factory_descriptor ); 00089 } 00090 00094 RefAST ASTFactory::create() 00095 { 00096 RefAST node = nodeFactories[0]->second(); 00097 node->setType(Token::INVALID_TYPE); 00098 return node; 00099 } 00100 00101 RefAST ASTFactory::create(int type) 00102 { 00103 RefAST t = nodeFactories[type]->second(); 00104 t->initialize(type,""); 00105 return t; 00106 } 00107 00108 RefAST ASTFactory::create(int type, const ANTLR_USE_NAMESPACE(std)string& txt) 00109 { 00110 RefAST t = nodeFactories[type]->second(); 00111 t->initialize(type,txt); 00112 return t; 00113 } 00114 00115 #ifdef ANTLR_SUPPORT_XML 00116 RefAST ASTFactory::create(const ANTLR_USE_NAMESPACE(std)string& type_name, ANTLR_USE_NAMESPACE(std)istream& infile ) 00117 { 00118 factory_descriptor_list::iterator fact = nodeFactories.begin(); 00119 00120 while( fact != nodeFactories.end() ) 00121 { 00122 if( type_name == (*fact)->first ) 00123 { 00124 RefAST t = (*fact)->second(); 00125 t->initialize(infile); 00126 return t; 00127 } 00128 fact++; 00129 } 00130 00131 string error = "ASTFactory::create: Unknown AST type '" + type_name + "'"; 00132 throw ANTLRException(error); 00133 } 00134 #endif 00135 00139 RefAST ASTFactory::create(RefAST tr) 00140 { 00141 if (!tr) 00142 return nullAST; 00143 00144 // cout << "create(tr)" << endl; 00145 00146 RefAST t = nodeFactories[tr->getType()]->second(); 00147 t->initialize(tr); 00148 return t; 00149 } 00150 00151 RefAST ASTFactory::create(RefToken tok) 00152 { 00153 // cout << "create( tok="<< tok->getType() << ", " << tok->getText() << ")" << nodeFactories.size() << endl; 00154 RefAST t = nodeFactories[tok->getType()]->second(); 00155 t->initialize(tok); 00156 return t; 00157 } 00158 00160 void ASTFactory::addASTChild(ASTPair& currentAST, RefAST child) 00161 { 00162 if (child) 00163 { 00164 if (!currentAST.root) 00165 { 00166 // Make new child the current root 00167 currentAST.root = child; 00168 } 00169 else 00170 { 00171 if (!currentAST.child) 00172 { 00173 // Add new child to current root 00174 currentAST.root->setFirstChild(child); 00175 } 00176 else 00177 { 00178 currentAST.child->setNextSibling(child); 00179 } 00180 } 00181 // Make new child the current child 00182 currentAST.child = child; 00183 currentAST.advanceChildToEnd(); 00184 } 00185 } 00186 00190 RefAST ASTFactory::dup(RefAST t) 00191 { 00192 if( t ) 00193 return t->clone(); 00194 else 00195 return RefAST(nullASTptr); 00196 } 00197 00199 RefAST ASTFactory::dupList(RefAST t) 00200 { 00201 RefAST result = dupTree(t); // if t == null, then result==null 00202 RefAST nt = result; 00203 00204 while( t ) 00205 { // for each sibling of the root 00206 t = t->getNextSibling(); 00207 nt->setNextSibling(dupTree(t)); // dup each subtree, building new tree 00208 nt = nt->getNextSibling(); 00209 } 00210 return result; 00211 } 00212 00216 RefAST ASTFactory::dupTree(RefAST t) 00217 { 00218 RefAST result = dup(t); // make copy of root 00219 // copy all children of root. 00220 if( t ) 00221 result->setFirstChild( dupList(t->getFirstChild()) ); 00222 return result; 00223 } 00224 00231 RefAST ASTFactory::make(ANTLR_USE_NAMESPACE(std)vector<RefAST>& nodes) 00232 { 00233 if ( nodes.size() == 0 ) 00234 return RefAST(nullASTptr); 00235 00236 RefAST root = nodes[0]; 00237 RefAST tail = RefAST(nullASTptr); 00238 00239 if( root ) 00240 root->setFirstChild(RefAST(nullASTptr)); // don't leave any old pointers set 00241 00242 // link in children; 00243 for( unsigned int i = 1; i < nodes.size(); i++ ) 00244 { 00245 if ( nodes[i] == 0 ) // ignore null nodes 00246 continue; 00247 00248 if ( root == 0 ) // Set the root and set it up for a flat list 00249 root = tail = nodes[i]; 00250 else if ( tail == 0 ) 00251 { 00252 root->setFirstChild(nodes[i]); 00253 tail = root->getFirstChild(); 00254 } 00255 else 00256 { 00257 tail->setNextSibling(nodes[i]); 00258 tail = tail->getNextSibling(); 00259 } 00260 00261 if( tail ) // RK: I cannot fathom why this missing check didn't bite anyone else... 00262 { 00263 // Chase tail to last sibling 00264 while (tail->getNextSibling()) 00265 tail = tail->getNextSibling(); 00266 } 00267 } 00268 00269 return root; 00270 } 00271 00275 RefAST ASTFactory::make(ASTArray* nodes) 00276 { 00277 RefAST ret = make(nodes->array); 00278 delete nodes; 00279 return ret; 00280 } 00281 00283 void ASTFactory::makeASTRoot( ASTPair& currentAST, RefAST root ) 00284 { 00285 if (root) 00286 { 00287 // Add the current root as a child of new root 00288 root->addChild(currentAST.root); 00289 // The new current child is the last sibling of the old root 00290 currentAST.child = currentAST.root; 00291 currentAST.advanceChildToEnd(); 00292 // Set the new root 00293 currentAST.root = root; 00294 } 00295 } 00296 00297 void ASTFactory::setASTNodeFactory( const char* factory_node_name, 00298 factory_type factory ) 00299 { 00300 default_factory_descriptor.first = factory_node_name; 00301 default_factory_descriptor.second = factory; 00302 } 00303 00304 #ifdef ANTLR_SUPPORT_XML 00305 bool ASTFactory::checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& in ) 00306 { 00307 char ch; 00308 00309 if( in.get(ch) ) 00310 { 00311 if( ch == '<' ) 00312 { 00313 char ch2; 00314 if( in.get(ch2) ) 00315 { 00316 if( ch2 == '/' ) 00317 { 00318 in.putback(ch2); 00319 in.putback(ch); 00320 return true; 00321 } 00322 in.putback(ch2); 00323 in.putback(ch); 00324 return false; 00325 } 00326 } 00327 in.putback(ch); 00328 return false; 00329 } 00330 return false; 00331 } 00332 00333 void ASTFactory::loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile, 00334 RefAST current ) 00335 { 00336 char ch; 00337 00338 for(;;) // for all children of this node.... 00339 { 00340 eatwhite(infile); 00341 00342 infile.get(ch); // '<' 00343 if( ch != '<' ) 00344 { 00345 string error = "Invalid XML file... no '<' found ("; 00346 error += ch + ")"; 00347 throw IOException(error); 00348 } 00349 00350 infile.get(ch); // / or text.... 00351 00352 if( ch == '/' ) // check for close tag... 00353 { 00354 string temp; 00355 00356 // read until '>' and see if it matches the open tag... if not trouble 00357 temp = read_identifier( infile ); 00358 00359 if( strcmp(temp.c_str(), current->typeName() ) != 0 ) 00360 { 00361 string error = "Invalid XML file... close tag does not match start tag: "; 00362 error += current->typeName(); 00363 error += " closed by " + temp; 00364 throw IOException(error); 00365 } 00366 00367 infile.get(ch); // must be a '>' 00368 00369 if( ch != '>' ) 00370 { 00371 string error = "Invalid XML file... no '>' found ("; 00372 error += ch + ")"; 00373 throw IOException(error); 00374 } 00375 // close tag => exit loop 00376 break; 00377 } 00378 00379 // put our 'look ahead' back where it came from 00380 infile.putback(ch); 00381 infile.putback('<'); 00382 00383 // and recurse into the tree... 00384 RefAST child = LoadAST(infile); 00385 00386 current->addChild( child ); 00387 } 00388 } 00389 00390 void ASTFactory::loadSiblings(ANTLR_USE_NAMESPACE(std)istream& infile, 00391 RefAST current ) 00392 { 00393 for(;;) 00394 { 00395 eatwhite(infile); 00396 00397 if( infile.eof() ) 00398 break; 00399 00400 if( checkCloseTag(infile) ) 00401 break; 00402 00403 RefAST sibling = LoadAST(infile); 00404 current->setNextSibling(sibling); 00405 } 00406 } 00407 00408 RefAST ASTFactory::LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile ) 00409 { 00410 RefAST current = nullAST; 00411 char ch; 00412 00413 eatwhite(infile); 00414 00415 if( !infile.get(ch) ) 00416 return nullAST; 00417 00418 if( ch != '<' ) 00419 { 00420 string error = "Invalid XML file... no '<' found ("; 00421 error += ch + ")"; 00422 throw IOException(error); 00423 } 00424 00425 string ast_type = read_identifier(infile); 00426 00427 // create the ast of type 'ast_type' 00428 current = create( ast_type, infile ); 00429 if( current == nullAST ) 00430 { 00431 string error = "Unsuported AST type: " + ast_type; 00432 throw IOException(error); 00433 } 00434 00435 eatwhite(infile); 00436 00437 infile.get(ch); 00438 00439 // now if we have a '/' here it's a single node. If it's a '>' we get 00440 // a tree with children 00441 00442 if( ch == '/' ) 00443 { 00444 infile.get(ch); // get the closing '>' 00445 if( ch != '>' ) 00446 { 00447 string error = "Invalid XML file... no '>' found after '/' ("; 00448 error += ch + ")"; 00449 throw IOException(error); 00450 } 00451 00452 // get the rest on this level 00453 loadSiblings( infile, current ); 00454 00455 return current; 00456 } 00457 00458 // and finaly see if we got the close tag... 00459 if( ch != '>' ) 00460 { 00461 string error = "Invalid XML file... no '>' found ("; 00462 error += ch + ")"; 00463 throw IOException(error); 00464 } 00465 00466 // handle the ones below this level.. 00467 loadChildren( infile, current ); 00468 00469 // load the rest on this level... 00470 loadSiblings( infile, current ); 00471 00472 return current; 00473 } 00474 #endif // ANTLR_SUPPORT_XML 00475 00476 #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE 00477 } 00478 #endif 00479 00480 /* Heterogeneous AST/XML-I/O ramblings... 00481 * 00482 * So there is some heterogeneous AST support.... 00483 * basically in the code generators a new custom ast is generated without 00484 * going throug the factory. It also expects the RefXAST to be defined. 00485 * 00486 * Is it maybe better to register all AST types with the ASTFactory class 00487 * together with the respective factory methods. 00488 * 00489 * More and more I get the impression that hetero ast was a kindoff hack 00490 * on top of ANTLR's normal AST system. 00491 * 00492 * The heteroast stuff will generate trouble for all astFactory.create( ... ) 00493 * invocations. Most of this is handled via getASTCreateString methods in the 00494 * codegenerator. At the moment getASTCreateString(GrammarAtom, String) has 00495 * slightly to little info to do it's job (ok the hack that is in now 00496 * works, but it's an ugly hack) 00497 * 00498 * An extra caveat is the 'nice' action.g thing. Which also judiciously calls 00499 * getASTCreateString methods because it handles the #( ... ) syntax. 00500 * And converts that to ASTFactory calls. 00501 * 00502 * 00503 */
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:47 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003