KDevelop API Documentation

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.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:34 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003