$search
00001 /* 00002 * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g) 00003 * 00004 * Authors: Sumana Srinivasan, NeXT Inc.; sumana_srinivasan@next.com 00005 * Terence Parr, Parr Research Corporation; parrt@parr-research.com 00006 * Russell Quong, Purdue University; quong@ecn.purdue.edu 00007 * 00008 * VERSION 1.1 00009 * 00010 * SOFTWARE RIGHTS 00011 * 00012 * This file is a part of the ANTLR-based C++ grammar and is free 00013 * software. We do not reserve any LEGAL rights to its use or 00014 * distribution, but you may NOT claim ownership or authorship of this 00015 * grammar or support code. An individual or company may otherwise do 00016 * whatever they wish with the grammar distributed herewith including the 00017 * incorporation of the grammar or the output generated by ANTLR into 00018 * commerical software. You may redistribute in source or binary form 00019 * without payment of royalties to us as long as this header remains 00020 * in all source distributions. 00021 * 00022 * We encourage users to develop parsers/tools using this grammar. 00023 * In return, we ask that credit is given to us for developing this 00024 * grammar. By "credit", we mean that if you incorporate our grammar or 00025 * the generated code into one of your programs (commercial product, 00026 * research project, or otherwise) that you acknowledge this fact in the 00027 * documentation, research report, etc.... In addition, you should say nice 00028 * things about us at every opportunity. 00029 * 00030 * As long as these guidelines are kept, we expect to continue enhancing 00031 * this grammar. Feel free to send us enhancements, fixes, bug reports, 00032 * suggestions, or general words of encouragement at parrt@parr-research.com. 00033 * 00034 * NeXT Computer Inc. 00035 * 900 Chesapeake Dr. 00036 * Redwood City, CA 94555 00037 * 12/02/1994 00038 * 00039 * Restructured for public consumption by Terence Parr late February, 1995. 00040 * 00041 * DISCLAIMER: we make no guarantees that this grammar works, makes sense, 00042 * or can be used to do anything useful. 00043 */ 00044 /* 00045 * 2001-2003 Version 2.0 September 2003 00046 * 00047 * Some modifications were made to this file to support a project by 00048 * Jianguo Zuo and David Wigg at 00049 * The Centre for Systems and Software Engineering 00050 * South Bank University 00051 * London, UK. 00052 * wiggjd@bcs.ac.uk 00053 * blackse@lsbu.ac.uk 00054 */ 00055 /* 2003-2004 Version 3.0 July 2004 00056 * Modified by David Wigg at London South Bank University for CPP_parser.g 00057 * 00058 * See MyReadMe.txt for further information 00059 * 00060 * This file is best viewed in courier font with tabs set to 4 spaces 00061 */ 00062 00063 #include <iostream> 00064 #include "CPPParser.hpp" 00065 #include "CPPSymbol.hh" 00066 00067 using namespace std; 00068 00069 void CPPParser::init() 00070 { 00071 //antlrTrace(false); // This is a dynamic trace facility for use with -traceParser etc. 00072 // It requires modification in LLkParser.cpp and LLkParser.hpp 00073 // otherwise it should be commented out (see MyReadMe.txt) 00074 // true shows antlr trace (can be set and reset during parsing) 00075 // false stops showing antlr trace 00076 // Provided the parser is always generated with -traceParser this 00077 // facility allows trace output to be turned on or off by changing 00078 // the setting here from false to true or vice versa and then 00079 // recompiling and linking CPPParser only thus avoiding the need 00080 // to use antlr.Tool to re-generate the lexer and parser again. 00081 00082 // Creates a dictionary to hold symbols with 4001 buckets, 200 scopes and 800,000 characters 00083 // These can be changed to suit the size of program(s) being parsed 00084 symbols = new CPPDictionary(4001, 200, 800000); 00085 00086 symbols->saveScope(); // Advance currentScope from 0 to 1 00087 externalScope = symbols->getCurrentScopeIndex(); // Set external scope to 1 00088 00089 // Global flags to allow for nested declarations 00090 _td = false; // For typedef 00091 _sc = scInvalid; // For StorageClass 00092 _tq = tqInvalid; // For TypeQualifier 00093 _ts = tsInvalid; // For TypeSpecifier 00094 _ds = dsInvalid; // For DeclSpecifier 00095 00096 functionDefinition = 0; 00097 assign_stmt_RHS_found = 0; 00098 in_parameter_list = false; 00099 in_return = false; 00100 } 00101 00102 CPPParser::~CPPParser() 00103 { 00104 delete symbols; 00105 } 00106 00107 /* 00108 * Return true if 's' can pose as a type name 00109 */ 00110 int CPPParser::isTypeName(const std::string& s) 00111 { 00112 CPPSymbol *cs = (CPPSymbol *) symbols->lookup(s); 00113 00114 if (cs==NULL) 00115 { 00116 //printf("support.cpp isTypeName %s not found\n",s); 00117 return 0; 00118 } 00119 00120 if (cs->getType()==CPPSymbol::otTypedef|| 00121 cs->getType()==CPPSymbol::otEnum|| 00122 cs->getType()==CPPSymbol::otClass|| 00123 cs->getType()==CPPSymbol::otStruct|| 00124 cs->getType()==CPPSymbol::otUnion) 00125 { 00126 00127 // DW 13/06/03 Check that scope level found is not greater 00128 // than the current scope i.e. lower level 00129 // if (cs->this_scope > symbols->getCurrentScopeIndex() ) 00130 // { 00131 // return 0; 00132 // } 00133 // 00134 // if (cs->getInScope()==false) 00135 // { 00136 // return 1; 00137 // } 00138 return 1; 00139 } 00140 00141 return 0; 00142 } 00143 00144 void CPPParser::beginDeclaration() { } 00145 00146 void CPPParser::endDeclaration() { } 00147 00148 void CPPParser::beginFunctionDefinition() 00149 { 00150 functionDefinition = 1; 00151 } 00152 00153 void CPPParser::endFunctionDefinition() 00154 { 00155 // Remove parameter scope 00156 symbols->dumpScope(stdout); 00157 //fprintf(stdout, "endFunctionDefinition remove parameter scope(%d):\n",symbols->getCurrentScopeIndex()); 00158 symbols->removeScope(); 00159 symbols->restoreScope(); 00160 //printf("endFunctionDefinition restoreScope() now %d\n",symbols->getCurrentScopeIndex()); 00161 functionDefinition = 0; 00162 } 00163 00164 void CPPParser::beginParameterDeclaration() 00165 { } 00166 00167 void CPPParser::beginFieldDeclaration() 00168 { } 00169 00170 void CPPParser::declarationSpecifier(bool td, StorageClass sc, TypeQualifier tq, 00171 TypeSpecifier ts, DeclSpecifier ds) 00172 { 00173 //printf("support.cpp declarationSpecifier td %d, fd %d, sc %d, tq, %d, ts %d, ds %d, qi %d\n", 00174 // td,fd,sc,tq,ts,ds,qi); 00175 _td = td; // For typedef 00176 _sc = sc; 00177 _tq = tq; 00178 _ts = ts; 00179 _ds = ds; 00180 // _qi = qi; 00181 } 00182 00183 /* Symbols from declarators are added to the symbol table here. 00184 * The symbol is added to whatever the current scope is in the symbol table. 00185 * See list of object types below. 00186 */ 00187 void CPPParser::declaratorID(const std::string& id, QualifiedItem qi) 00188 { 00189 CPPSymbol *c; 00190 if (qi==qiType || _td) // Check for type declaration 00191 { 00192 if (!(qi==qiType && _td)) 00193 { 00194 std::cerr << LT(1) -> getLine() 00195 << "support.cpp declaratorID warning qi " << qi << ", _td " << _td 00196 << " inconsistent for " << id << std::endl; 00197 } 00198 00199 c = new CPPSymbol(id, CPPSymbol::otTypedef); 00200 symbols->defineInScope(id, c, externalScope); 00201 } 00202 else if (qi==qiFun) // For function declaration 00203 { 00204 c = new CPPSymbol(id, CPPSymbol::otFunction); 00205 symbols->define(id, c); // Add to current scope 00206 } 00207 else 00208 { 00209 if (qi!=qiVar) 00210 { 00211 std::cerr << LT(1) -> getLine() 00212 << "support.cpp declaratorID warning qi " << qi << "not qiVar _td " << qiVar 00213 << " inconsistent for " << id << std::endl; 00214 } 00215 00216 c = new CPPSymbol(id, CPPSymbol::otVariable); // Used to leave otInvalid DW 02/07/03 Think this should be otVariable 00217 symbols->define(id, c); // Add to current scope 00218 } 00219 } 00220 00221 void CPPParser::enterNamespace(std::string const& name) { } 00222 void CPPParser::exitNamespace() { } 00223 00224 /* These are the object types 00225 0 = otInvalid 00226 1 = otFunction 00227 2 = otVariable 00228 3 = otTypedef Note. 3-7 are type names 00229 4 = otStruct Note. 4, 5 & 7 are class names 00230 5 = otUnion 00231 6 = otEnum 00232 7 = otClass 00233 8 = otEnumElement 00234 */ 00235 00236 void CPPParser::declaratorArray(int size) { } 00237 00238 void CPPParser::declaratorParameterList(int def) 00239 { 00240 symbols->saveScope(); 00241 //printf("declaratorParameterList saveScope() now %d\n",symbols->getCurrentScopeIndex()); 00242 } 00243 00244 void CPPParser::declaratorEndParameterList(int def) 00245 { 00246 if (!def) 00247 { 00248 symbols->dumpScope(stdout); 00249 symbols->removeScope(); 00250 symbols->restoreScope(); 00251 //printf("declaratorEndParameterList restoreScope() now %d\n",symbols->getCurrentScopeIndex()); 00252 } 00253 } 00254 00255 void CPPParser::functionParameterList() 00256 { 00257 symbols->saveScope(); 00258 //printf("functionParameterList saveScope() now %d\n",symbols->getCurrentScopeIndex()); 00259 // DW 25/3/97 change flag from function to parameter list 00260 functionDefinition = 2; 00261 } 00262 00263 void CPPParser::functionEndParameterList(int def) 00264 { 00265 // If this parameter list is not in a definition then this 00266 if ( !def) 00267 { 00268 symbols->dumpScope(stdout); 00269 symbols->removeScope(); 00270 symbols->restoreScope(); 00271 //printf("functionEndParameterList restoreScope() now %d\n",symbols->getCurrentScopeIndex()); 00272 } 00273 else 00274 { 00275 // Change flag from parameter list to body of definition 00276 functionDefinition = 3; 00277 } 00278 /* Otherwise endFunctionDefinition removes the parameters from scope */ 00279 } 00280 00281 void CPPParser::enterNewLocalScope() 00282 { 00283 symbols->saveScope(); 00284 //printf("enterNewLocalScope saveScope() now %d\n",symbols->getCurrentScopeIndex()); 00285 } 00286 00287 void CPPParser::exitLocalScope() 00288 { 00289 symbols->dumpScope(stdout); 00290 symbols->removeScope(); 00291 symbols->restoreScope(); 00292 //printf("exitLocalScope restoreScope() now %d\n",symbols->getCurrentScopeIndex()); 00293 } 00294 00295 void CPPParser::enterExternalScope() 00296 {// Scope has been initialised to 1 in CPPParser.init() in CPPParser.hpp 00297 // DW 25/3/97 initialise 00298 functionDefinition = 0; 00299 //classDefinition = 0; DW 19/03/04 not used anywhere 00300 } 00301 00302 void CPPParser::exitExternalScope() 00303 { 00304 symbols->dumpScope(stdout); 00305 symbols->removeScope(); // This just removes the symbols stored in the current scope 00306 symbols->restoreScope(); // This just reduces the current scope by 1 00307 //if (symbols->getCurrentScopeIndex()==0) 00308 // printf("\nSupport exitExternalScope, scope now %d\n",symbols->getCurrentScopeIndex()); 00309 //else 00310 // printf("\nSupport exitExternalScope, scope now %d, should be 0\n",symbols->getCurrentScopeIndex()); 00311 } 00312 00313 void CPPParser::classForwardDeclaration(TypeSpecifier ts, DeclSpecifier ds, const std::string& tag) 00314 { 00315 CPPSymbol *c = NULL; 00316 00317 // if already in symbol table as a class, don't add 00318 // of course, this is incorrect as you can rename 00319 // classes by entering a new scope, but our limited 00320 // example basically keeps all types globally visible. 00321 if ( symbols->lookup(tag)!=NULL ) 00322 return; 00323 00324 switch (ts) 00325 { 00326 case tsSTRUCT : 00327 c = new CPPSymbol(tag, CPPSymbol::otStruct); 00328 break; 00329 case tsUNION : 00330 c = new CPPSymbol(tag, CPPSymbol::otUnion); 00331 break; 00332 case tsCLASS : 00333 c = new CPPSymbol(tag, CPPSymbol::otClass); 00334 break; 00335 } 00336 00337 symbols->defineInScope(tag, c, externalScope); 00338 } 00339 00340 void CPPParser::beginClassDefinition(TypeSpecifier ts,const std::string& tag) 00341 { 00342 CPPSymbol *c; 00343 00344 // if already in symbol table as a class, don't add 00345 // of course, this is incorrect as you can rename 00346 // classes by entering a new scope, but our limited 00347 // example basically keeps all types globally visible. 00348 if (symbols->lookup(tag) != NULL) 00349 { 00350 symbols->saveScope(); // still have to use scope to collect members 00351 //printf("support.cpp beginClassDefinition_1 saveScope() now %d\n",symbols->getCurrentScopeIndex()); 00352 return; 00353 } 00354 00355 switch (ts) 00356 { 00357 case tsSTRUCT: 00358 c = new CPPSymbol(tag, CPPSymbol::otStruct); 00359 break; 00360 case tsUNION: 00361 c = new CPPSymbol(tag, CPPSymbol::otUnion); 00362 break; 00363 case tsCLASS: 00364 c = new CPPSymbol(tag, CPPSymbol::otClass); 00365 break; 00366 default: 00367 throw std::runtime_error("unexpected TypeSpecifier in CPPParser::beginClassDefinition"); 00368 } 00369 symbols->defineInScope(tag, c, externalScope); 00370 qualifierPrefix += tag; 00371 qualifierPrefix += "::"; 00372 00373 // add all member type symbols into the global scope (not correct, but 00374 // will work for most code). 00375 // This symbol lives until the end of the file 00376 00377 symbols->saveScope(); // use the scope to collect list of fields 00378 } 00379 00380 void CPPParser::endClassDefinition() 00381 { 00382 symbols->dumpScope(stdout); 00383 symbols->removeScope(); 00384 symbols->restoreScope(); 00385 // remove final T:: from A::B::C::T:: 00386 // upon backing out of last class, qualifierPrefix is set to "" 00387 size_t index = qualifierPrefix.rfind("::"); 00388 if (index == std::string::npos) 00389 return; 00390 qualifierPrefix.resize(index); 00391 } 00392 00393 void CPPParser::enumElement(const std::string& e, bool has_value, int value) 00394 { } 00395 00396 void CPPParser::beginEnumDefinition(const std::string& e) 00397 {// DW 26/3/97 Set flag for new class 00398 00399 // add all enum tags into the global scope (not correct, but 00400 // will work for most code). 00401 // This symbol lives until the end of the file 00402 CPPSymbol *c = new CPPSymbol(e, CPPSymbol::otEnum); 00403 symbols->defineInScope(e, c, externalScope); 00404 } 00405 00406 void CPPParser::endEnumDefinition() { } 00407 00408 void CPPParser::foundSimpleType(const std::list<std::string>& full_type) { } 00409 00410 void CPPParser::end_of_stmt() { } 00411 00412